Git合并:通过在合并文件中包含相同的代码块TWICE而没有投诉,并行相同的添加没有冲突合并。为什么? [英] Git Merge: parallel identical additions are merged without conflict by including the same code block TWICE in the merged file without complaint. Why?

查看:103
本文介绍了Git合并:通过在合并文件中包含相同的代码块TWICE而没有投诉,并行相同的添加没有冲突合并。为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在解释提交顺序之前,让我粘贴Git的图像记录(使用SmartGit可视化历史记录):



...


$ b

两位开发人员对有问题的文件Developer 1和Developer 2进行了代码更改。



开发人员1




  • 检出图片中标记为 origin / staging 的分支(但这也是' origin / development '在检出时)
  • 添加了一个小代码块(见下文)

  • 提交s并且推送 - 这个推送被标记为' jon-dev-test-merge ',在
  • 上方对前一个提交的代码进行简单的空白改变,并提交/推送这个空白变化,标记为' jon-dev-test-merge-2 ',上面

  • 意识到他应该一直在努力一个独立的分支,所以重新开始并检出' origining / staging '(当时' origin / development ' )加入到一个名为'emonsondev'的新分支中,他将它推送到原始位置
  • 添加了相同的小代码块(NOT包括空格的变化)到这个新的分支(蓝线)(在标有' test-merge-sales '之前的某个提交中)

  • 看到Developer 2在' origin / development '分支上进行了修改,将 origin / development '合并到他的' jons_dev '分支中



我一段时间......

开发人员2


  • 检出图片中标记为' origin / staging '的分支(但它在检出时也是' origin / development ')

  • 将代码更改为另一个文件(与上面的Developer 1的代码更改完全无关) - 这是他本地开发机器上的工作副本

  • 将开发人员1的代码更改提取到 origin / development '分支到他的本地计算机,并合并到仅限本地的分支/工作副本中;合并成功无冲突。请注意,我们没有看到开发人员2合并到他的本地分支(因为他没有将该分支推送到原点),而只是从他的本地分支合并(参见下一个项目符号点)回到什么是'原始/开发'分支。
  • 合并到本地机器上从原点开始的跟踪开发分支中,并将合并推回原点 - 标记为 vladimir-test-merge ',
  • 上面


到目前为止,

这是我的问题。



在理解上述事件序列的过程中,我注意到一些奇怪的东西 - 没有从' origin / development '有问题的文件的分支需要合并到标有' origin / development '的合并中 - 其解释原来就是这样在这个文件中,对这个文件的相同修改,并行,不包括空格,因此都存在于这两个文件中文件,这样只需要从' jons_dev '分支进行更改(这就是执行合并的方式)。



然而,我注意到合并中的一些东西,涉及Git合并和确定冲突的方法,我无法解释。



为了以最简单的方式为我的问题展示问题,我首先创建了测试分支 - 'em-test-merge-sales'和' jon-dev-test-merge '/' jon -dev - 测试 - 合并-2 。然后,我检出了分支'test-merge-sales',并对此分支执行了两次单独的合并(取消了两次测试之间的合并)。

这两个合并的相关结果如下所示。 (附录:由于下面的问题的评论,第二个合并方案很容易解释,但是第一个合并方案仍然是一个问题。)




(0)BASE文件
$ b 在从两个合并中显示3路屏幕截图之前,文件的相关部分存在于' origin / staging '分支之前分支分支

基本档案



该图显示了该文件在开发者进行任何更改之前是如何查找这两个开发者的。



目前的评论,其中解释了每个开发人员到底在案例(1)中显示的合并前状态所做的代码更改。



正如您可以看到的从评论中,开发人员1添加了一个函数 - print_customer_part_order_history ,然后是第二个函数,即 print_sales_analysis_page ,到文件中的给定位置。同时,另一个分支已经在文件的同一位置添加了一个函数 - print_customer_part_order_history - 。代码是相同的,包括空格。



这是进入下面合并案例(1)的文件状态。






