我正在编写一个脚本,需要检查特定提交是否是合并/恢复提交,我想知道是否有 git 技巧。
到目前为止我想到的(我绝对不想依赖这里的提交消息)是检查
HASH^2
并看看我是否没有收到错误,是否有更好的方法?
判断某个东西是否是合并很容易。这是不止一位父母的所有承诺。要检查这一点,您可以执行以下操作
$ git cat-file -p $commit_id
如果输出中存在多个“父”行,则您发现了合并。
对于恢复来说并不那么容易。通常,恢复只是正常提交,恰好相反地应用先前提交的差异,从而有效地删除提交引入的更改。除此之外,他们并不特别。
如果使用
git revert $commit
创建了恢复,那么 git 通常会生成一条提交消息,指示恢复以及恢复的提交。但是,很可能以其他方式进行恢复,或者仅更改由 git revert
生成的提交的提交消息。
寻找那些生成的恢复提交消息对于您想要实现的目标来说可能已经是一个足够好的启发式方法。如果不是,您必须实际查看其他提交,比较它们之间的差异,检查其中一个是否是另一个的精确反向操作。但即使这样也不是一个好的解决方案。通常,足够的恢复与它们要恢复的提交的相反略有不同,例如为了适应提交和恢复之间发生的代码更改。
以下指令将“仅”转储父哈希值。需要更少的过滤...
git show --no-patch --format="%P" <commit hash>
git cat-file
的答案是使用 git
"plumbing"命令,这通常更适合构建脚本,因为输出格式不太可能改变。使用
git show
和 git rev-parse
的用户可能需要随着时间的推移而改变,因为他们正在使用 porcelain 命令。
我长期使用的bash函数使用git rev-list
:
gitismerge () {
local sha="$1"
msha=$(git rev-list -1 --merges ${sha}~1..${sha})
[ -z "$msha" ] && return 1
return 0
}
瓷器/管道命令列表可以在顶级gitgit-rev-list
和特定的 gitrevisions 查询 ${sha}~1..${sha}
,如果存在,则打印 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
注意引号字符测试合并提交的一种方法:
git show -s --pretty=%p <commit>
使用
%P
进行完整哈希。这会打印 HEAD
有多少个父母:
git show -s --pretty=%p HEAD | wc -w
接受的答案对于手动检查结果效果很好,但对于脚本编写有一个致命的缺陷:提交消息本身可能包含以“parent”开头的行,您可能会意外地捕获它,而不是顶部的元数据输出。
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:..
,并且正则表达式不会捕获它。请注意正则表达式开头的 ^
,它与行的开头匹配。如果以下命令的输出为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
要检查它是否是恢复提交,您必须查看其他答案。