Bayangkan sejarah berikut ini:
c---e---g--- feature
/ \
-a---b---d---f---h--- master
Bagaimana saya dapat menemukan ketika komit "c" telah digabungkan menjadi master (yaitu, temukan merger komit "h")?
Bayangkan sejarah berikut ini:
c---e---g--- feature
/ \
-a---b---d---f---h--- master
Bagaimana saya dapat menemukan ketika komit "c" telah digabungkan menjadi master (yaitu, temukan merger komit "h")?
Jawaban:
Contoh Anda menunjukkan bahwa cabang featuremasih tersedia.
Dalam hal ini hadalah hasil terakhir dari:
git log master ^feature --ancestry-path
Jika cabang featuretidak tersedia lagi, Anda bisa menunjukkan komit gabungan di garis sejarah antara cdan master:
git log <SHA-1_for_c>..master --ancestry-path --merges
Namun ini juga akan menunjukkan semua gabungan yang terjadi setelah h, dan di antara edan gdi feature.
Membandingkan hasil dari perintah berikut:
git rev-list <SHA-1_for_c>..master --ancestry-path
git rev-list <SHA-1_for_c>..master --first-parent
akan memberi Anda SHA-1 hsebagai baris terakhir yang sama.
Jika tersedia, Anda dapat menggunakan comm -1 -2hasil ini. Jika Anda menggunakan msysgit, Anda dapat menggunakan kode perl berikut untuk membandingkan:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2
(kode perl dari http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/ , yang mengambilnya dari "seseorang di grup berita comp.unix.shell").
Lihat penggantian proses jika Anda ingin membuatnya satu-liner.
masterdigabung menjadi feature, maka segera featuredigabung menjadi mastersebagai fast-forward (ujung featurepengganti master). Apakah itu menyebabkan --first-parentmengembalikan orangtua yang salah?
comm -1 -2tetapi tidak berhasil. commhanya berfungsi pada garis yang diurutkan. (Perl one-liner bekerja, meskipun saya tidak bisa membacanya.)
git find-merge h master(mengembalikan apa-apa selain harus mengembalikan h), git find-merge d master(mengembalikan f tetapi harus mengembalikan d), git find-merge c feature(mengembalikan e tetapi harus mengembalikan g).
Tambahkan ini ke Anda ~/.gitconfig:
[alias]
find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
Maka Anda dapat menggunakan alias seperti ini:
# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master
Untuk melihat pesan komit gabungan dan detail lainnya, gunakan git show-mergedengan argumen yang sama.
(Berdasarkan jawaban Gauthier . Terima kasih kepada Rosen Matev dan javabrett karena telah memperbaiki masalah sort.)
sort -k2 | uniq -f1 -d | sort -n | tail -1 | cut -f2tidak menemukan baris terakhir yang benar secara umum. Berikut ini contoh gagal.
16db9fef5c581ab0c56137d04ef08ef1bf82b0b7sini ketika saya menjalankannya pada pasta Anda, apakah itu tidak diharapkan? OS apa yang Anda pakai?
29c40c3a3b33196d4e79793bd8e503a03753bad1
git-get-merge akan menemukan dan menunjukkan komit gabungan yang Anda cari:
pip install git-get-merge
git get-merge <SHA-1>
Perintah mengikuti anak-anak dari komit yang diberikan sampai penggabungan ke cabang lain (mungkin master) ditemukan.
Artinya, untuk meringkas posting Gauthier:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' <(git rev-list --ancestry-path <SHA-1_for_c>..master) <(git rev-list --first-parent <SHA-1_for_c>..master) | tail -n 1
EDIT: karena ini menggunakan proses substitusi " <()", itu tidak kompatibel dengan POSIX, dan mungkin tidak berfungsi dengan shell Anda. Ini bekerja dengan bashatau zshmeskipun.
<()tidak kompatibel dengan POSIX. Anda perlu menggunakan bash, zshatau substitusi proses pendukung shell . Saya mengedit jawaban saya sesuai dengan itu.
Saya perlu melakukan ini, dan entah bagaimana menemukan git-when-merged(yang sebenarnya merujuk pertanyaan SO ini, tetapi Michael Haggerty tidak pernah menambahkan referensi ke skrip Python yang sangat bagus di sini). Jadi sekarang saya punya.
Membangun berdasarkan jawaban hebat Gauthier, kita tidak perlu menggunakan communtuk membandingkan daftar. Karena kami sedang mencari hasil terakhir --ancestry-pathyang juga ada --first-parent, kami dapat dengan mudah menerima yang terakhir di keluaran yang pertama:
git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1
Atau untuk sesuatu yang tajam dan dapat digunakan kembali, inilah fungsi untuk muncul .bashrc:
function git-find-merge() {
git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}
commtidak berfungsi saat input tidak diurutkan.
Saya menggunakan skrip bash di bawah ini yang saya tempatkan di jalur ~/bin/git-find-merge. Ini didasarkan pada jawaban Gauthier dan jawaban evilstreak dengan beberapa penyesuaian untuk menangani kasus sudut. commmelempar ketika input tidak diurutkan. grep -fbekerja dengan sempurna.
Kasus sudut:
~/bin/git-find-merge naskah:
#!/bin/bash
commit=$1
if [ -z $commit ]; then
echo 1>&2 "fatal: commit is required"
exit 1
fi
commit=$(git rev-parse $commit)
branch=${2-@}
# if branch points to commit (both are same), then return commit
if [ $commit == $(git rev-parse $branch) ]; then
git log -1 $commit
exit
fi
# if commit is a merge commit on first-parent path of branch,
# then return commit
# if commit is a NON-merge commit on first-parent path of branch,
# then return branch as it's either a ff merge or commit is only on branch
# and there is not a good way to figure out the right commit
if [[ $(git log --first-parent --pretty='%P' $commit..$branch | \
cut -d' ' -f1 | \
grep $commit | wc -l) -eq 1 ]]; then
if [ $(git show -s --format="%P" $commit | wc -w) -gt 1 ]; then
# if commit is a merge commit
git log -1 $commit
else
# if commit is a NON-merge commit
echo 1>&2 ""
echo 1>&2 "error: returning the branch commit (ff merge or commit only on branch)"
echo 1>&2 ""
git log -1 $branch
fi
exit
fi
# 1st common commit from bottom of first-parent and ancestry-path
merge=$(grep -f \
<(git rev-list --first-parent $commit..$branch) \
<(git rev-list --ancestry-path $commit..$branch) \
| tail -1)
if [ ! -z $merge ]; then
git log -1 $merge
exit
fi
# merge commit not found
echo 1>&2 "fatal: no merge commit found"
exit 1
Yang memungkinkan saya melakukan ini:
(master)
$ git find-merge <commit> # to find when commit merged to current branch
$ git find-merge <branch> # to find when branch merged to current branch
$ git find-merge <commit> pu # to find when commit merged to pu branch
Skrip ini juga tersedia di github saya .
Versi ruby saya dari ide @ robinst, bekerja dua kali lebih cepat (yang penting ketika mencari komit yang sangat lama).
find-commit.rb
commit = ARGV[0]
master = ARGV[1] || 'origin/master'
unless commit
puts "Usage: find-commit.rb commit [master-branch]"
puts "Will show commit that merged <commit> into <master-branch>"
exit 1
end
parents = `git rev-list #{commit}..#{master} --reverse --first-parent --merges`.split("\n")
ancestry = `git rev-list #{commit}..#{master} --reverse --ancestry-path --merges`.split("\n")
merge = (parents & ancestry)[0]
if merge
system "git show #{merge}"
else
puts "#{master} doesn't include #{commit}"
exit 2
end
Anda bisa menggunakannya seperti ini:
ruby find-commit.rb SHA master
Anda dapat mencoba sesuatu seperti ini. Idenya adalah untuk beralih melalui semua gabungan komit dan melihat apakah komit "c" dapat dicapai dari salah satu dari mereka:
$ git log --merges --format='%h' master | while read mergecommit; do
if git log --format='%h' $mergecommit|grep -q $c; then
echo $mergecommit;
break
fi
done
git rev-list <SHA-1_for_c>..master --ancestry-path --merges
Saya harus melakukan ini beberapa kali (terima kasih kepada semua orang yang menjawab pertanyaan ini!), Dan akhirnya menulis skrip (menggunakan metode Gauthier) yang dapat saya tambahkan ke koleksi kecil utilitas git saya. Anda dapat menemukannya di sini: https://github.com/mwoehlke/git-utils/blob/master/bin/git-merge-point .