我陷入了泡菜中。我无法从其他 SO 问题或阅读 git 文档中找到我的答案。我真的很感激你在这里的帮助。
在 Github 上 merge 我的分支后,我从 UI(远程)中删除了我的分支。
我定期修剪我的本地分支:
git checkout master
git pull origin master
git fetch -p
git branch -d X
Error: error: The branch X is not fully merged. If you are sure you want to delete it, run 'git branch -D X'
分支 X 已 merge 。当我这样做时,我可以看到来自 X 的提交
git log
在 master
.为什么会发生这种情况?我想用-d
而不是 -D
因为这可能导致灾难性地删除真正未 merge 的分支。
最佳答案
这里有几个不同的棘手部分。 branch -d: base the "already-merged" safety on the branch it merges with When a branch is marked to merge with another ref (e.g. local 'next' that
merges from and pushes back to origin's 'next', with 'branch.next.merge'
set to 'refs/heads/next'), it makes little sense to base the "branch -d"
safety, whose purpose is not to lose commits that are not merged to other
branches, on the current branch. It is much more sensible to check if it
is merged with the other branch it merges with.git branch -d
的关键问题(delete without force1) 不是“分支 merge 了吗?”,因为这个问题实际上是无法回答的。问题是“分支是否 merge 到
这个测试在 Git 1.7 版中发生了变化(这意味着每个人今天都应该拥有它,但请检查你的 Git 版本),在 commit 99c419c91554e9f60940228006b7d39d42704da7通过 Junio C Hamano:
因此,有两个——有时是三个,如果你看看上面的提交——你(或 Git)必须回答的问题,以查看 -d
允许:
T 是 U 的祖先吗?
如果问题 2 的答案是肯定的(即 T ≤ U),则允许删除。
如果没有上游怎么办?嗯,这就是“在 1.7 中更改”的地方:原始测试不是 T ≤ U,而是 T ≤ HEAD。那个测试还在那里。现在,如果没有上游,则使用 HEAD 测试代替上游测试。同时,在每个人都适应新奇的 Git 1.7 行为的“过渡期”中,当有上游时,您也可能会收到警告或额外的解释。即使在今天,这个警告仍然存在,在 Git 2.10 中(现在已经快 7 年了:这是一个非常长的过渡期!):if ((head_rev != reference_rev) &&
in_merge_bases(rev, head_rev) != merged) {
if (merged)
warning("deleting branch ... not yet merged to HEAD.");
else
warning("not deleting branch ... even though it is merged to HEAD.");
}
(我在这里修剪了一些代码用于显示目的):基本上,如果 HEAD
解析为我们在 T ≤ 测试中使用的提交之外的其他提交,并且我们会得到 T ≤ HEAD 的结果与 T ≤ U 的结果不同,我们添加了额外的警告消息。 (请注意,测试的第一部分是多余的:如果我们因为 1.7 之前的兼容性和缺少上游而与 HEAD 进行比较,那么如果再次与 HEAD 进行比较,我们将得到相同的结果。我们真正需要的是in_merge_bases
测试。)
你怎么知道上游是什么?好吧,实际上有一个简单的命令行方法可以找到:$ git rev-parse --abbrev-ref master@{u}
origin/master
$ git rev-parse --symbolic-full-name master@{u}
refs/remotes/origin/master
--abbrev-ref
变体为您提供了 Git 的典型缩写版本,而 --symbolic-full-name
为您提供完整的引用名称。如果在没有上游集的分支上运行,两者都会失败。当然你也可以用git branch -vv
查看缩写的上游(所有分支)。
你如何测试这整个 T ≤ U 的事情? git merge-base --is-ancestor
命令对 shell 脚本执行此操作,因此:$ git merge-base --is-ancestor master origin/master && echo yes || echo no
会告诉你是否master
是origin/master
的祖先(为此,“指向同一个提交”算作“是一个祖先”,即,这是完全相同的 ≤ 测试)。
每当此过渡期最终结束时,“使用 HEAD”测试可能会完全消失,或者可能会继续用于没有上游集的分支。但是无论如何,问题总是“要删除的分支是否 merge 到____?(填空)”,您必须看看是什么填空了。
与您提议删除的分支上的提交相对应的上游提交必须(或至少在其历史记录中具有)相同的提交,通过提交哈希 ID,对于“已 merge 到”测试成功。如 feature/X
并入 origin/develop
通过所谓的“ Squash merge ”(这不是 merge ,尽管它是通过 merging2 完成的),该提交 ID 将不匹配,并且“merge 到”测试将始终失败。
1顺便说一下,从 Git 2.3 开始,您现在可以添加 --force
至 git branch -d
,而不是被要求使用 git branch -D
,当然-D
仍然有效。
2这里的区别是“a merge”——merge作为名词,意思是“a commit that is a merge commit”(使用merge作为形容词)和“to merge”——merge作为动词,意思是结合一些变化。 git merge
命令可以:
“ Squash merge ”仅在您要求时发生,而“快进非 merge ”仅在可以且您不禁止时发生。
关于git - 删除 merge 的分支给出 "error: The branch X is not fully merged...',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40515232/