我正在编写一个脚本,需要检查特定提交是否是合并/恢复提交,我想知道是否有一个 git 技巧。
到目前为止我想出的(我绝对不想依赖这里的提交消息)是检查HASH^2
我是否没有收到错误,有没有更好的方法?
我正在编写一个脚本,需要检查特定提交是否是合并/恢复提交,我想知道是否有一个 git 技巧。
到目前为止我想出的(我绝对不想依赖这里的提交消息)是检查HASH^2
我是否没有收到错误,有没有更好的方法?
弄清楚某事是否是合并很容易。这就是与不止一个父母的所有承诺。要检查这一点,您可以这样做,例如
$ git cat-file -p $commit_id
如果输出中有多个“父”行,则您找到了合并。
对于还原来说,这并不容易。通常,reverts 只是正常的提交,恰好相反地应用了先前提交的差异,有效地删除了提交引入的更改。其他没什么特别的。
如果使用 来创建还原git revert $commit
,那么 git 通常会生成一个提交消息,指示还原以及它还原的提交。但是,很有可能以其他方式进行还原,或者只是更改由git revert
.
寻找那些生成的还原提交消息可能已经是您想要实现的足够好的启发式方法了。如果不是,您必须实际查看其他提交,将它们的差异相互比较,查看一个是另一个的完全反向操作。但即使这样也不是一个好的解决方案。通常,足够多的还原与它们正在还原的提交的反向略有不同,例如,以适应在提交和还原之间发生的代码更改。
以下指令将仅转储父哈希。需要更少的过滤...
git show --no-patch --format="%P" <commit hash>
使用的答案git cat-file
是使用 git "plumbing"命令,这通常更适合构建脚本,因为输出格式不太可能改变。那些使用git show
并且git rev-parse
可能需要随着时间的推移而改变,因为他们正在使用瓷器命令。
我使用了很长时间的 bash 函数使用git rev-list
:
gitismerge () {
local sha="$1"
msha=$(git rev-list -1 --merges ${sha}~1..${sha})
[ -z "$msha" ] && return 1
return 0
}
瓷器/管道命令列表可以在顶级git命令的文档中找到。
此代码使用带有特定gitrevisions查询的git-rev-list以打印 SHA 的第二个父项(如果存在),或者如果它不存在则不打印,这是合并提交的确切定义。${sha}~1..${sha}
具体来说,SHA~1..SHA
意味着包括可从 SHA 访问的提交,但不包括可访问的 SHA~1 的提交,它是 SHA 的第一个父级。
结果存储在 $msha 中,如果为空,则使用 bash[ -z "$msha" ]
失败(返回 1)测试是否为空,如果为非空则通过(返回 0)。
我发现所有答案都很复杂,有些甚至不可靠。
特别是如果您想对合并和定期提交执行不同的操作。
IMO 最佳解决方案是git rev-parse
使用第二个父表达式调用^2
,然后检查错误:
git rev-parse HEAD^2 >/dev/null 2>/dev/null && echo "is merge" || echo "regular commit"
这对我来说非常有效。上面的大多数示例只是一种装饰,它只是丢弃了不需要的输出。
对于 Windows,cmd
这也很有效:
git rev-parse "HEAD^2" >nul 2>nul && echo is merge || echo regular commit
注意引号字符
测试合并提交的一种方法:
$ test -z $(git rev-parse --verify $commit^2 2> /dev/null) || echo MERGE COMMIT
至于 git revert 提交,我同意@rafl的观点,最现实的方法是在提交消息中查找 revert 消息样板;如果有人改变了它,那么检测它会非常复杂。
接受的答案非常适合手动检查结果,但对于脚本编写有一个致命缺陷:提交消息本身可能包含以“父”开头的行,您可能会不小心抓住它,而不是顶部的元数据输出。
更可靠的选择是:
git show --summary <commit>
并检查一行是否以Merge:
. 这类似于 git cat-file,但它会在提交消息前加上空格,因此您可以在脚本中安全地 grep 获取它:
git show --summary HEAD | grep -q ^Merge:
这将返回 0 用于合并提交,1 用于非合并提交。将 HEAD 替换为您想要的测试提交。
示例用法:
if git show --summary some-branch | grep -q ^Merge: ; then
echo "some-branch is a merge"
fi
这是有效的,因为提交消息本身以 4 个空格为前缀,因此即使它包含以“Merge:”开头的行,它也会看起来像 Merge:..
,并且正则表达式不会捕获它。注意^
正则表达式的开头,它与行的开头匹配。
找到提交的父母的另一种方法:
git show -s --pretty=%p <commit>
用于%P
完整哈希。这会打印出有多少父母HEAD
:
git show -s --pretty=%p HEAD | wc -w
如果以下命令的输出为 1,则表明它是一个单独的提交。如果不是,则为合并提交
git cat-file -p $commitID | grep -o -i parent | wc -l
要检查它是否是合并提交,
# Use the FULL commit hash because -q checks if the entire line is matched.
git rev-list --merges --all | grep -qx <FULL_commit_hash>
echo $? # 0 if it's a merge commit and non-zero otherwise
要检查它是否是还原提交,您必须查看其他答案。