git 查找包含特定提交的合并提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8475448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find merge commit which include a specific commit
提问by Guillaume Morin
Imagine the following history:
想象以下历史:
c---e---g--- feature
/ \
-a---b---d---f---h--- master
How can I find when commit "c" has been merged into master (ie, find merge commit "h") ?
我怎样才能找到提交“c”何时被合并到主(即,找到合并提交“h”)?
采纳答案by Gauthier
Your example shows that the branch feature
is still available.
您的示例显示该分支feature
仍然可用。
In that case h
is the last result of:
在这种情况下h
是最后的结果:
git log master ^feature --ancestry-path
If the branch feature
is not available anymore, you can show the merge commits in the history line between c
and master
:
如果分支feature
不再可用,您可以在c
和之间的历史记录行中显示合并提交master
:
git log <SHA-1_for_c>..master --ancestry-path --merges
This will however also show all the merges that happened after h
, and between e
and g
on feature
.
然而,这将同时显示所有之后发生的合并h
,以及之间e
以及g
上feature
。
Comparing the result of the following commands:
比较以下命令的结果:
git rev-list <SHA-1_for_c>..master --ancestry-path
git rev-list <SHA-1_for_c>..master --first-parent
will give you the SHA-1 of h
as the last row in common.
会给你 SHA-1h
作为最后一行的共同点。
If you have it available, you can use comm -1 -2
on these results. If you are on msysgit, you can use the following perl code to compare:
如果你有它,你可以使用comm -1 -2
这些结果。如果你在 msysgit 上,你可以使用下面的 perl 代码进行比较:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2
(perl code from http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/, which took it from "someone at comp.unix.shell news group").
(来自http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/ 的perl 代码,它来自“comp.unix.shell 新闻组的某个人”)。
See process substitutionif you want to make it a one-liner.
回答by robinst
Add this to your ~/.gitconfig
:
将此添加到您的~/.gitconfig
:
[alias]
find-merge = "!sh -c 'commit=# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master
&& 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 pip install git-get-merge
git get-merge <SHA-1>
) && [ -n \"$merge\" ] && git show $merge'"
Then you can use the aliases like this:
然后你可以像这样使用别名:
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
To see the merge commit's message and other details, use git show-merge
with the same arguments.
要查看合并提交的消息和其他详细信息,请使用git show-merge
相同的参数。
(Based on Gauthier's answer. Thanks to Rosen Matevand javabrettfor correcting a problem with sort
.)
(基于Gauthier 的回答。感谢Rosen Matev和javabrett纠正了一个问题sort
。)
回答by Jian
git-get-mergewill locate and show the merge commit you're looking for:
git-get-merge将定位并显示您正在寻找的合并提交:
git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1
The command follows the children of the given commit until a merge intoanother branch (presumably master) is found.
该命令跟随给定提交的子项,直到找到合并到另一个分支(可能是主分支)。
回答by Totor
That is, to summarize Gauthier's post:
也就是说,总结 Gauthier 的帖子:
function git-find-merge() {
git rev-list ..master --ancestry-path | grep -f <(git rev-list ..master --first-parent) | tail -1
}
EDIT: because this uses process substitution"<()
", it is not POSIX compatible, and it may not work with your shell. It works with bash
or zsh
though.
编辑:因为这使用了进程替换“ <()
”,它与 POSIX 不兼容,并且它可能不适用于您的 shell。它适用于bash
或zsh
。
回答by Alex Dupuy
I needed to do this, and somehow found git-when-merged
(which actually references this SO question, but Michael Haggerty never added a reference to his very nice Python script here). So now I have.
我需要这样做,并以某种方式发现git-when-merged
(实际上引用了这个 SO question,但 Michael Haggerty 从未在此处添加对他非常好的 Python 脚本的引用)。所以现在我有了。
回答by evilstreak
Building on Gauthier's great answer, we don't need to use comm
to compare the lists. Since we're looking for the last result in --ancestry-path
which is also in --first-parent
, we can simply grep for the latter in the output of the former:
基于 Gauthier 的精彩答案,我们不需要使用comm
来比较列表。由于我们正在寻找--ancestry-path
也是 in的最后一个结果--first-parent
,我们可以在前者的输出中简单地 grep 后者:
$ gem install git-whence
$ git whence 1234567
234557 Merge pull request #203 from branch/pathway
Or for something snappy and reusable, here's a function to pop into .bashrc
:
或者对于一些活泼且可重用的东西,这里有一个弹出的函数.bashrc
:
#!/bin/bash
commit=
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
回答by steel
For the Ruby crowd, there's git-whence. Very easy.
对于 Ruby 人群,有git-whence。好简单。
(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
回答by hIpPy
I use below bash script which I place at path ~/bin/git-find-merge
. It's based on Gauthier's answerand evilstreak's answerwith few tweaks to handle corner cases. comm
throws when the inputs are not sorted. grep -f
works perfectly.
我使用下面放置在 path 的 bash 脚本~/bin/git-find-merge
。它基于Gauthier 的回答和evilstreak 的回答,并进行了一些调整以处理极端情况。comm
当输入未排序时抛出。grep -f
完美地工作。
Corner cases:
角落案例:
- 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. 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 commit and branch are same, then return commit.
- 如果提交是分支的第一父路径上的合并提交,则返回提交。
- 如果提交是分支的第一父路径上的非合并提交,则返回分支。它要么是 ff 合并,要么是仅在分支上提交,并且没有找到正确提交的好方法。
- 如果提交和分支相同,则返回提交。
~/bin/git-find-merge
script:
~/bin/git-find-merge
脚本:
git log --topo-order
Which lets me do this:
这让我可以这样做:
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
This script is also available on my github.
这个脚本也可以在我的 github 上找到。
回答by Roman
ruby find-commit.rb SHA master
Then look for the first merge before the commit.
然后在提交之前寻找第一个合并。
回答by Kaplan Ilya
My ruby version of @robinst's idea, works twice faster (which is important when searching for very old commit).
我的@robinst 想法的 ruby 版本,工作速度快了两倍(这在搜索非常旧的提交时很重要)。
find-commit.rb
find-commit.rb
You can just use it like this:
你可以像这样使用它:
##代码##