Angenommen, das Remote-Repository verfügt über eine Kopie des Entwicklungszweigs (Ihre ursprüngliche Beschreibung beschreibt sie in einem lokalen Repository, es scheint jedoch auch in der Remote vorhanden zu sein), sollten Sie in der Lage sein, das zu erreichen, was ich denke, aber den Ansatz ist ein bisschen anders als Sie es sich vorgestellt haben.
Die Geschichte von Git basiert auf einer DAG von Commits. Zweige (und „Refs“ im Allgemeinen) sind nur vorübergehende Bezeichnungen, die auf bestimmte Commits in der kontinuierlich wachsenden Commit-DAG verweisen. Daher kann die Beziehung zwischen Zweigen im Laufe der Zeit variieren, die Beziehung zwischen Commits jedoch nicht.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Es sieht so aus, als ob baz
es auf (einer alten Version von) basiert bar
? Aber was ist, wenn wir löschen bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Jetzt sieht es so aus, als ob baz
es auf basiert foo
. Aber die Abstammung von baz
hat sich nicht geändert, wir haben nur ein Etikett entfernt (und das daraus resultierende baumelnde Commit). Und was ist, wenn wir bei ein neues Label hinzufügen 4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Jetzt sieht es so aus, als ob baz
es auf basiert quux
. Die Abstammung änderte sich jedoch nicht, nur die Beschriftungen änderten sich.
Wenn wir jedoch fragten: "Ist Commit 6
ein Nachkomme von Commit 3
?" (vorausgesetzt , 3
und 6
sind voll SHA-1 Namen begehen), dann wäre die Antwort „ja“ lautet, ob die bar
und quux
Etiketten vorhanden sind oder nicht.
Sie könnten also Fragen stellen wie "Ist das Push-Commit ein Nachkomme der aktuellen Spitze des Entwicklungszweigs ?", Aber Sie können nicht zuverlässig fragen: "Was ist der übergeordnete Zweig des Push-Commits?".
Eine meist verlässliche Frage, die sich Ihren Wünschen zu nähern scheint, lautet:
Für alle Vorfahren des Push-Commits (mit Ausnahme des aktuellen Entwicklungstipps und seiner Vorfahren), die den aktuellen Entwicklungstipp als übergeordnetes Element haben:
- Gibt es mindestens ein solches Commit?
- Sind alle diese Commits Single-Parent-Commits?
Welches könnte implementiert werden als:
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_children_of_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
,) echo "must descend from tip of '$basename'"
exit 1 ;;
,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
exit 1 ;;
,*) exit 0 ;;
esac
Dies wird einige der von Ihnen gewünschten Einschränkungen abdecken, aber möglicherweise nicht alles.
Als Referenz finden Sie hier eine erweiterte Beispielhistorie:
A master
\
\ o-----J
\ / \
\ | o---K---L
\ |/
C--------------D develop
\ |\
F---G---H | F'--G'--H'
| |\
| | o---o---o---N
\ \ \ \
\ \ o---o---P
\ \
R---S
Der obige Code kann verwendet werden , um abzulehnen H
und S
während der Annahme H'
, J
, K
, oder N
, aber es wäre auch zu akzeptieren , L
und P
(sie beinhalten verschmilzt, aber sie verschmelzen nicht mit der Spitze entwickeln ).
Um auch L
und abzulehnen P
, können Sie die Frage ändern und stellen
Für alle Vorfahren des Push-Commits (mit Ausnahme des aktuellen Entwicklertipps und seiner Vorfahren):
- Gibt es irgendwelche Verpflichtungen mit zwei Eltern?
- Wenn nicht, hat mindestens ein solches Commit den aktuellen Tipp , sein (einziges) Elternteil zu entwickeln?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_commits_beyond_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
*\ *) echo "must not push merge commits (rebase instead)"
exit 1 ;;
*"$baserev"*) exit 0 ;;
*) echo "must descend from tip of '$basename'"
exit 1 ;;
esac