查找包含特定提交的合并提交
想象下面的历史:
c---e---g--- feature / \ -a---b---d---f---h--- master
我怎样才能find提交“C”已被合并到主(即,find合并提交“H”)?
您的示例显示分支feature
仍然可用。
在这种情况下, h
是最后的结果:
git log master ^feature --ancestry-path
如果分支feature
不再可用,则可以在c
和master
之间的历史logging行中显示合并提交:
git log <SHA-1_for_c>..master --ancestry-path --merges
然而,这也将显示h
之后发生的所有合并,以及e
和g
之间的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。 它虽然与bash
或zsh
。
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 。