尝试的git merge异常终止,没有任何错误

时间:2018-12-18 18:05:18

标签: git git-merge

C:\Users\danie01\fox (fox-45481 -> origin)
λ git merge feature/master-stg
error: The following untracked working tree files would be overwritten by merge:
        blah/blah/blahblah.cpp
        ... (many files)
        common/wizard/wizpa
Aborting

C:\Users\danie01\fox (fox-45481 -> origin)
λ

自从我之前合并以来已经很长时间了。此外,该分支中的最后一次提交是合并。

有趣的是,此列表中的最后一个文件已被切断(它没有文件扩展名,甚至没有完整的文件名)-这可能是我的缓冲区有问题吗?

我最近刚从一个远程分支机构签出了该文件;我没有合并到远程分支的权限,需要创建合并请求。 git是否可能试图直接合并到远程分支中?

在这里可以做什么?我很茫然。

2 个答案:

答案 0 :(得分:2)

  

是否可能是git试图直接合并到远程分支中?

不。这不是Git执行合并的方式。

(顺便说一句,您的主题行是错误的,因为合并会中止并出现错误,告诉您某些未跟踪的文件将被覆盖。)

  

有趣的是,此列表中的最后一个文件已被切断(它没有文件扩展名,甚至没有完整的文件名)-这可能是我的缓冲区有问题吗?

我不确定您的意思是什么,但可以肯定的是输出中的文件名不应被截断。

请注意,当您要求Git进行合并时,它必须处理几个不同的项目。所有 commits 都是冻结的(只读),并且基本上是永久的 1 ,因此这不是问题。但是有两件事没有被冻结,因此可能被覆盖:

  • 您当前的索引内容。对于工作树中的每个跟踪文件,您的索引保存一个条目(有时(在不完全合并期间)多个)。实际上,这就是被跟踪的文件:它是现在在工作树中的文件,现在也在索引中。 2

  • 您当前的工作树内容。 Git不会直接使用它-您可以在其中使用,但是各种操作当然会在工作树中覆盖 文件。例如,如果另一个分支的git checkout显然具有其他文件内容,则必须至少覆盖几个文件。

在这两件事之间,您可以轻松创建未跟踪的文件。未被跟踪的文件就是现在存在于您的工作树中的文件,但是现在不在您的索引中。可以忽略或不忽略每个此类文件,但是无论哪种方式,都不会被跟踪。如果未忽略 ,则git status会对此抱怨。

在开始合并之前,最好先确保两件事:首先,您尚未处于其他操作的中间,其次,您的HEAD提交,索引,和工作树在所有跟踪文件方面都匹配。 git merge命令会自动执行大部分操作,但是首先运行git status并确保其显示nothing to commit, working tree clean并不是一个坏主意。

如果这也抱怨各种未跟踪的文件,那就可以了,因为我们有机会马上处理它们。现在,您确定没有正在进行的工作可能会丢失,您发出合并命令:

λ git merge feature/master-stg

Git现在要做的是:

  • 查找当前提交(git rev-parse HEAD)的哈希ID。
  • 查找指定提交(git rev-parse feature/master-stg)的哈希ID。
  • 使用git merge-base --all查找这两个提交的合并基础。合并基础是一个提交,有时甚至是一个以上的提交,都位于两个分支上,并且是最佳这样的提交。

理想情况下,只有一个合并基础提交。您可以通过运行以下命令来验证是否是这种情况:

git merge-base --all HEAD feature/master-stg

如果仅输出一个哈希ID,则表示(单个)合并基础提交。在这里获得多个合并基础是很少见的,而且如果发生这种情况,则需要进行更多讨论,但是由于 是罕见的(而且这里可能不会发生),所以我们可以假设只有一个合并基础。

