【问题标题】:Do all diffs get copied to source branch from destination branch during git merge?在 git 合并期间是否所有差异都从目标分支复制到源分支?
【发布时间】:2015-10-22 20:42:08
【问题描述】:

我一直在尝试获取从 dst 分支到 src 分支的所有差异。我通常遵循以下工作流程。

git checkout dst (switch to dst branch)
git pull dst     (fetch and merge changes on remote dst to local dst)
git checkout src (switch to src branch)
git merge dst    (pull all diffs from dst to src?)
[optionally if merge conflicts occur, I resolve merge conflicts and do]
git commit 

但是,在合并之后,我发现并非所有差异都复制到了我的 src 分支。例如,git diff src:somefile dst:somefile 在 src 和 dst 之间的 somefile 中显示了添加内容,但是这些更改没有复制到 src,我希望在合并后发生。

我考虑合并的方式有什么根本错误吗?如何获取从 dst 到 src 分支的所有差异(添加和删除)。

【问题讨论】:

标签: git version-control merge


【解决方案1】:

我考虑合并的方式有什么根本错误吗?

是的:

...git diff src:somefile dst:somefile...

这不是合并所做的。合并一个分支并不意味着“让我的文件和他们的一样”。

提交图

让我们从绘制提交图开始:

... <- B <- C <- D   <-- branch

在这里,大写字母代表提交 ID,即像 f931ca0... 这样的 40 个字符的 SHA-1 ID 之一。每个提交记录一个源代码树(例如,您可以使用&lt;id&gt;:path 查看该文件在该提交 ID 的内容)。它还记录一些父提交 ID:通常只有一个 ID,但有时会超过一个(“合并”提交),很少有零父 ID(“根”提交)。

branch 只是您的一个分支的名称,它包含提交 ID D,即分支名称“指向”该分支上最尖端的提交 D。提交D 指向C,后者又指向B,以此类推。

一个图变成“branch-y”或“branched”——不幸的是,这个术语与我们用来谈论一个分支的 name 的术语相冲突——当几个不同的提交指向同一个时父母。请记住,这里的箭头都指向左,即使它们指向左上或左下;并且由于文本样式的图表没有箭头空间,我们将在这里画一条线,如-\/

... B - C - D   <-- br1
      \
        E - F   <-- br2

这里分支br1 的尖端是commit D,分支br2 的尖端是commit F。您可以使用git rev-parse 向 git 询问实际 ID,具体的 40 个字符的东西:

$ git rev-parse br1
e59f6c2d348d465e3147b11098126d3965686098

例如。同样,我们说br1“指向”提交D,它又指向C,又指向B,以此类推。同时br2 指向FE 又指向B

任何给定分支名称指向的提交是该分支的“提示提交”。当您向分支添加新提交时,git 通过使新提交存储上一个提示的 ID 作为其父 ID 来执行此操作,一旦新提交完成并安全地存储在存储库中,更改存储在分支名称中的 ID .也就是说,如果你向br1添加一个新的提交,新的提交G会指向D,而git会让br1指向G

... B - C - D - G  <-- br1
      \
        E - F   <-- br2

无论我们随着时间的推移提交了多少新的提示,提交B 仍然特别有趣。在图论术语中,这里的概念是“可达性”:commit B (总是)可以从 both 分支提示访问。

合并

那么,git merge 就是这样做的。你给它两个分支提示 ID - 其中一个是你现在所在的分支,另一个是你命名的分支 - 它:

  1. 标识从两个分支提示可到达的最近提交(这是“合并基础”);
  2. 从合并基础到当前分支提示进行差异;
  3. 从合并基础到另一个技巧的差异;
  4. 结合这两个差异来查看“双方”在哪里进行了相同的更改;
  5. 应用在步骤 3 中找到的更改,而不重新应用在步骤 4 中找到的组合更改;和
  6. 如果一切顺利,使用 两个 父级进行新的提交,这两个父级都是分支提示。

冲突发生在步骤 2 和 3 中发现的更改影响同一文件的同一区域,但完全相同相同(因此无法通过步骤 4 减去)。如果发生冲突,git 会让你解决它们;当你做最后的git commit 时,这仍然会产生同样的“合并提交”。

现在,假设在B-C-D-G 行中的某个地方,有人修改了路径README.txt 以在第一行包含一个感叹号。同时在B-E-F 行中,没有人对README.txt 这样做。最终的合并提交将保留此处所做的更改,但如果您将 br1:READMEbr2:README 进行比较,则会存在差异:br2 中的第一行将没有感叹号。这是因为合并的更改(base-to-br2)不会改变这一点;保留的更改(base-to-br1)确实如此。我们不希望将 base-to-br1 更改删除,我们只希望尚未存在的更改(未在“双方”进行)添加了

无论如何,让我们在最后的合并提交H

... B - C - D - G - H  <-- br1
      \           /
        E ----- F      <-- br2

现在br1:README!br2:README 没有。

简而言之,在合并之后,没有理由期望任何两个文件在新的分支提示中匹配。如果所有文件都必须完全匹配,则您将清除 br1 上的所有工作,仅将其替换为 br2 上的工作。

【讨论】:

    猜你喜欢
    • 2014-04-21
    • 2019-07-25
    • 2020-02-17
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多