
Peter Bauer
Nehmen wir an, ich habe das folgende lokale Repository mit einem Commit-Baum wie diesem:
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
ist mein Dies ist der neueste stabile Release-Code, develop
ist mein dies ist der ‘nächste’ Freigabecodeund feature
ist eine neue Funktion in Vorbereitung develop
.
Mit Hooks möchte ich Pushes ablehnen können feature
zu meinem Remote-Repository, es sei denn, es wird festgeschrieben f
ist ein direkter Nachkomme von develop
KOPF. Dh der Commit-Baum sieht so aus, weil Feature wurde git rebase
an d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
Ist es also möglich:
- Identifizieren Sie den übergeordneten Zweig von
feature
?
- Identifizieren Sie das Commit im übergeordneten Zweig which
f
ist ein Nachkomme von?
Von dort aus würde ich überprüfen, was HEAD des übergeordneten Zweigs ist, und sehen, ob f
Vorgänger stimmt mit HEAD des übergeordneten Zweigs überein, um zu bestimmen, ob das Feature rebasiert werden muss.

Chris Johnsen
Angenommen, das Remote-Repository verfügt über eine Kopie der entwickeln branch (Ihre anfängliche Beschreibung beschreibt es in einem lokalen Repository, aber es hört sich so an, als ob es auch in einem entfernten Repository existiert), sollten Sie in der Lage sein, das zu erreichen, was Sie meiner Meinung nach wollen, aber der Ansatz unterscheidet sich etwas von dem, was Sie sich vorgestellt haben.
Die Geschichte von Git basiert auf a DAG von Commits. Branches (und „refs“ im Allgemeinen) sind nur vorübergehende Bezeichnungen, die auf bestimmte Commits im kontinuierlich wachsenden Commit-DAG verweisen. Daher kann sich die Beziehung zwischen Zweigen im Laufe der Zeit ändern, die Beziehung zwischen Commits jedoch nicht.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Es sieht aus wie baz
basiert auf (einer alten Version von) bar
? Aber was ist, wenn wir löschen bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Jetzt sieht es so aus baz
basiert auf foo
. Aber die Abstammung von baz
änderte sich nicht. Wir haben gerade ein Label entfernt (und den daraus resultierenden Dangling Commit). Und was ist, wenn wir unter ein neues Label hinzufügen? 4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Jetzt sieht es so aus baz
basiert auf quux
. Die Abstammung änderte sich jedoch nicht, nur die Etiketten änderten sich.
Wenn wir jedoch fragten: „ist begangen 6
ein Nachkomme von Commit 3
?” (vorausgesetzt 3
und 6
vollständige SHA-1-Commit-Namen sind), dann wäre die Antwort „ja“, ob die bar
und quux
Etiketten vorhanden sind oder nicht.
Sie könnten also Fragen stellen wie „Ist der gepushte Commit ein Nachkomme des aktuellen Tipp der entwickeln branch?”, aber Sie können nicht zuverlässig fragen: “Was ist der übergeordnete Branch des gepushten Commits?”.
Eine meist zuverlässige Frage, die dem, was Sie wollen, nahe zu kommen scheint, ist:
Für alle Vorfahren des gepushten Commits (mit Ausnahme der aktuellen Spitze von entwickeln und seine Vorfahren), die die aktuelle Spitze haben entwickeln als Elternteil:
- Gibt es mindestens ein solches Commit?
- Sind alle diese Commits Single-Eltern-Commits?
Was umgesetzt werden könnte 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 einiges von dem abdecken, was Sie einschränken möchten, aber vielleicht 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 könnte zum Ablehnen verwendet werden H
und S
beim Akzeptieren H'
, J
, K
oder N
würde es aber auch akzeptieren L
und P
(Sie beinhalten Zusammenführungen, aber sie führen nicht die Spitze von zusammen entwickeln).
Auch abzulehnen L
und P
Sie können die Frage ändern und stellen
Für alle Vorfahren des gepushten Commits (mit Ausnahme der aktuellen Spitze von entwickeln und seine Vorfahren):
- Gibt es Verpflichtungen mit zwei Elternteilen?
- Wenn nicht, hat mindestens ein solcher Commit den aktuellen Tipp von entwickeln sein (einziger) 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

Joe Chrysler
Eine Umschreibung
Eine andere Möglichkeit, die Frage zu formulieren, lautet: “Was ist das nächste Commit, das sich auf einem anderen Zweig als dem aktuellen Zweig befindet, und welcher Zweig ist das?”
Eine Lösung
Sie können es mit ein wenig Kommandozeilen-Magie finden
git show-branch \ | sed "s/].*//" \ | grep "\*" \ | grep -v "$(git rev-parse --abbrev-ref HEAD)" \ | Kopf -n1 \ | sed "s/^.*\[//"
With AWK:
git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \ | awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'
So funktioniert das:
- Zeigen Sie einen Textverlauf aller Commits an, einschließlich Remote-Branches.
- Ancestors des aktuellen Commits sind durch einen Stern gekennzeichnet. Alles andere herausfiltern.
- Ignorieren Sie alle Commits im aktuellen Zweig.
- Das erste Ergebnis ist der nächste Vorfahrenzweig. Ignorieren Sie die anderen Ergebnisse.
- Filialnamen werden angezeigt [in brackets]. Ignoriere alles außerhalb der Klammern und die Klammern.
- Manchmal enthält der Zweigname a
~#
oder ^#
um anzugeben, wie viele Commits zwischen dem referenzierten Commit und der Verzweigungsspitze liegen. Es ist uns egal. Ignoriere sie.
Und das Ergebnis
Führen Sie den obigen Code aus
A---B---D <-master
\
\
C---E---I <-develop
\
\
F---G---H <-topic
Werde dir geben develop
wenn Sie es von H ausführen und master
wenn Sie es von I ausführen.
Der Code ist als Gist verfügbar.

