Git“错误:分支'x'未完全合并”

405

以下是我从主分支中使用的命令。

git branch experiment
git checkout experiment

然后我更改了我的文件,提交了更改,并将新分支推送到GitHub。

git commit . -m 'changed files'
git push -u origin experiment

后来,我决定将我的实验分支合并到主分支中。

git checkout master
git merge experiment

最终我将更改推送到了GitHub。

git push -u origin master

一切都进行得很顺利,直到我尝试使用以下命令删除我的实验分支:

git branch -d experiment

我收到了如下错误信息:

错误:分支'experiment'没有被完全合并。
如果你确定要删除它,请运行'git branch -D experiment'。

我对Git比较陌生,也不知道我需要合并这两个分支的程度。我在这里漏掉了什么?


2
这篇文章对您有帮助吗?https://dev59.com/8XI-5IYBdhLWcg3wta7w - Chrisdigital
2
有时候,当我执行了git commit --amend命令时会出现这种情况。 - Arcolye
41
请注意,这条消息会在进行了“压缩”操作后出现:https://dev59.com/JFgQ5IYBdhLWcg3w9Yzk - Jim G.
1
我认为最常见的情况是,在本地删除分支之前,您只需要拉取您新合并的更改。 - RaisinBranCrunch
14个回答

423

注意: 根据评论更改了措辞。感谢 @slekse
这不是一个错误,而是一个警告。它意味着你即将删除的分支包含的提交无法从以下任何一个地方到达:其上游分支或 HEAD(当前检出的修订版)。换句话说,你可能会丢失提交¹。

实际上,这意味着您可能已经修改、变基(包括压缩合并)或筛选了提交,但它们看起来不完全相同

因此,您可以通过检出包含您要通过删除另一个分支来取消引用的提交的分支²来避免警告

您需要验证自己确实没有漏掉任何重要的提交:

git log --graph --left-right --cherry-pick --oneline master...experiment
这将为您提供任何分支之间未共享的列表。如果您感到好奇,可能会存在没有--cherry-pick的区别,这种差异可能是您收到警告的原因:

-- cherry-pick

当使用对称差异限制提交集时,省略引入与“另一侧”上的另一个提交相同更改的任何提交。例如,如果您有两个分支A和B,以--left-right列出它们其中一个分支上的所有提交的常规方式就像上面选项描述中的示例一样。但是,它显示了从其他分支中挑选的提交(例如,“b上的第3个”可能是从分支A中挑选的)。使用此选项,这些提交对被排除在输出之外。


¹默认情况下,它们只在一段时间后才被垃圾回收。此外,git-branch命令不会检查所有分支的修订树。警告是为了避免明显的错误。

²(我个人偏向强制删除,但您可能希望获得额外的保证)。


35
谢谢。关键词是“包含的提交在任何其他引用头中都不可到达”。尽管我不再需要实验分支,已经将其合并到主分支并计划从源中删除它,但 Git 直到我将更改推送到实验分支源才会感到满意。我想这个警告是某种理智检查。 - mellowsoon
41
这句话的意思是你将要删除的分支包含一些提交记录,这些提交记录不能通过任何其他引用来访问。但实际上这是不正确的。这个警告的意思是该分支无法从其上游(如果有)或当前的HEAD访问到。请参考git-branch的man页面。 - sleske
4
@TachyonVortex,不错的链接。命令git branch -vv 确实让我更清楚地了解了正在发生的事情。 - Jason Massey
19
@sleske 感谢您的评论--这个答案真的需要编辑。很遗憾它获得了很高的赞数,因为主要的解释句子是不正确的。我刚刚遇到了这个问题,花了很长时间才找出问题所在,原来是远程跟踪分支已经被删除,作为拉取请求的一部分,并且在那之后我从本地分支上拉取了来自主分支的更改。唯一的“问题”就是找不到已经被删除的远程跟踪分支(而我正试图出于同样的原因删除本地分支)。 - ely
6
如果你在删除一个本地分支时处于与创建该分支时不同的分支上,就会出现这种情况。 “没有从任何其他引用可达的提交”是不正确且不必要令人恐慌的说法! - Alkanshel
显示剩余14条评论

