Angenommen, das entfernte Repository hat eine Kopie der entwickeln. Zweig (Ihre anfängliche Beschreibung beschreibt ihn in einem lokalen Repository, aber es klingt so, als ob er auch im entfernten Repository existiert), sollten Sie in der Lage sein, das zu erreichen, was ich denke, dass Sie wollen, aber der Ansatz ist ein bisschen anders als das, was Sie sich vorgestellt haben.
Die Geschichte von Git basiert auf einer DAG von Übertragungen. Branches (und "Refs" im Allgemeinen) sind nur flüchtige Markierungen, die auf bestimmte Commits in der ständig wachsenden Commit-DAG verweisen. Daher kann sich die Beziehung zwischen Zweigen im Laufe der Zeit ändern, nicht aber die Beziehung zwischen Commits.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Es sieht so aus baz
basiert auf (einer alten Version von) bar
? Aber was, wenn wir löschen bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Jetzt sieht es so aus baz
stützt sich auf foo
. Aber die Abstammung von baz
hat sich nicht geändert. Wir haben lediglich ein Etikett (und die daraus resultierende hängende Übergabe) entfernt. Und was ist, wenn wir ein neues Label hinzufügen bei 4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Jetzt sieht es so aus baz
stützt sich auf quux
. Doch die Abstammung hat sich nicht geändert, nur die Bezeichnungen haben sich geändert.
Wenn wir jedoch die Frage stellen würden: "Ist Commit 6
ein Nachkomme von commit 3
?" (unter der Annahme, dass 3
et 6
vollständige SHA-1 Commit-Namen sind), dann wäre die Antwort "ja", egal ob die bar
et quux
Etiketten vorhanden sind oder nicht.
Man könnte also Fragen stellen wie "ist die geschobene Übergabe ein Nachkomme der aktuellen Spitze der entwickeln. Zweig?", aber Sie können nicht zuverlässig fragen: "Was ist der übergeordnete Zweig der gepushten Übertragung?".
Eine meist zuverlässige Frage, die dem Gewünschten nahe zu kommen scheint, ist die folgende:
Für alle Vorgänger der gepushten Übertragung (mit Ausnahme der aktuellen Spitze von entwickeln. und seine Vorfahren), die die aktuelle Spitze von entwickeln. als Elternteil:
- gibt es mindestens eine solche Verpflichtung?
- Sind alle diese Commits Single-Eltern-Commits?
Dies könnte wie folgt umgesetzt werden:
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 einiges von dem abdecken, was Sie eingeschränkt haben möchten, aber vielleicht nicht alles.
Als Referenz finden Sie hier ein ausführliches Beispiel:
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 könnte verwendet werden, um Folgendes abzulehnen H
et S
bei Annahme H'
, J
, K
ou N
aber sie würde auch akzeptieren L
et P
(sie beinhalten Verschmelzungen, aber sie verschmelzen nicht die Spitze der entwickeln. ).
Auch zurückweisen L
et P
können Sie die Frage ändern und fragen
Für alle Vorgänger der gepushten Übergabe (außer der aktuellen Spitze von entwickeln. und seine Vorfahren):
- Gibt es Pendler mit zwei Elternteilen?
- wenn nicht, hat mindestens eine dieser Übertragungen die aktuelle Spitze von entwickeln. sein (einziges) Elternteil?
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