Nikhil CM
Git-Elternteil
Sie können den Befehl einfach ausführen
git parent
um das übergeordnete Element des Zweigs zu finden, wenn Sie die Antwort von Joe Chrysler als a hinzufügen Git-Alias. Es wird die Verwendung vereinfachen.
Öffne das gitconfig Datei befindet sich unter "~/.gitconfig"
mit einem beliebigen Texteditor (für Linux). Und für Windows befindet sich der Pfad “.gitconfig” im Allgemeinen unter C:\users\your-user\.gitconfig
.
vim ~/.gitconfig
Fügen Sie den folgenden Alias-Befehl in der Datei hinzu:
[alias]
parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"
Speichern und beenden Sie den Editor.
Führen Sie den Befehl aus git parent
.
Das ist es!

rcde0
Sie können auch versuchen:
git log --graph --decorate
Ich habe eine Lösung für Ihr Gesamtproblem (bestimmen Sie, ob feature
stammt von der Spitze ab develop
), aber es funktioniert nicht mit der von Ihnen beschriebenen Methode.
Sie können verwenden git branch --contains
um alle Zweige aufzulisten, die von der Spitze abstammen develop
dann benutze grep
sichergehen feature
ist unter ihnen.
git branch --contains develop | grep "^ *feature$"
Wenn es darunter ist, wird es gedruckt " feature"
auf die Standardausgabe und haben einen Rückgabecode von 0. Andernfalls wird nichts gedruckt und der Rückgabecode ist 1.

Peter Mortensen
Das funktioniert gut für mich:
git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
Höflichkeitskommentar und Antworten von droidbot und @Jistanidiot.

Matt Stuvysant
Eine Lösung
Die Lösung basiert auf git show-branch
hat bei mir nicht ganz funktioniert (siehe unten), also habe ich es mit dem basierend auf kombiniert git log
und endete damit:
git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
| grep -v "(HEAD" \ # removes current head (and branch)
| head -n1 \ # selects only the closest decoration
| sed 's/.* (\(.*\)) .*/\1/' \ # filters out everything but decorations
| sed 's/\(.*\), .*/\1/' \ # picks only the first decoration
| sed 's/origin\///' # strips "origin/" from the decoration
Einschränkungen und Vorbehalte
- HEAD kann getrennt werden (viele CI-Tools tun dies, um sicherzustellen, dass sie den richtigen Commit in einem bestimmten Zweig erstellen), aber Ursprungsniederlassung und Ortsniederlassung müssen beides sein gleich oder “über” der aktuelle KOPF.
- Da muss sein keine Tags im Weg (ich nehme an; ich habe das Skript nicht auf Commits mit einem Tag zwischen untergeordnetem und übergeordnetem Zweig getestet)
- das Drehbuch stützt sich auf die Tatsache “KOPF” ist immer als erste Dekoration aufgeführt bis zum
log
Befehl
- Laufen das Skript an
master
und develop
resultiert (meistens) in <SHA> Initial commit
Die Ergebnisse
A---B---D---E---F <-origin/master, master
\ \
\ \
\ G---H---I <- origin/hotfix, hotfix
\
\
J---K---L <-origin/develop, develop
\
\
M---N---O <-origin/feature/a, feature/a
\ \
\ \
\ P---Q---R <-origin/feature/b, feature/b
\
\
S---T---U <-origin/feature/c, feature/c
Trotz lokaler Filialexistenz (zB nur origin/topic
ist seit dem Commit vorhanden O
direkt von seinem SHA ausgecheckt wurde), sollte das Skript wie folgt ausgeben:
- Für Zusagen
G
, H
, I
(sich verzeigen hotfix
) → master
- Für Zusagen
M
, N
, O
(sich verzeigen feature/a
) → develop
- Für Zusagen
S
, T
, U
(sich verzeigen feature/c
) → develop
- Für Zusagen
P
, Q
, R
(sich verzeigen feature/b
) → feature/a
- Für Zusagen
J
, K
, L
(sich verzeigen develop
) → <sha> Initial commit
*
- Für Zusagen
B
, D
, E
, F
(sich verzeigen master
) → <sha> Initial commit
* – oder master
wenn develop
Die Commits von lagen über dem HEAD des Masters (~ der Master wäre für die Entwicklung schnell vorspulbar)
Warum hat Show-Zweig für mich nicht funktioniert
Die Lösung basiert auf git show-branch
hat sich für mich in folgenden Situationen als unzuverlässig erwiesen:
- abgetrennter KOPF – einschließlich abgenommenem Kopfgehäuse bedeutet Austausch
grep '\*' \
für `grep ‘!’ \ – und das ist erst der Anfang aller Probleme
- Laufen das Skript an
master
und develop
ergibt sich develop
bzw. “
- Zweige an
master
sich verzeigen (hotfix/
Zweige) enden mit der develop
als Eltern seit ihrer engsten master
Branch Parent wurde mit markiert !
anstatt *
aus einem Grund.
9857300cookie-checkSo finden Sie das nächste übergeordnete Element eines Git-Zweigsyes
Diese Frage sollte umformuliert werden, um den Elternteil eines Elternteils zu finden.
– Tim Boland
3. Mai 2018 um 17:11 Uhr
Im Allgemeinen verwende ich
git log --first-parent
es werden alle Commits aus dem aktuellen Zweig angezeigt, danach werden der übergeordnete Zweig und seine Commits angezeigt– Vipul Patil
6. Oktober 2021 um 10:18 Uhr