112
如Drew Taylor所指出,使用-d删除分支只考虑当前HEAD来确定该分支是否“完全合并”。 即使该分支与其他某些分支合并,它也会发出警告。 在这方面,错误消息肯定可以更清晰地说明... 您可以在删除之前检出合并的分支,或者只需使用git branch -D。 大写的-D将完全覆盖检查。

4
“当前HEAD的部分解决了我的问题。我的主分支不同于我创建冲突分支所基于的特性分支:D” - viki.omega9
3
对于正在学习git的人来说,“current”这个词似乎与“HEAD”重复了?不存在未更新的HEAD,根据定义,HEAD就是当前分支。我是否漏掉了什么?我想你可以说“current branch”或“HEAD”,但不能说“current HEAD”。 - Mark Lakata
1
有没有办法改变/配置这个(例如,让它始终检查origin/master?)我猜先检出origin/master并不太麻烦,但这感觉就像一种奇怪的流程——为什么我需要在本地检出origin/master,只是为了让你验证我的更改是否已经合并到那里? - alecbz
@Alec,你可以随时创建别名。master 没有什么特别之处。Git 对分支名称或重要性没有任何假设(或要求),用户需要明确我们想要合并/比较/检查等的内容。Git 甚至不会假设远程 master 比您的本地分支更重要!并且要明确的是,origin/master 是您在 origin 的远程 master 的本地副本,可能与您的本地 master 不同(这取决于您是否进行了获取或拉取)。您可以检出 master。很少有充分的理由去检出 origin/master - Zim
在删除分支之前,请检查已合并的分支。当前检出的分支似乎无法删除。 - R. Schreurs
显示剩余2条评论

34

我尝试了sehe的回答,但它没有起作用。

要查找尚未合并的提交,只需使用:

git log feature-branch ^master --no-merges

19

Easy Solution with Explanation (double checked solution) (previously faced the same problem)

Problem:

1. Unable to delete a branch.

2. Terminal keeps displaying a warning message stating that there are some unapproved commits.

3. Confirmed that both the master and branch are identical and up to date.

Solution:

git checkout master
git merge branch_name
git checkout branch_name
git push
git checkout master
git branch -d branch_name

说明:

当你的分支与上游远程分支(在Github、Bitbucket或其他平台上)连接时,你需要将其合并(推送)到主分支中,并且你需要从该分支将新更改(提交)推送到远程存储库(Github、Bitbucket或其他平台)。

我在我的代码中所做的是切换到主分支,然后将该分支合并到主分支中(以确保它们在你的本地机器上是相同的),然后再次切换到该分支,并使用 "git push" 将更新或更改推送到远程在线存储库。

之后,我再次切换到主分支,并尝试删除该分支,问题(警告消息)消失了,并成功删除该分支。


16

今天我遇到了这个问题,因为我正在将我的第一个特性分支合并回主分支。正如其他某些人在 Stack Overflow 上的线程中所说的那样,诀窍是在尝试删除分支之前切换回主分支。一旦回到主分支,git 就可以快乐地删除该分支而不会有任何警告。


这是一个不同的警告,没有“未完全合并”的提示。 - Spartan

5
你可以简单地找出:
git log --cherry master...experimental --cherry选项是--right-only --cherry-mark --no-merges的同义词。
git-log手册中说:
限制输出到我们这一侧的提交,并使用git log --cherry upstream...mybranch标记已应用于分叉历史的另一侧的提交,类似于git cherry upstream mybranch。
顺便提一下,--cherry-pick会省略等效提交,但--cherry-marks不会。它对于查找上游和协作公共分支之间的rebase和强制更新更改很有用。

这个有用,我在Github网站上提交了一个pull request,它显示为比主分支领先一个commit,但这个commit已经在主分支中。另外,'git branch -d -r origin/branch-name'的操作很奇怪,它似乎可以删除,但是该分支仍然存在于远程,并且第二次使用时会显示未找到。 - Spartan

