在git合并过程中,所有差异是否从目标分支复制到源分支? [英] Do all diffs get copied to source branch from destination branch during git merge?

查看:1377
本文介绍了在git合并过程中,所有差异是否从目标分支复制到源分支?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  git checkout dst(切换到dst分支)
git pull dst(fetch将远程dst上的更改合并到本地dst)
git checkout src(切换到src分支)
git合并dst(将所有差异从dst拖到src?)
[如果合并冲突发生,我解决合并冲突,并做]
git commit

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



我在考虑合并的方式时是否存在根本性错误?如何获得从dst到src分支的所有差异(增加和删除)。

解决方案

我在考虑合并的方式是否存在根本性错误?

是:


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


这不是合并的操作。合并分支并不意味着使我的文件与他们的文件相同。



提交图



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

  ... <-B <-C <-D < ;  - 分支

这里,大写字母表示提交ID,即其中一个像 f931ca0 ... 这样的大的丑陋的40个字符的SHA-1 ID。每个提交都会记录一个源代码树(例如,您可以使用< id>:path 来查看该文件的内容以及该提交ID)。它还记录了一些父提交ID:通常只有一个ID,但有时不止一个(合并提交),很少有零父ID(根提交)。

分支就是您的其中一个分支的名称,它包含commit-ID D ,即分支名称指向该分支上的最小提交 D 。提交 D 指向 C ,它指向 B ,等等。



一个图形变成分支-y或分支 - 这个术语不幸与我们用来讨论分支的名称 - 当几个不同的提交指向同一个父代时。请记住,这里的箭头都指向左边,即使它们指向左右或左右,因为文本样式的图表没有箭头的空间,所以我们只画一条线,比如 - 或者 \

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

在这里,分支 br1 的提示是commit D ,并且分支的尖端 br2 是提交 F 。使用 git rev-parse

<$ p可以向git请求实际的ID,具体的40个字符的东西$ p> $ git rev-parse br1
e59f6c2d348d465e3147b11098126d3965686098

for实例。我们再次说, br1 指向commit D ,它指向 C ,它指向 B ,依此类推。同时 br2 指向 F ,它指向 E 指向哪个点返回到 B



任何给定分支名称指向的提交是提交提交科。当你向一个分支添加一个新的提交时,git通过使新的提交存储上一个提示的ID作为它的父ID来做到这一点,并且一旦新的提交被确定并安全地存储在存储库中,改变存储在分支名称中的ID 。也就是说,如果您向 br1 添加新提交,新提交 G 将指向 D ,git将使 br1 指向 G

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

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



合并



所以,下面是 git merge 的确。你给它两个分支提示ID--其中一个是你现在的分支,另一个是你指定的分支 - 和它:


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

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

    现在,假设在 B - C - D - G 行,有人修改了路径 README.txt 以在第一行包含感叹号。同时在 B - E - F 这到 README.txt 。最后的合并提交将保留这里所做的更改,但如果您比较 br1:README br2:README 有区别: br2 中的第一行不会有感叹号。这是因为被合并的变更(base-to - br2 )不会改变这个;保留的变化(基于 - < - c $ c> br1 )。我们不希望基于 - br1 更改来取消 ,我们只想要尚未存在的更改(尚未完成在任何情况下,让我们在最后的合并提交中绘制 H

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

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



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


    I have been trying to get all the diffs from a dst branch to a src branch. I usually follow the following workflow.

    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 
    

    However, after merge, I am seeing that not all diffs are copied to my src branch. For instance git diff src:somefile dst:somefile shows additions in somefile between the src and dst, however these changes are not copied over to src which I am expecting to happen after merge.

    Is there something fundamentally wrong in the way I am thinking about merge? How do I get all the diffs (additions and deletions) from dst to src branch.

    解决方案

    Is there something fundamentally wrong in the way I am thinking about merge?

    Yes:

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

    This isn't what merge does. Merging a branch does not mean "make my files the same as theirs".

    The commit graph

    Let's start with a bit of commit-graph drawing:

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

    Here, the uppercase letters stand in for a commit ID, i.e., one of those big ugly 40-character SHA-1 IDs like f931ca0.... Each commit records a source tree (this is how, for instance, you can use <id>:path to see that file's contents as of that commit ID). It also records some parent commit ID(s): usually just one ID, but sometimes more than one (a "merge" commit) and rarely zero parent IDs (a "root" commit).

    The branch is just the name of one of your branches, and it contains commit-ID D, i.e., the branch name "points to" the tip-most commit D on that branch. Commit D points back to C, which points back to B, and so on.

    A graph becomes "branch-y" or "branched"—this term unfortunately collides with the same term we use to talk about the name of a branch—when several different commits point to the same parent. Remember that the arrows here all point left-ish, even if they point up-and-left or down-and-left; and since text-style graphs don't have room for arrows, we'll just draw a line like - or \ or / here:

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

    Here the tip of branch br1 is commit D, and the tip of branch br2 is commit F. You can ask git for the actual ID, the concrete 40-character thing, using git rev-parse:

    $ git rev-parse br1
    e59f6c2d348d465e3147b11098126d3965686098
    

    for instance. Again, we say that br1 "points to" commit D, which points back to C, which points back to B, and so on. Meanwhile br2 points to F which points to E which points back to B.

    The commit that any given branch-name points to is the "tip commit" of that branch. When you add a new commit to a branch, git does this by making the new commit store the previous tip's ID as its parent ID, and once the new commit is finalized and safely in the repository, changing the ID stored in the branch-name. That is, if you add a new commit to br1, the new commit G will point back to D, and git will make br1 point to G:

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

    No matter how many new tip commits we make over time, commit B remains especially interesting. In graph theory terms, the concept here is "reachability": commit B is (always) reachable from both branch-tips.

    Merge

    So, here's what git merge does. You give it two branch tip IDs—one of these is the branch you're on now, the other is the one you name—and it:

    1. identifies the nearest commit reachable from both branch tips (this is the "merge base");
    2. does a diff from the merge-base to the current-branch tip;
    3. does a diff from the merge-base to the other tip;
    4. combines these two diffs to see where "both sides" made the same changes;
    5. applies the changes found in step 3, without re-applying the combined changes found in step 4; and
    6. if all goes well, makes a new commit with two parents, those two parents being both branch-tips.

    Conflicts occur wherever the changes found in steps 2 and 3 affect the same region of the same file, but are not exactly the same (hence can't be subtracted away via step 4). If conflicts occur, git makes you resolve them; when you do your final git commit this still makes the same kind of "merge commit".

    Now, suppose that somewhere along the way in the B-C-D-G line, someone modified the path README.txt to include an exclamation point in the first line. Meanwhile in B-E-F line, nobody did this to README.txt. The final merge commit will retain the change made here, but if you compare br1:README to br2:README there will be differences: the first line in br2 won't have the exclamation point. That's because the changes being merged-in (base-to-br2) don't change this; the changes being retained (base-to-br1) do. We don't want base-to-br1 changes to get removed, we only want changes that aren't already present (have not been made on "both side") to be added.

    In any case, let's draw in the final merge commit H:

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

    Now br1:README has the ! but br2:README doesn't.

    In short, there's no reason to expect, after a merge, any two files to match in the new branch-tips. If all the files had to match exactly, you'd wipe out all the work on br1, replacing it with only the work on br2.

    这篇关于在git合并过程中,所有差异是否从目标分支复制到源分支?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