Git Merge Conflict:添加要在解决时提交的更改?

时间:2017-01-05 15:56:16

标签: php git github git-merge

我经常遇到以下合并冲突问题并解决它,但我想问一下我的解决方案是否正确。就个人而言,我没有看到任何问题,因为功能测试正在通过,但是对这个问题有所了解会很好。

所以,假设我们有两个分支:

  1. develop
  2. feature
  3. 我正在更改feature分支中的代码,然后创建PR以合并到develop。但是,GithubBitbucket的差异工具表明我们遇到了合并冲突;编码很常见。

    然后我采取以下步骤:

    1. git checkout developgit pull origin develop

    2. git checkout feature然后git pull origin feature

    3. git merge develop,以便更新我当前的分支。这些步骤可以帮助我找出发生冲突的文件。
    4. 然后我手动修复了冲突,我看到了:
    5. `你有未合并的路径。   (修复冲突并运行“git commit”)

      要提交的更改:

      modified:   app/BlablaFile.php
          modified:   app/Blabla2File.php
          renamed:    app/OldName.php -> app/NewName.php
      

      然后:

      Unmerged paths:
        (use "git add <file>..." to mark resolution)
          both modified:   app/UnmergedFile.php
      

      基本上是我为解决合并冲突而编辑的文件列表。

      问题是我应该只git add app/UnmergedFile.php然后git commit -m "Updated app/UnmergedFile.php"吗?或者我应该git add还包含Changes to be committed:部分中包含的文件?

      我通常会做第一个但是想到另一个想法会很好。

3 个答案:

答案 0 :(得分:2)

TL; DR:您无需重新添加&#34;要提交的更改的文件&#34;。

Git&#34;索引&#34;

Git有一个名称,不同的是,索引登台区域,有时甚至是缓存(如{{1} }})。它解释得不是很好,部分原因是因为它很复杂。幸运的是,索引的 use 非常简单,除了(唉)合并期间。 : - )

索引中的内容最好被描述为您将要进行的下一次提交。它还有助于记住Git始终具有当前提交,命名为git diff --cached和(HEAD存储库除外),工作树工作树,您可以在其中查看文件,编译,编辑以及您对文件执行的任何其他操作。

最初,您的工作树,索引和--bare提交都匹配(当您第一次克隆存储库时)。您无法直接在索引中触摸文件,因此您可以在工作树中进行任何更改 - 甚至创建新文件 - 您可以在其中完成所有工作。然后,要将修改后的文件放回索引,请在路径上运行HEAD,以便Git将修改后的文件复制到索引中。要将新文件放入索引,您还可以在路径上运行git add

如果你出于某种原因让你兴奋并立即运行git add,Git会读取你当前的索引并将其打包为新提交。作为工作树快照,新提交将在索引中现在处于索引中的每个文件。

如果该状态匹配 git commit提交,HEAD只是说:&#34; Huhwha?为什么你现在尝试做出新的提交?&#34;所以大概是你在这一点上改变了索引中的某些东西。 git commit会向您显示索引中 git status提交不同的内容:这些是&#34;要提交的更改&#34 ;

合并

运行HEAD有时会显示有关索引的秘密。 索引中的每个条目实际上都有四个插槽,它们都已编号。通常情况下,您只会看到插槽零,这是为&#34;正常&#34;文件,准备提交。

合并旨在合并两个(有时更多,但让我们坚持两个)一组变更。例如,也许你和Bob开始使用相同的文件。然后,您对某些文件进行了一些更改,并git merge - 编辑并提交了源的新快照。与此同时,Bob对某些文件进行了一些更改 - 可能是相同的文件,甚至是git add - 并且已经提交,现在是时候将更改和Bob的更改结合起来。

要执行合并 - 合并动词某些文件--Git首先找到合并基础,即您和Bob同步的点。然后Git运行两个git add:一个从该合并基地到你的最新提交,一个从同一个合并基地到 Bob 最新承诺。这表明&#34;你改变了什么&#34;和#34; Bob改变了什么&#34;。

Git然后尽力合并这些更改(包括,在这种情况下,计算和关注文件重命名,并确定如果只有一个该怎么做您重命名了一些文件 - 但大多数合并冲突都不包含文件重命名,除非您编写了大量Java代码...)。但有时候,Git无法独立完成这项工作。在这种特殊情况下,Git会将合并工作交还给您,此时您可以看到索引中的所有插槽

索引槽1是Git存储文件的 base 版本的地方。这是您开始使用的常见版本。

索引插槽2是文件的git diffHEAD版本。 (它有时也被称为&#34;本地&#34;版本。)

索引插槽3是该文件的另一个或--ours(或有时是&#34;远程&#34;)版本。

这几乎就是它的全部内容:这三个版本保留了三个版本,最终你会得到&#34;未合并的路径&#34;。工作树中的文件包含Git的初始合并工作,以及冲突标记和--theirs--ours版本的一些混搭。如果您将--theirs设置为merge.conflictstyle,Git还会包含文件的 base 版本中的部分,这些部分存储在索引槽1中。现在它已经到了你解决合并。

一旦您找到了正确的解决方案并更新了文件的工作树版本,您就必须diff3路径。这将工作树版本存储到索引槽零中,消除了插槽1-3中的三个条目。由于插槽零保存正常的,即将提交的版本,因此文件现在可以提交了。

对于根本没有任何更改的文件,只是其中一人更改了某些内容,,其中Git认为它正确地合并了您的更改,而Bob&#39; s更改,那些文件已在工作树和(插槽零)索引中更新。如果结果与当前git add提交不同,HEAD会将文件显示为&#34;要提交的更改&#34;。

最后一位

我上面说过这是几乎所有它都有。关于索引槽的最后几件事要记住:

  • 某些广告位可能为空。假设您 Bob都添加了一个文件。在这种情况下,您将获得&#34;添加/添加冲突&#34;。该文件的哪个版本是常见的基本版本?当然没有:你们都添加了 new 文件。所以在这种情况下,基本插槽1是空的。

    如果删除文件并且Bob更改了文件,也会发生同样的情况。在这种情况下,git status插槽,插槽2为空,而插槽1和3保留基本版本和Bob的版本。由您自行决定是保留Bob的版本,保留文件,还是使用第三个版本,但三个插槽中只有两个被填充。

  • 如果您中的一个或两个重命名文件,则三个插槽中的文件版本可能来自先前提交中具有不同名称的文件。例如,您的输出显示:

    --ours

    此处没有冲突,但如果有, renamed: app/OldName.php -> app/NewName.php 的至少一个广告位将从app/NewName.php的其他提交版本中填充。

    当你去看旧版本时,这主要是重要的。如果在单独的克隆或工作树中检出其中一个尚未重命名文件的提交,或者如果使用app/OldName.php查看文件而未将其检出,则必须使用名称,只要它有旧名称。但是,如果您使用git show <commit>:app/OldName.phpgit checkout --ours将这两个版本中的一个提取到工作树中,则必须使用 new 名称,因为索引现在具有该文件以新名称存储。

  • 如果您 使用git checkout --theirsgit checkout --ours分别获取您或您的Bob版本的文件,则无法解决文件,但clobber Git尝试将它们合并到工作树中。如果您想要恢复Git尝试合并它们,请使用git checkout --theirs。请注意,所有这些都会覆盖文件的工作树版本,而只留下三个未解析的索引槽。

  • 奇怪的是,如果您git checkout -m从某个特定提交中获取旧版本的文件,将覆盖索引:它会复制提交内容。 s版本的文件索引槽零,破坏插槽1-3条目。该文件现在显示已解决!同样,您可以使用git checkout <commit-id> -- <path>恢复未解决的状态。 (当然会覆盖工作树版本。)

  • 同样,如果您使用git checkout -m错误地解决了该文件尚未完全的问题,您可以git add解决它 - 但是当然,这会覆盖工作树版本。如果您大部分时间都已完成解析,那么您也可以完成解析并重新git checkout -m结果。这将使用从工作树中新复制的版本替换slot-zero索引条目:文件保持已解析,但为下一次提交准备的版本将更改为最新的git add版本。

    < / LI>

答案 1 :(得分:0)

我通常会选择后一个并且没有面对并发现它。

我认为这取决于你将要实现的目标。

如果您想明确提及您已准确解决冲突的文件,您可以执行第一个。否则你可以做另一个。

答案 2 :(得分:0)

“要提交的更改”列表中指定的文件已经在暂存区域中(也称为索引)。
Git add是用于将您的工作放入索引的内容,它告诉git您希望它们包含在提交中。 因此,已经上传的文件的git add将是多余的。

只有在两个列表中列出文件时才需要在“待提交”列表中添加其他文件(如果您暂存文件然后再修改它们,则有时会发生这种情况。)