Wie kann anhand einer Commit-ID festgestellt werden, ob der aktuelle Zweig das Commit enthält?

154

Ich versuche eine Versionsprüfung. Ich möchte sicherstellen, dass der Code auf einer Mindestversion bleibt. Ich muss also wissen, ob der aktuelle Zweig ein bestimmtes Commit enthält.

TieDad
quelle
10
Im vorgeschlagenen Duplikat finden Sie Informationen zum Auffinden aller Zweige, die ein bestimmtes Commit enthalten. Verwenden Sie den Befehl "plumbing", um herauszufinden, ob der aktuelle Zweig Commit C enthält git merge-base --is-ancestor. Der aktuelle Zweig enthält C, wenn C ein Vorfahr von ist HEAD, also:if git merge-base --is-ancestor $hash HEAD; then echo I contain commit $hash; else echo I do not contain commit $hash; fi
torek
1
Hallo, bitte senden Sie dies als Antwort, damit es als die richtige Antwort ausgewählt werden kann =)
Ben
1
@ Ben - Ich habe es als Community-Wiki-Antwort hinzugefügt.
Zitrax
1
@ Remover: In Shell-Skripten ist Null wahr, ungleich Null ist falsch: die Umkehrung der C-Konvention. /bin/truewurde ursprünglich als exit 0und /bin/falseals implementiert exit 1. (Moderne Muscheln haben dann eingebaut.)
Torek

Antworten:

216

Es gibt mehrere Möglichkeiten, um dieses Ergebnis zu erzielen. Die erste naive Option besteht darin, git logein bestimmtes Commit zu verwenden und danach zu suchen grep, aber das ist nicht immer genau

git log | grep <commit_id>

Es ist besser, git branchdirekt zu verwenden, um alle Zweige zu finden, die gegebenes COMMIT_IDVerwenden enthalten

git branch --contains $COMMIT_ID

Der nächste Schritt besteht darin, den aktuellen Zweig herauszufinden, der seit der git 1.8.1Verwendung durchgeführt werden kann

git symbolic-ref --short HEAD

Und kombiniert als

git branch $(git symbolic-ref --short HEAD) --contains $COMMIT_ID

Der obige Befehl gibt jedoch weder true noch false zurück, und es gibt eine kürzere Version, die den Exit-Code 0 zurückgibt, wenn sich das Commit im aktuellen Zweig befindet, oder den Exit-Code 1, wenn nicht

git merge-base --is-ancestor $COMMIT_ID HEAD

Exit-Code ist nett, aber wenn Sie einen String trueoder falseeine Antwort wünschen , müssen Sie etwas mehr hinzufügen und dann mit ifBash kombinieren

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
JiriS
quelle
9
Das ist nicht richtig; das grepkönnte in Fehlalarme führen , wenn git logerwähnt der SHA aus anderen Gründen begehen, zum Beispiel in einem Commit als Ergebnis eines Hafens von einem anderen Zweig Nachricht erwähnt wird .
Adam Spires
1
Korrigiert (oder vielmehr eine andere Option hinzugefügt).
JiriS
3
Bitte lesen Sie den Kommentar zu der Frage, die das integrierte Git-Toolset verwendet. stackoverflow.com/questions/43535132/…
Ben
2
Ich mag die erste Option, aber aus Adams Einwand gegen Regel, würde ich die Option hinzufügen --format=format:%Hzu git log.
PJSCopeland
71

Rufen Sie eine Liste der Zweige ab, die das spezifische Commit enthalten.

# get all the branches where the commit exists
$ git branch --contains <commit-id>

Überprüfen Sie, ob ein Zweig das spezifische Commit hat.

# output the branch-name if the commit exists in that branch
$ git branch --contains <commit-id> | grep <branch-name>

Durchsuchen Sie den Zweig (z. B. feature) mit exakter Übereinstimmung .

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

zB Wenn Sie 3 lokale Filialen angerufen featurehaben feature1, feature2dann

$ git branch --contains <commit-id> | grep 'feature'

# output
feature
feature1
feature2

$ git branch --contains <commit-id> | grep -E '(^|\s)feature$'

# output
feature     