5
Git警告你删除这个分支可能会丢失历史记录。即使它不会立即删除任何提交,如果这些提交不属于其他分支,那么该分支上的一些或所有提交将变得无法访问。
要使分支“完全合并”到另一个分支中,其尖端提交必须是另一个分支尖端的祖先,使得实验中的提交成为另一个分支的子集。这样就可以安全地删除实验,因为所有提交都将通过其他分支保留在存储库历史记录中。它必须是“完全”合并,因为它可能已经被多次合并,但现在已经添加了自上次合并以来未包含在其他分支中的提交。
Git不会检查存储库中的每个其他分支;只有两个:
1. 当前分支(HEAD) 2. 上游分支(如果有)
对于实验,您的“上游分支”可能是origin/experiment。如果实验在当前分支中完全合并,则Git将无需进行任何投诉即可删除它。如果它没有完全合并,但在其上游分支中完全合并,则Git将继续发出警告,如下所示:
warning: deleting branch 'experiment' that has been merged
to 'refs/remotes/origin/experiment', but not yet merged to
HEAD.
Deleted branch experiment (was xxxxxxxx).

xxxxxxxx 表示一个提交 ID。如果 experiment 分支被完全合并到了其上游分支,那么这些提交就已经被推送到了源代码库中,即使你在本地丢失了这些提交,它们也至少可以在其他地方保存。

由于 Git 不会检查其他分支,因此删除一个分支可能是安全的,因为你知道它已经完全合并到另一个分支中;你可以使用 -D 选项来执行此操作,或者先切换到该分支,让 Git 为你确认其是否已经完全合并。


1
关键是“完全合并到当前分支”。我从X创建了一个名为X'的分支,将其完全合并回X,并已删除origin/X'。但当我检出Y时,我收到了这个警告。当我检出X时,我能够删除X'。我认为这相当愚蠢。 - Lawrence Dol
4
这个答案是从这里抄袭而来,没有注明出处:http://chimera.labs.oreilly.com/books/1230000000561/ch05.html#branch-deletion - Mark Lakata

3
为了查看未合并的更改,我执行了以下操作:
git checkout experiment
git merge --no-commit master

git diff --cached
<注意:这显示了master中的更改,而这些更改不在experiment中。>

不要忘记:

git merge --abort

完成查看后,您可以结束此过程。

2

我在本地的git上没有上游分支。我从master创建了一个本地分支,使用git checkout -b mybranch命令。我在upstream git上使用bitbucket GUI创建了一个分支,并将我的本地分支(mybranch)推送到该上游分支。一旦我在本地git上执行了git fetch命令以检索上游分支,我就可以使用git branch -d mybranch命令删除我的本地分支。


0

被接受的答案是正确的。在这个答案中,我会补充三件事:

  1. 这是如何发生的(经常发生在我身上)
  2. 展示一个例子
  3. 如何确保在通过 -D 强制删除之前不会错过任何更改

我在 GitHub 上使用 Rebase and merge 作为默认的 PR 合并方法。这将为相同的更改创建 新的 提交(哈希值)。

例如,当我运行以下命令时:

git log --graph --left-right --oneline add-theme-dark-2...main

在我的一个项目中,我遇到了这个:
> fba6fce (HEAD -> main, tag: v2.0.9, origin/main) Refactored to semantic class names.
> 4e665bc Refactored to semantic class names. (1a)
....
> 8bd13a6 Added 'font-semibold' to title.     (2a)
< 23f7b8a (add-theme-dark-2) Refactored to semantic class names.
< cf71814 Refactored to semantic class names.  (1b)
....
< d3a774a Added 'font-semibold' to title.      (2b)
(END)


请注意,1a / 1b和2a / 2b具有不同的提交哈希值。
为确保您未错过任何更改,请运行:
git log --graph --left-right --cherry-pick --oneline add-theme-dark-2...main

如果它返回一个以"="开头的列表:

= fba6fce (HEAD -> main, tag: v2.0.9, origin/main) Refactored to semantic class names.
= 4e665bc Refactored to semantic class names.
...
= 346770b Moved text size to component.
= 68cd471 Added theme-dark.
= 8bd13a6 Added 'font-semibold' to title.

可以安全删除分支:

git branch -D add-theme-dark2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接