我正在编写一个脚本,需要检查特定的提交是否是合并/撤销提交,想知道是否有适用于git的技巧。
到目前为止我想到的方法(绝对不要依赖提交消息)是检查HASH^2
并查看是否没有出错,有更好的方法吗?
我正在编写一个脚本,需要检查特定的提交是否是合并/撤销提交,想知道是否有适用于git的技巧。
到目前为止我想到的方法(绝对不要依赖提交消息)是检查HASH^2
并查看是否没有出错,有更好的方法吗?
判断一个提交是否是合并提交很容易,只需要查看它是否有多个父提交。例如,要检查这一点,可以执行以下操作:
$ git cat-file -p $commit_id
如果输出中有多个“parent”行,那么您找到了一个合并操作。git revert $commit
创建了还原操作,则 Git 通常会生成一个提交消息,指示还原操作以及它所还原的提交。但是,很可能以其他方式进行还原操作,或者只更改由 git revert
生成的提交的提交消息。git show --no-patch --format="%P" <提交哈希>
使用 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
}
您可以在顶级 git 命令的文档中找到瓷器/管道命令列表。
此代码使用特定的 git-rev-list 和 gitrevisions 查询${sha}~1..${sha}
,以一种打印SHA的第二父项(如果存在)或不打印任何内容(如果不存在)的方式,这正是合并提交的确切定义。
具体来说,SHA~1..SHA
表示包括可从SHA到达但不包括可从SHA~1(即SHA的第一个父项)到达的提交。
结果存储在$msha中,并使用bash [ -z "$msha" ]
测试其是否为空。如果为空,则失败(返回1),如果非空,则通过(返回0)。
git rev-list --no-walk --count --merges "$@"
)) }
这段代码是用于 Git 版本控制工具的检测,判断提交历史中是否存在合并操作。如果存在,则返回 0,否则返回 1。 - jthill))
后加上分号才能编译。)请考虑将其发布为答案。 - Joshua Goldbergrev-list --no-walk --count --merges
,但我不再有一台苹果电脑了(现在是在Windows/WSL上工作),所以无法测试。 - undefined我发现所有的答案都过于复杂,有些甚至不可靠。
特别是如果您想对合并和普通提交执行不同的操作。
在我看来,最好的解决方案是使用第二个父级表达式^2
调用git rev-parse
,然后检查是否有错误:
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撤销提交,我同意@rafl的看法,最现实的方法是在提交信息中查找撤销消息的样板内容;如果有人更改了它,那么检测起来将非常复杂。
test -z
究竟是做什么的?问题并不要求使用 Bashisms... - knocte对于手动检查结果,已接受的答案效果很好,但对于脚本来说有一个致命缺陷:提交消息本身可能包含以 "parent" 开头的一行,而您可能会意外捕捉到该行,而不是输出顶部的元数据。
更可靠的替代方法是:
git show --summary <commit>
请检查是否有一行以Merge:
开头。这类似于git cat-file,但它会在提交消息前添加空格,因此您可以在脚本中安全地进行grep操作:
git show --summary HEAD | grep -q ^Merge:
if git show --summary some-branch | grep -q ^Merge: ; then
echo "some-branch is a merge"
fi
Merge:..
,正则表达式也不会捕获它。请注意正则表达式开头的^
,它匹配行的开头。git cat-file
grep 有什么作用?你能详细说明一下吗? - knocte查找提交的父级的另一种方法:
git show -s --pretty=%p <commit>
%P
来获取完整的哈希值。这会打印出 HEAD
的父提交数量:git show -s --pretty=%p HEAD | wc -w
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
要检查它是否是还原提交,您需要查看其他答案。