在某些情况下,只有一个合并基础是与当前({{1)}提交相同的相同哈希ID。这些情况通常很容易处理,Git默认执行 fast-forward 操作而不是合并。可能您的情况并非如此(但可能是–在这里没有任何一种或另一种证据)。我假设Git正在进行真正的合并,因为无论哪种方式,问题都将是相同的,解决方案将是相同的。


1 提交中的文件肯定被冻结,但是它们以形式存在,因为存在。如果您设法使Git忘记该提交,则提交本身最终将消失。做到这一点非常困难,所以提交主要是是永久的。不过,它们是完全 只读的:任何提交(由其哈希ID标识)都无法更改。

2 从技术上讲,您可以删除工作树副本,同时保留索引副本。我认为,尽管该命名法有些不稳定,但它仍将是“跟踪文件”。 (如果文件不存在,如何跟踪该文件?)


Git如何执行真正的合并

现在,Git知道了合并的三个输入-基本提交,HEAD--ours提交,另一个或HEAD提交,从--theirs开始,Git实际上将运行两个 feature/master-stg命令:

git diff

合并的作业现在非常简单而且非常明显。这是它必须要做的:

  • 从合并基本提交中的所有文件开始。
  • 然后,如果我们更改或创建或删除(和/或重命名)文件,并且他们没有触摸文件,请使用我们的< / em>更改。
  • 如果他们更改或创建或删除(和/或重命名)文件,并且 we 没有触摸文件,请使用它们更改。
  • 如果我们和他们都更改或创建或删除(和/或重命名)了相同的文件 ,请合并这两组独立的更改。

在简单的情况下,完成所有这些操作非常简单。例如,也许我们俩都碰到了git diff --find-renames <hash-of-base> HEAD # what we changed git diff --find-renames <hash-of-base> feature/master-stg # what they changed ,但是碰到了不同的地方。我们更改了README.md,但他们没有更改;他们更改了a/main.py,但我们没有。然后,合并的结果将是所有基本文件,除了b/prog.cc(具有合并的更改),我们的README.md及其a/main.py

如果一切顺利,Git会提交结果文件,并一路将它们放入您的索引和工作树中。新的提交将更新当前分支,因此无论分支b/prog.cc的名称如何,现在都将命名新的提交。新提交的第一个父级是当前分支的前一个提示,新提交的第二个父级是另一个提交(在这种情况下,该提交仍由HEAD标识)。由于新提交具有两个父提交,因此它是合并提交

在复杂的情况下,出问题了,合并要么在中间停止(这是最混乱的情况),要么永远不会开始。后一种情况:合并永远不会开始。

您已提交了未跟踪的文件

这里出了问题,在他们的 提交中-由feature/master-stg命名的文件-他们提交了一些文件,即:

  • 不在合并基础提交中,并且
  • 也不在您的HEAD提交中。

Git已打印出这些文件的完整列表:

feature/master-stg

blah/blah/blahblah.cpp ... (many files) common/wizard/wizpa 输出中,他们添加了这些文件。您可以通过自己运行相同的git diff --find-renames <hash of merge base> feature/master-sta来确认这一点,也许使用git diff可以使它更短,更易读。

您的--name-status提交中没有这些文件,但是您现在要做在您的工作树中具有这些文件。 / p>

要让Git进行合并并获得最终结果,Git将必须覆盖您的工作树文件。由于它们不在您的索引中,也不在您的提交中,因此Git无法确定销毁它们的唯一副本就可以了,它位于工作树中。因此,Git中止了合并,根本没有开始。

解决方案是按照Git所说的或应该说的做(也许在“ blahblahblah”部分中丢失了):

  

在合并之前,请先移动或删除它们。

从本质上讲,Git认为有必要覆盖这些文件。如果这样做的话,您拥有的任何内容将是无法检索的,或者至少 Git 无法将其取回。因此,如果内容有价值,则必须将其保存在其他位置。

答案 1 :(得分:1)

我认为git试图告诉您,通过运行合并,某些文件在当前工作树上没有被跟踪,在其他分支上也被跟踪,因此如果合并,它们将被覆盖。我想您可以从工作树中删除它们,以便合并通过。