Diberi id komit, bagaimana cara menentukan jika cabang saat ini berisi komit?

156

Apa yang saya coba lakukan adalah pemeriksaan versi. Saya ingin memastikan kode tetap di atas versi minimum. Jadi saya perlu cara untuk mengetahui apakah cabang saat ini berisi komit yang ditentukan.

TieDad
sumber
10
Lihat duplikat yang diajukan untuk cara menemukan semua cabang yang berisi komit yang ditentukan. Untuk mengetahui apakah cabang saat ini berisi komit C , gunakan perintah "plumbing" git merge-base --is-ancestor. Cabang saat ini berisi C jika C adalah leluhur HEAD, jadi: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
Hai, tolong kirimkan ini sebagai jawaban sehingga dapat dipilih sebagai jawaban yang benar =)
Ben
1
@ Ben - Saya menambahkannya sebagai jawaban wiki komunitas.
Zitrax
1
@Remover: dalam skrip shell, nol benar, bukan nol salah: kebalikan dari konvensi C. /bin/trueawalnya diimplementasikan sebagai exit 0dan /bin/falsesebagai exit 1. (Kerang modern kemudian dibangun di.)
torek

Jawaban:

220

Ada beberapa cara untuk mencapai hasil ini. Opsi naif pertama adalah menggunakan git logdan mencari komit tertentu menggunakan grep, tetapi itu tidak selalu tepat

git log | grep <commit_id>

Anda lebih baik menggunakan git branchsecara langsung untuk menemukan semua cabang yang mengandung diberikan COMMIT_IDmenggunakan

git branch --contains $COMMIT_ID

Langkah selanjutnya adalah mencari cabang saat ini yang dapat dilakukan sejak git 1.8.1menggunakan

git symbolic-ref --short HEAD

Dan digabungkan bersama sebagai

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

Tetapi perintah di atas tidak mengembalikan benar atau salah dan ada versi yang lebih pendek yang mengembalikan kode keluar 0 jika komit di cabang saat ini ATAU kode keluar 1 jika tidak

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

Kode keluar memang bagus, tetapi seperti yang Anda inginkan string trueatau falsesebagai jawaban, Anda perlu menambahkan sedikit lebih banyak dan kemudian dikombinasikan dengan ifdari bash Anda dapatkan

if [ 0 -eq $(git merge-base --is-ancestor $COMMIT_ID HEAD) ]; then echo "true"; else echo "false"; fi
Jiri
sumber
9
Itu tidak benar; hal ini grepdapat menghasilkan false positive jika git logmenyebutkan commit SHA karena alasan lain, misalnya disebutkan dalam pesan commit sebagai hasil dari port dari cabang lain.
Adam Spires
1
Dikoreksi (atau lebih tepatnya menambahkan opsi lain).
JiriS
3
Silakan lihat komentar pada pertanyaan, yang menggunakan git toolset bawaan. stackoverflow.com/questions/43535132/…
Ben
2
Aku seperti pilihan pertama, tetapi untuk mengesampingkan keberatan Adam, saya akan menambahkan pilihan --format=format:%Huntuk git log.
PJSCopeland
71

Dapatkan daftar cabang yang berisi komit spesifik.

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

Periksa apakah cabang memiliki komit tertentu.

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

Cari cabang (katakanlah, feature) dengan pencocokan tepat .

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

misalnya Jika Anda memiliki 3 cabang lokal disebut feature, feature1, feature2maka

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

# output
feature
feature1
feature2

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

# output
feature     

Anda juga dapat mencari di kedua localdan remotecabang (gunakan -a) atau hanya di remotecabang (gunakan -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
sumber
1
Di grepsini juga bisa menghasilkan false positive jika ada cabang lain yang mengandung komit yang namanya juga mengandung <branch-name>sebagai substring.
Adam Spires
1
Ya @AdamSpiers, Memperbarui jawabannya dengan persis sama dengan nama cabang olehgrep -E '(^|\s)branchname$'
Sajib Khan
1
Per komentar ini pada pertanyaan terkait , akan bermanfaat untuk menambahkan opsi -r("jarak jauh") atau -a("semua") git branchuntuk mencari cabang yang mungkin tidak direplikasi dalam klon repo lokal.
sxc731
Ini tidak bekerja untuk saya, saya butuhkan git branch --all --contains <commit-id>
Arthur Tacca
7

Diekstraksi komentar oleh @torek sebagai jawaban:

Lihat duplikat yang diajukan untuk cara menemukan semua cabang yang berisi komit yang ditentukan.

Untuk mengetahui apakah cabang saat ini berisi komit C, gunakan perintah "plumbing" git merge-base --is-ancestor. Cabang saat ini berisi C jika C adalah leluhur HEAD, jadi:

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

(Catatan: dalam skrip shell, perintah yang keluar nol adalah "benar" sedangkan yang keluar bukan nol adalah "salah".)

torek
sumber
4

Untuk membuat daftar cabang lokal yang mengandung komit:

git branch --contains <commit-id>

dan untuk mencantumkan semua cabang, termasuk hanya jarak jauh, yang mengandung komit:

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

Demikian pula untuk memeriksa apakah komit ada di cabang tertentu:

git log <branch> | grep <commit_id>

dan jika cabang tidak ada, awali nama cabang dengan origin/

hgrey
sumber
Terpilih untuk komentar pada -a. Terima kasih atas sarannya!
Thorkil Værge
3

Ya alternatif lain:

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

Ini bekerja paling baik untuk saya karena itu juga akan bekerja pada cabang-cabang terpencil yang di-cache secara lokal seperti remotes/origin/master, yang git branch --containstidak akan bekerja.

Ini mencakup lebih dari pertanyaan OP tentang hanya "cabang saat ini" tetapi saya merasa bodoh untuk menanyakan versi "cabang apa pun" dari pertanyaan ini jadi saya memutuskan untuk tetap mengirim di sini.

logika atau
sumber
1
git branch --contains <commit-id> --points-at <target branch name>

Ini akan mengembalikan nama cabang target jika ada komit di cabang itu. Kalau tidak, perintah akan gagal.

Impian
sumber
tidak ...error: malformed object name 'branch-name'
bbodenmiller
1
Anda mungkin mendapatkan kesalahan itu dalam 2 kasus 1. Ketika <branch name> yang diberikan tidak mengandung <commit id> yang diberikan 2. 2. checkout <branch name> bukan <branch name> yang diberikan
DreamUth
0

Karena pertanyaan ini memiliki beberapa jawaban skrip yang bagus, saya menambahkan favorit saya.

Yang ini akan menunjukkan kepada Anda, untuk $nkomit terakhir di $brmana cabang-cabang berisi masing-masing:

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

Yang ini mirip tetapi melakukan hal yang sama untuk daftar cabang:

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
sumber