Biorąc pod uwagę identyfikator zatwierdzenia, jak określić, czy bieżąca gałąź zawiera zatwierdzenie?

156

To, co próbuję zrobić, to sprawdzenie wersji. Chcę się upewnić, że kod pozostaje na szczycie wersji minimalnej. Potrzebuję więc sposobu, aby wiedzieć, czy bieżąca gałąź zawiera określone zatwierdzenie.

TieDad
źródło
10
Zobacz proponowany duplikat, aby dowiedzieć się, jak znaleźć wszystkie gałęzie zawierające określone zatwierdzenie. Aby dowiedzieć się, czy bieżąca gałąź zawiera zatwierdzenie C , użyj polecenia „plumbing” git merge-base --is-ancestor. Bieżąca gałąź zawiera C, jeśli C jest przodkiem HEAD, więc: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
Cześć, prześlij to jako odpowiedź, aby można ją było wybrać jako prawidłową odpowiedź =)
Ben
1
@Ben - dodałem go jako odpowiedź wiki społeczności.
Zitrax
1
@Remover: w skryptach powłoki zero jest prawdą, wartość niezerowa jest fałszem: odwrotność konwencji C. /bin/truezostał pierwotnie zaimplementowany jako exit 0i /bin/falsejako exit 1. (Współczesne pociski miały wtedy wbudowane.)
torek

Odpowiedzi:

220

Istnieje wiele sposobów osiągnięcia tego wyniku. Pierwszą naiwną opcją jest użycie git logi wyszukanie określonego zatwierdzenia za pomocą grep, ale nie zawsze jest to dokładne

git log | grep <commit_id>

Lepiej jest użyć git branchbezpośrednio, aby znaleźć wszystkie gałęzie zawierające podane COMMIT_IDużycie

git branch --contains $COMMIT_ID

Następnym krokiem jest ustalenie bieżącej gałęzi, którą można zrobić od czasu git 1.8.1użycia

git symbolic-ref --short HEAD

I połączone razem jako

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

Ale powyższe polecenie nie zwraca prawdy ani fałszu i istnieje krótsza wersja, która zwraca kod zakończenia 0, jeśli zatwierdzenie znajduje się w bieżącej gałęzi LUB kod zakończenia 1, jeśli nie

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

Kod zakończenia jest fajny, ale jeśli chcesz napisać truelub falsejako odpowiedź, musisz dodać trochę więcej, a następnie połączyć z ifz basha.

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
JiriS
źródło
9
To nie jest poprawne; grepmoże spowodować fałszywie dodatnich jeśli git logwspomina commit SHA z innych powodów, np to wspomniano w commit wiadomość w wyniku port z innego oddziału.
Adam Spiers
1
Poprawiono (a raczej dodano inną opcję).
JiriS
3
Zobacz komentarz do pytania, który korzysta z wbudowanego zestawu narzędzi git. stackoverflow.com/questions/43535132/…
Ben
2
Podoba mi się pierwsza opcja, ale żeby wykluczyć sprzeciw Adama, dodałbym opcję --format=format:%Hdo git log.
PJSCopeland
71

Uzyskaj listę gałęzi, które zawierają określone zatwierdzenie.

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

Sprawdź, czy gałąź ma określone zatwierdzenie.

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

Wyszukaj gałąź (powiedzmy feature) z dokładnym dopasowaniem .

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

np Jeśli masz 3 lokalne oddziały zwane feature, feature1, feature2następnie

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

# output
feature
feature1
feature2

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

# output
feature     

Można też szukać w obu locali remoteoddziałów (zastosowanie -a) lub tylko w remotegałęzi (wykorzystania -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
źródło
1
grepTutaj może również powodować fałszywych alarmów, jeśli istnieją inne gałęzie zawierające popełnić których nazwy zawierają również <branch-name>jako podciąg.
Adam Spiers
1
Tak @AdamSpiers, zaktualizowałem odpowiedź, podając dokładne dopasowanie nazwy oddziału przezgrep -E '(^|\s)branchname$'
Sajib Khan.
1
Zgodnie z tym komentarzem do pokrewnego pytania przydatne może być dodanie opcji -r(„zdalne”) lub -a(„wszystkie”) w git branchcelu wyszukania gałęzi, które mogą nie być replikowane w lokalnym klonie repozytorium.
sxc731
To nie zadziałało dla mnie, potrzebowałem git branch --all --contains <commit-id>
Arthur Tacca
7

Wyodrębniony komentarz @torek jako odpowiedź:

Zobacz proponowany duplikat, aby dowiedzieć się, jak znaleźć wszystkie gałęzie zawierające określone zatwierdzenie.

Aby dowiedzieć się, czy bieżąca gałąź zawiera zatwierdzenie C, użyj polecenia „plumbing” git merge-base --is-ancestor. Bieżąca gałąź zawiera C, jeśli C jest przodkiem HEAD, więc:

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

(Na marginesie: w skryptach powłoki polecenie, które wychodzi z zera, jest „prawdziwe”, a wyjście niezerowe jest „fałszywe”).

torek
źródło
4

Aby wyświetlić lokalne gałęzie zawierające zatwierdzenie:

git branch --contains <commit-id>

i wymienić wszystkie gałęzie, w tym tylko zdalne, zawierające zatwierdzenie:

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

Podobnie, aby sprawdzić, czy zatwierdzenie znajduje się w konkretnej gałęzi:

git log <branch> | grep <commit_id>

a jeśli gałąź nie istnieje lokalnie, przedrostek nazwy gałęzi z origin/

hgrey
źródło
Zagłosowano za uwagą w sprawie -a. Dzięki za radę!
Thorkil Værge
3

Tak, inna alternatywa:

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

To działa najlepiej dla mnie, ponieważ działałoby również na zdalnych gałęziach buforowanych lokalnie, takich jak remotes/origin/master, na których git branch --containsnie będzie działać.

Obejmuje to więcej niż pytanie OP dotyczące tylko "bieżącej gałęzi", ale uważam, że głupio jest zadawać "dowolną gałąź" tego pytania, więc i tak zdecydowałem się opublikować tutaj.

logicor
źródło
1
git branch --contains <commit-id> --points-at <target branch name>

Zwróci nazwę gałęzi docelowej, jeśli identyfikator zatwierdzenia istnieje w tej gałęzi. W przeciwnym razie polecenie zakończy się niepowodzeniem.

DreamUth
źródło
nie ...error: malformed object name 'branch-name'
bbodenmiller
1
Możesz otrzymać ten błąd w 2 przypadkach 1. Kiedy podana <nazwa oddziału> nie zawiera podanego <ID zatwierdzenia> 2. Do kasy <nazwa oddziału> nie jest podana <nazwa oddziału>
DreamUth
0

Ponieważ to pytanie ma kilka fajnych odpowiedzi skryptowych, dodaję moje ulubione.

Ten pokaże ci, dla ostatnich $nzatwierdzeń, w $brktórych gałęziach znajdują się:

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

Ten jest podobny, ale robi to samo dla listy oddziałów:

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
źródło