(1)从' jon-dev-test-merge '合并到' test-merge- sales '分支
$ b 注意:这种合并方案是我的主要问题。由于该问题下面的评论,与其他合并方案(下面#2)相关的问题已经得到解答。



此合并确实不会导致冲突。打开合并文件的差异查看器,以下是相关(合并)行的屏幕截图:



<点击这个 link to full-size image
strong>请注意,Git通过包含两个相同的函数(并行添加)来合并文件'print_customer_part_order_history()' - 没有合并冲突
。 (这是开发人员1并行添加到两个分支的代码片段。)因此,此函数在合并代码中出现两次。



注意: 'test-merge-sales '分支具有相同的空格 - 前导空格 - 在两个分支中突出显示的代码块中。

问题1:为什么Git认为没有合并冲突?两个代码块并行添加到文件中的相同位置。即使代码块是相同的,我认为这应该是一个合并冲突。






( 2)从' jon-dev-test-merge-2 '合并到' test-merge-sales '分支中

注意:由于此问题下面的评论,与此合并方案相关的问题已经得到解答。





< (点击这里 link to full-size image


合并代码的唯一区别在于开发人员1将前导空格更改为制表符。 然而,在这种情况下,只有空白区别,Git声明存在合并冲突。



问题2:为什么 - 仅限于空白区别 - Git会决定在一种情况下,没有合并冲突,另一种情况是,合并冲突?






我的两个问题是在上面指出的,关于Git如何处理合并和合并冲突。



谢谢! p>




附加
我添加了一个额外的屏幕截图 - strong> BEFORE
这两个分支与描述性文本分开,名为(0)基本文件部分。感谢!

解决方案

非常简单:当执行 merge 时,git分析两种尺寸都发生了变化的线条:




  • 如果变化间隔少于2行<引用即将推出> 这会产生冲突,因为更改很可能是关于同一事物的 ;
  • 如果更改超过2行,从双方被认为是两个不同的东西,添加的内容不被分析,只是添加到结果文件中。


由于LHS在第79行上添加了该函数,并且RHS在第69行中添加了它,git认为它是不同的内容,因为它超过了几行。






未来如何避免这种情况?




  • 继续阅读两个分支之间的 diff ,如果您阅读差异小心然后在合并中进行编辑;
  • 在团队中进行更多沟通(如果可能的话),这是正常情况,两名开发人员在两次写入完全相同函数单独的分支?







如何呈现冲突

在合并过程中,工作树文件会更新以反映合并的
结果。在对共同祖先的
版本进行的更改中,不重叠的版本(即,您更改了
文件的某个区域,而另一侧完全保留该区域,或反之亦然)是
逐字记录在最终结果中
。然而,当双方在同一区域内改变
时,Git不能随便选择一边
而另一边要求另一边
,并要求您通过将
双方留给该区域来解决。



I have a slightly tricky history in my Git log that I am trying to understand fully.

Before explaining the sequence of commits, let me paste images of the Git log (using SmartGit to visualize the history) for a file in question:

...

Shown is the Git history relevant to my question, with the irrelevant middle section snipped away.

Two developers made code changes to the file in question, Developer 1 and Developer 2.

Developer 1

  • checks out the branch labeled 'origin/staging' in the picture (but which was also 'origin/development' at the time it was checked out)
  • adds a small code block (see below)
  • commits and pushes - this push is labeled 'jon-dev-test-merge', above
  • makes a simple whitespace change to the code from the previous commit, and commits/pushes this whitespace change, labeled 'jon-dev-test-merge-2', above
  • realizes he should have been working on a separate branch, so starts over and checks out 'origing/staging' (at that time, 'origin/development'), into a new branch called 'jons_dev', which he pushes to, and sets up tracking for, on origin
  • adds the same small code block (NOT including the whitespace change) to this new branch (blue line) (into a commit sometime before the one labeled 'test-merge-sales')
  • later, seeing that Developer 2 has made a change on the 'origin/development' branch, merges 'origin/development' into his 'jons_dev' branch

Meanwhile...

Developer 2

  • checks out the branch labeled 'origin/staging' in the picture (but which was also 'origin/development' at the time it was checked out)
  • makes a code change to another file (completely unrelated to the code change from Developer 1, above) - this is in his working copy on his local development machine
  • pulls Developer 1's code changes to the 'origin/development' branch to his local machine and merges into a local-only branch/working copy; the merge succeeds without conflict. Note that we don't see Developer 2's merge into his local branch (because he did not push that branch to the origin), but only the merge (see next bullet point) from his local branch back into what was the 'origin/development' branch at that time.
  • merges into the tracked development branch from origin on his local machine, and pushes the merge back up to origin - labeled 'vladimir-test-merge', above

So far, so good.

Here is my question.

In the process of understanding the sequence of events above, I noticed something odd - no changes from the 'origin/development' branch for the file in question needed to be incorporated into the merge labeled 'origin/development' - whose explanation turned out to be that in this file, the identical changes to this file, made in parallel, not including whitespace, were therefore present in both files so that just the changes from the 'jons_dev' branch were required (and this is how the merge was performed).

However, I noticed something from the merge, involving Git's method for merging and determining conflicts, that I cannot explain.

To demonstrate the issue in the simplest way for my question, I first created the test branches indicated in the screenshots - 'test-merge-sales', and 'jon-dev-test-merge' / 'jon-dev-test-merge-2'. I then checked out the branch 'test-merge-sales' and performed two separate merges into this branch (cancelling the merge in between the two tests).

The relevant results from these two merges are shown below. (Addendum: due to comments below the question, the second merge scenario is easily explained. However, the FIRST merge scenario is still a question.)


(0) BASE file

Before showing a 3-way screenshot from the two merges, here is a screenshot of the relevant section of the file as it existed in the 'origin/staging' branch BEFORE the branches diverged:

The base file:

The image shows how the file looked for BOTH developers, BEFORE any changes were made by either developer.

There are also comments present, which explain exactly what code changes were made by each developer to arrive at the pre-merge state shown in Case (1), below.

As you can see from the comments, Developer 1 adds a function - print_customer_part_order_history, followed by a second function, print_sales_analysis_page, to a given spot in the file. In parallel, the other branch has added to it a single function - print_customer_part_order_history - in exactly the same place in the file. The code is identical, including whitespace.

This is the state of the file moving into Merge Case (1), below.


(1) Merge from 'jon-dev-test-merge' into the 'test-merge-sales' branch

Note: This merge scenario is my main question. Due to comments below the question, the question associated with the other merge scenario (#2, below) is already answered.

This merge did not result in a conflict. Opening a diff viewer for the merged file, here is a screenshot from the relevant (merged) lines:

(Click this link to full-size image)

Note that Git merged the files by including BOTH identical functions (added in parallel) 'print_customer_part_order_history()' - with no merge conflict. (This is the code snippet that Developer 1 added, in parallel, to the two branches.) Therefore, this function appears twice in the merged code.

Note: the 'test-merge-sales' branch has the same whitespace - leading spaces - in the highlighted code block in both branches.

Question 1: Why did Git decide there was no merge conflict? Two blocks of code were added in parallel at the same location in the file. Even though the blocks of code are identical, I would think that this should be a merge conflict.


(2) Merge from 'jon-dev-test-merge-2' into the 'test-merge-sales' branch

Note: Due to comments below this question, the question associated with this merge scenario is already answered.

(Click this link to full-size image)

The only difference in the code being merged is that Developer 1 changed leading spaces to tabs. However, in this case, with only the whitespace difference, Git has declared there is a merge conflict.

Question 2: Why - with only a difference in whitespace - would Git decide that in one case, there is no merge conflict, and in the other case, that there is a merge conflict?


My two questions are identified above, regarding how Git handles merges and merge conflicts.

Thanks!


ADDENDUM I have added an additional screenshot - the relevant text of the file BEFORE the two branches diverged - along with descriptive text, in the section called "(0) Base File". Thanks!

解决方案

It's pretty simple: when doing a merge, git analyze the lines that have changed on both size:

  • If the changes are less than 2 lines apart(Reference is coming soon) this will create a conflict, since the changes are very probably about the same thing;
  • If the changes are more than 2 lines apart the content from both side is considered as two different things and the content added is not analyzed, just added to the resulting file.

Since LHS added the function on line 79 and RHS added it on line 69 git thought that it was different content as it was more than a very few lines apart.


How to avoid this in the future?

  • Proceed to a diff between the two branches, this will be visible if you read your diff carefully and then edit it in the merge;
  • Communicate more within your team (if possible), is this normal that two developer wrote the exact same function in two separate branches?

From the git merge doc (emphasis is mine)

HOW CONFLICTS ARE PRESENTED

During a merge, the working tree files are updated to reflect the result of the merge. Among the changes made to the common ancestor’s version, non-overlapping ones (that is, you changed an area of the file while the other side left that area intact, or vice versa) are incorporated in the final result verbatim. When both sides made changes to the same area, however, Git cannot randomly pick one side over the other, and asks you to resolve it by leaving what both sides did to that area.

这篇关于Git合并:通过在合并文件中包含相同的代码块TWICE而没有投诉,并行相同的添加没有冲突合并。为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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