Sie können auch in Such- localund remoteZweigen (Verwendung -a) oder nur in remoteFilialen (Verwendung -r).

# search in both 'local' & 'remote' branches  
$ git branch -a --contains <commit-id> | grep -E '(^|\s)feature$'

# search in 'remote' branches  
$ git branch -r --contains <commit-id> | grep -E '(^|\s)feature$'
Sajib Khan
quelle
1
Das grephier kann auch zu Fehlalarmen führen, wenn andere Zweige das Commit enthalten, deren Namen ebenfalls <branch-name>als Teilzeichenfolge enthalten sind.
Adam Spires
1
Ja @AdamSpiers, Aktualisierte die Antwort mit exakt übereinstimmendem grep -E '(^|\s)branchname$'
Filialnamen
1
Gemäß diesem Kommentar zu der zugehörigen Frage kann es nützlich sein, die Option -r("remote") oder -a("all") hinzuzufügen git branch, um nach Zweigen zu suchen, die möglicherweise nicht im lokalen Repo-Klon repliziert werden.
sxc731
Das hat bei mir nicht funktioniert, ich brauchte git branch --all --contains <commit-id>
Arthur Tacca
7

Extrahierter Kommentar von @torek als Antwort:

Im vorgeschlagenen Duplikat finden Sie Informationen zum Auffinden aller Zweige, die ein bestimmtes Commit enthalten.

Verwenden Sie den Befehl "plumbing", um herauszufinden, ob der aktuelle Zweig Commit C enthält git merge-base --is-ancestor. Der aktuelle Zweig enthält C, wenn C ein Vorfahr von HEAD ist.

if git merge-base --is-ancestor $hash HEAD; then
    echo I contain commit $hash
else
    echo I do not contain commit $hash
fi

(Randnotiz: In Shell-Skripten ist ein Befehl, der Null beendet, "wahr", während ein Befehl, der ungleich Null beendet wird, "falsch" ist.)

torek
quelle
4

So listen Sie lokale Zweige mit Commit auf:

git branch --contains <commit-id>

und um alle Zweige aufzulisten, einschließlich nur Remote, die Commit enthalten:

git branch -a --contains <commit-id>

Um zu überprüfen, ob sich das Commit in einem bestimmten Zweig befindet:

git log <branch> | grep <commit_id>

und wenn die Verzweigung nicht lokal vorhanden ist, stellen Sie den Verzweigungsnamen vor origin/

hgrey
quelle
Für die Bemerkung am gestimmt -a. Danke für diesen Rat!
Thorkil Værge
3

Ja, eine andere Alternative:

git rev-list <branch name> | grep `git rev-parse <commit>`

Dies funktioniert am besten für mich, da es auch auf lokal zwischengespeicherten Remote-Zweigen wie z. B. funktioniert remotes/origin/master, auf denen dies git branch --containsnicht funktioniert.

Dies deckt mehr als die Frage von OP zu "aktuellem Zweig" ab, aber ich finde es dumm, eine "beliebige Zweig" -Version dieser Frage zu stellen, also entscheide ich mich trotzdem, hier zu posten.

Logik oder
quelle
1
git branch --contains <commit-id> --points-at <target branch name>

Der Name des Zielzweigs wird zurückgegeben, wenn die Festschreibungs-ID in diesem Zweig vorhanden ist. Andernfalls schlägt der Befehl fehl.

DreamUth
quelle
nein ...error: malformed object name 'branch-name'
bbodenmiller
1
Dieser Fehler kann in zwei Fällen auftreten: 1. Wenn der angegebene <Zweigname> nicht die angegebene <Commit-ID> enthält. 2. Die Kasse <
Zweigname
0

Da diese Frage einige nette Antworten enthält, füge ich meine Favoriten hinzu.

Dieser zeigt Ihnen für die letzten $nCommits, in $brdenen Zweige jeweils enthalten:

br=mybranch
n=10
git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'

Dieser ist ähnlich, macht aber dasselbe für eine Liste von Zweigen:

br="mybranch yourbranch herbranch"
n=4
for br in $brs; do git log --oneline -n$n $br | awk '{print; system("git branch --contains "$1)}'; done
Bruno Bronosky
quelle