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
Meanwhile...
Developer 2
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:
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?
diff
between the two branches, this will be visible if you read your diff carefully and then edit it in the merge;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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With