Git 通过删除 master 中的文件来修复合并冲突,这可能吗?



我与我的一个分支与 master 发生冲突,有一个文件发生冲突。我可以删除主文件并与分支合并以取回文件吗?这会解决冲突吗?谢谢

(旁注,但这很重要:首先不要考虑太多分支。文件在提交中。 Git 存储提交。 Git 合并提交。 一切都与提交有关,像master这样的分支名称只是用来查找提交。

如果要删除文件,则会在提交中执行此操作。 (该提交可能包含也可能不包含在可通过名称master访问的提交集中;在您正在考虑的方法中,它将在该提交集中。 但这并没有真正的帮助:你只会得到一个不同的冲突,特别是修改/删除冲突。 冲突的答案从来都不是复杂的"在这里或那里删除文件"之类的事情。 总是为了解决冲突

你应该从头开始,那就是:合并是关于组合变化。 这涉及查找合并基提交。 你告诉 Git 合并一个提交——通常是通过命名一个分支,就像在git merge otherbranch中一样,但这仍然命名一个特定的提交。 Git 将这个合并基础提交本身定位为提交 #1,使用当前提交(当前分支的提示)作为提交 #2,并使用您命名为提交 #3 的提交。

每次提交都会存储所有文件的完整快照,因此在 Git 可以合并更改之前,Git 首先必须查找更改。 这涉及运行git diff,它可以比较两个提交。 不过,它只能比较两个提交!1因此,git merge选择的合并基础必须位于两个分支上:

I--J   <-- branch1 (HEAD)
/
...--G--H

K--L   <-- branch2

如果你在branch1上运行git merge branch2,Git 此时将使用的三个提交是HJLJ是您当前的提交,在branch1的尖端;Lbranch2尖端的提交,您正在合并它;H两个分支上最好的共享提交,因此H是合并基础。

实际上,Git 现在运行:

git diff --find-renames <hash-of-H> <hash-of-J>   # what we changed on branch1
git diff --find-renames <hash-of-H> <hash-of-L>   # what they changed on branch2

合并的过程现在是一项简单的工作,对于我们都更改的每个文件,我们所做的一组更改,并组合这些更改。 然后,这些组合的更改将应用于提交H中文件中的任何内容 - 不是应用于我们的提交J,也不是应用于它们的提交L,而是应用于基本提交! 这样,我们就可以得到组更改。

发生冲突是因为您和他们都更改了同一文件的相同行。 您和他们也可能更改了同一文件的不同行;Git 将能够自行组合它们。 只有当你的更改和它们的更改"接触"(重叠或相邻),并且您和他们没有进行完全相同的更改时,您才会发生冲突。

在冲突进行期间,Git 确实允许您访问所有三个原始输入文件。 您在工作树文件中看到的是它合并更改的最佳尝试,并带有冲突标记;但是,如果您愿意,可以访问文件的合并基本副本、branch1提交J文件的副本及其branch2提交L文件的副本。 (git mergetool命令为您执行此类操作,提取文件的三个副本并运行您选择的合并工具。 不过,我倾向于不使用它:我通常只是直接编辑工作树副本。

如果您绝对确定要丢弃所有更改(即使是那些与另一方的更改不冲突的更改),此时可以使用git checkout --theirs轻松完成此操作。 例如,如果冲突在文件lib.py中:

git checkout --theirs lib.py

将文件的 #3 副本(从提交L)提取到工作树副本中。 然后,您可以检查它,确保它良好,然后使用git add lib.py将冲突标记为已解决。


1Git 确实有一个可以比较三个或更多提交git diff,产生它所谓的组合差异,但这在这里并不真正相关:它不适用于合并。


如果在合并之前删除文件会怎样?

假设你继续你的计划。 您将在分支branch1上进行新的提交,其中此文件(为了具体性,我们继续将其称为lib.py):

I--J--N   <-- branch1 (HEAD)
/
...--G--H

K--L   <-- branch2

Git 现在git diff提交H与提交N以查看您更改的内容。 在它发现的任何其他更改中,它会发现您完全删除lib.py。 然后 Git 将 diff 提交H与提交L. 它必须在这里找到一些lib.py更改,因为当您尝试与 commitJ合并时,它发生了冲突,并且只有当您和他们都对该文件的同一行进行更改时,它才会发生冲突。 因此,Git 将希望对HL进行一些更改。

您将获得的是修改/删除冲突。 Git 可能会暂时删除,或者可能会从提交L中留下他们的lib.py版本。 如果 Git 删除了该文件,您现在需要git checkout --theirs lib.py才能获取他们的文件。 如果 Git 将你的工作树留在你的工作树中,你不必在这里做任何事情——在这里节省你一步,但代价是让提交N的额外步骤。 然后,您将git add lib.py解决冲突。

你刚刚完成了几乎完全相同的工作量! 为什么不以正确的方式做,而不进行额外的提交呢?

最新更新