查找包含特定提交的合并提交

想象下面的历史:

c---e---g--- feature / \ -a---b---d---f---h--- master 

我怎样才能find提交“C”已被合并到主(即,find合并提交“H”)?

您的示例显示分支feature仍然可用。

在这种情况下, h是最后的结果:

 git log master ^feature --ancestry-path 

如果分支feature不再可用,则可以在cmaster之间的历史logging行中显示合并提交:

 git log <SHA-1_for_c>..master --ancestry-path --merges 

然而,这也将显示h之后发生的所有合并,以及eg之间的feature


比较以下命令的结果:

 git rev-list <SHA-1_for_c>..master --ancestry-path git rev-list <SHA-1_for_c>..master --first-parent 

会给你h的SHA-1作为最后一行的共同点。

如果有可用的话,可以在这些结果上使用comm -1 -2 。 如果你在msysgit上,你可以使用下面的perl代码来比较:

 perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2 

(来自http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/的; perl代码,它来自“comp.unix.shell新闻组中的某个人”)。

如果你想使它成为一个class轮,请参阅stream程replace 。

添加到你的~/.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'" 

那么你可以使用这样的别名:

 # current branch git find-merge <SHA-1> # specify master git find-merge <SHA-1> master 

要查看合并提交的消息和其他细节,请使用具有相同参数的git show-merge

(基于Gauthier的回答 ,感谢Rosen Matev和javabrett纠正sort问题。)

也就是说,总结高蒂尔的post:

 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 

编辑:因为这使用过程replace “ <() ”,它不是POSIX兼容,它可能不适用于你的shell。 它虽然与bashzsh

git-get-merge会find并显示你正在寻找的合并提交:

 pip install git-get-merge git get-merge <SHA-1> 

该命令跟随给定提交的子节点,直到find另一个分支(可能是master)的合并为止。

基于Gauthier的很好的回答,我们不需要使用comm比较列表。 既然我们正在寻找最后一个结果,而这个结果也是在--first-parent ,我们可以简单地在后者的输出中寻找:

 git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1 

或者为了快速和可重用的东西,这里有一个函数可以popup到.bashrc

 function git-find-merge() { git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1 } 

我需要这样做,并以某种方式发现了git-when-merged (实际上引用了这个SO问题,但是Michael Haggerty从来没有在这里添加对他非常好的Python脚本的引用)。 所以现在我有。

对于ruby的人群来说,就是这样。 好简单。

 $ gem install git-whence $ git whence 1234567 234557 Merge pull request #203 from branch/pathway 

我的@ robinst的想法的ruby版本,工作两次更快(这是非常重要的时候search非常古老的提交)。

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 

你可以像这样使用它:

 ruby find-commit.rb SHA master 

我使用下面的脚本,我放在path~/bin/git-find-merge 。 这是基于Gauthier的答案和evilstreak的答案 ,几乎没有处理angular落案件的调整。 当input未被sorting时, comm会抛出。 grep -f完美地工作。

案例:

  • 如果commit是分支的第一个父path上的合并提交,则返回提交。
  • 如果提交是分支的第一个父path上的非合并提交,则返回分支。 这是一个合并或提交只是在分支,没有一个好的方法来找出正确的提交。
  • 如果提交和分支相同,则返回提交。

~/bin/git-find-merge脚本:

 #!/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 

哪个让我做到这一点:

 (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 

这个脚本也可以在我的github上 。

你可以尝试这样的事情。 这个想法是遍历所有的合并提交,看看提交“C”是否可以从其中之一:

 $ 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 

我不得不这样做几次(感谢大家回答这个问题!),最后写了一个脚本(使用Gauthier的方法),我可以添加到我的小集合git实用程序。 你可以在这里find它: https : //github.com/mwoehlke/git-utils/blob/master/bin/git-merge-point 。