我看到了一些关于“如何检查分支是否X已重新基于Y”的问题,但我还没有找到具有我想要的特定风味的分支。
我想检查是否X是“简单的分支下降Y”。X严格来说,只允许在和 之间使用这种模式,而不是在和Y之间使用这种模式:ZY
换句话说,如果分支中的每个提交都X具有Y作为祖先(或者等于Y或是其中一个Y祖先)——而不仅仅是 的尖端是否具有作为X祖先Y。
这对于帮助人们实现基于 rebase 的合并模式是可取的,其中X是功能分支,Y是主要开发分支。(如果有人真的知道他们在做什么,并且非严格分支是他们真正想要的,我们可以轻松地授予特殊豁免并允许合并。但我们希望他们至少意识到他们正在这样做,这一直没有发生。)
请注意,这与“可以合并”不同--ff-only。 git merge --ff-only会很高兴地更新Y以指向XifY是 的后代X,即使 的某些祖先X既不是 的后代也不是祖先Y。
我知道我可以遍历所有祖先X并检查是否Y是每个祖先的祖先(当我到达Y自身时停止,并确保没有多个父母),但我想知道是否有更好的内置东西到我错过的 Git。
附录:
pull正如 @TTT 指出的,另一个常见的情况是有人在 之前使用 ing而push不是执行 ,从而搞乱了 rebase push --force-with-lease。我为我们的内部“如何使用 Git”文档创建了下图,如果能自动执行此检查就太好了:
检查所有提交是否Y..X都是 的后代的一种方法是使用或Y检查该范围的边界。git log --boundary Y..Xgit rev-list --boundary Y..X
从这段历史开始:
$ git log --graph --oneline --all
* 036a9f9 (HEAD -> X) create d.txt
* cadd199 create c.txt
| * 0680934 (Z) Merge commit '22a23fe' into Z
|/|
| * 22a23fe create b.txt
* | 8dec744 (Y) create a.txt
|/
* 878ac8b first commit
Run Code Online (Sandbox Code Playgroud)
你会得到 :
$ git log --oneline --boundary Y..X
036a9f9 (HEAD -> X) create d.txt
cadd199 create c.txt
- 8dec744 (Y) create a.txt # <- one single boundary commit, pointing at Y
$ git log --oneline --boundary Y..Z
0680934 (Z) Merge commit '22a23fe' into Z
22a23fe create b.txt
- 8dec744 (Y) create a.txt # <- two commits on the boundary
- 878ac8b first commit # <-
Run Code Online (Sandbox Code Playgroud)
检查您是否处于这种情况的可编写脚本的方法是:
# 'git rev-list' prints full hashes, boundary commits are prefixed with '-'
boundary=$(git rev-list --boundary Y..X | grep -e '^-')
want=$(git rev-parse Y)
want="-$want"
# the boundary should consist of "-<hash of Y>" only:
if [ "$boundary" = "$want" ]; then
echo "all commits in X are descendants of Y"
fi
Run Code Online (Sandbox Code Playgroud)
上面只是检查所有提交是否都在Y. 您还可能面临以下情况:
* 036a9f9 (HEAD -> X) create d.txt
* 0680934 Merge 'origin/X' into X # <- someone created a merge commit in between
|\
| * cadd199 create c.txt
* | 22a23fe create b.txt
|/
* 8dec744 (Y) create a.txt
* 878ac8b first commit
Run Code Online (Sandbox Code Playgroud)
这也会影响变基工作流程。
如果您还想排除这种情况,请使用或--merges选项:git loggit rev-list
# git rev-list also has a --count option, which will output the count
# rather than the complete list of commits
merges=$(git rev-list --count --merges Y..X)
if [ "$merges" -eq 0 ]; then
echo "all good, no merges between Y and X"
fi
Run Code Online (Sandbox Code Playgroud)
的文档--boundary没有很好地解释什么是“边界提交”。
我想说这个答案有一个不错的定义:
边界提交是限制修订范围但不属于该范围的提交。例如,修订范围 HEAD~3..HEAD 由 3 个提交(HEAD~2、HEAD~1 和 HEAD)组成,并且提交 HEAD~3 作为其边界提交。
更正式地说,git 通过从指定的提交开始并通过父链接获取其他提交来处理修订范围。它在不满足选择标准的提交处停止(因此应该被排除) - 这些是边界提交。