2

Merging master, after being pulled from origin, with my current branch that has local commits, seems to always create conflicts with files that only I have edited before in that same branch. I would normally expect these to be automatically resolved.

To illustrate, here's my workflow (I run the commands in the console):

Assume there's a branch named "branch_a" in which commits have been previously made and merged into master, and it is now in sync with master.

  • (After making changes in branch_a) git add . then git commit -m "made changes"
  • (By now some time has passed and master is ahead) git checkout master.
  • git pull.
  • git checkout branch_a.
  • git merge master. (Here I get merge conflicts of my latest changes with previous changes I made in branch_a, which were already merged into master)

Is there an obvious issue with my workflow I am not seeing? And, is it expected that git would automatically resolve these conflicts given that the only changes made to a file were committed on the same branch but different point in time?

dsosa
  • 71
  • 5
  • What are some specific merge conflicts you have observed using this workflow? – Philip Wrage Nov 18 '20 at 19:16
  • 1
    I would use `git rebase` instead of `git merge`. [When do you use Git rebase instead of Git merge?](https://stackoverflow.com/a/804156/10951752) And if you changed something in the same file, you can get a conflict. – flaxel Nov 18 '20 at 19:23
  • @PhilipWrage They're conflicts with the content of a file. Say I edited line 5 of a file, committed it, and made a pull request which then got merged with master remotely. In that same branch, I edit line 5 again with different content, commit it, checkout to master, pull the changes from master (which have my first line 5 change), switch to the working branch, and merge master. After that last merge, it would then ask me to manually solve a conflict in line 5. Does that help? – dsosa Nov 18 '20 at 19:35
  • Yes, I believe you've answered your own question with that example. As mentioned by @flaxel, if you modify the same file you can get a conflict, even if you are the only person on your team modifying that file. – Philip Wrage Nov 18 '20 at 19:42
  • Is it on GitHub ? Can we check the history of your repo ? – LeGEC Nov 18 '20 at 20:06
  • I see. I completely thought it would automatically take whichever change was ahead given it's comparing it with a earlier commit already on that branch. Thanks for your answers. – dsosa Nov 18 '20 at 20:31

2 Answers2

1

I completely thought it would automatically take whichever change was ahead given it's comparing it with a earlier commit already on that branch.

This is a perfectly reasonable assumption based on what git log shows you. Unfortunately, git log is lying to you by omission. By default git log shows commits as being in a straight line ordered by time.

commit b8502a5b1efcb971f90d605517d3f93d0a0951de
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Sat Nov 14 12:00:00 2020 -0800

    Add more foo

commit 20969b1e307efd6152ef43165ae0d11aceb2a2b5
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Fri Nov 13 12:00:00 2020 -0800

    Fix foo

commit 83693247615e3f528d07f33d955c9a3fbdee2791
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Thu Nov 12 12:00:00 2020 -0800

    Add more foo

commit 8b4a4381ebe79091ccdcf2ed1214a55c94189cbf
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Wed Nov 11 12:00:00 2020 -0800

    Change foo

commit ad5f84597211909ff1f1adc3754271817556f7f7
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Tue Nov 10 12:00:00 2020 -0800

    Add foo

All the commits are working on the same part of the code. If they change the same lines it should just choose the newest commits, right?

git log --graph --decorate --all will show you the true history.

* commit b8502a5b1efcb971f90d605517d3f93d0a0951de (HEAD -> master)
| Author: Michael G. Schwern <schwern@pobox.com>
| Date:   Sat Nov 14 12:00:00 2020 -0800
| 
|     Add more foo
|   
| * commit 20969b1e307efd6152ef43165ae0d11aceb2a2b5 (feature)
| | Author: Michael G. Schwern <schwern@pobox.com>
| | Date:   Fri Nov 13 12:00:00 2020 -0800
| | 
| |     Fix foo
| | 
* | commit 83693247615e3f528d07f33d955c9a3fbdee2791
| | Author: Michael G. Schwern <schwern@pobox.com>
| | Date:   Thu Nov 12 12:00:00 2020 -0800
| | 
| |     Add more foo
| | 
| * commit 8b4a4381ebe79091ccdcf2ed1214a55c94189cbf
|/  Author: Michael G. Schwern <schwern@pobox.com>
|   Date:   Wed Nov 11 12:00:00 2020 -0800
|   
|       Change foo
| 
* commit ad5f84597211909ff1f1adc3754271817556f7f7
  Author: Michael G. Schwern <schwern@pobox.com>
  Date:   Tue Nov 10 12:00:00 2020 -0800
  
      Add foo

Now we can see the changes happened in different branches. While b8502a happened after 20969 in time they happened in parallel in space. Branches really branch and that's fundamental to understanding Git. Unfortunately, Git hides that.

Git assumes work in branches was uncoordinated. This lets many people work on the same code independently, or one person work on many things at the same time, without having to keep track of who is changing what. That will be resolved by Git when merging.

Because of this, Git cannot preference changes in one branch vs another. While Git can assume that b8502a was written with knowledge of 836932, they're on the same branch, it cannot assume b8502a was written with knowledge of 20969b nor 8b4a43; even though b8502a is newer than both 20969b and 8b4a43 they're on different branches.

Even if the author is the same, Git does not assume it can preference newer changes on different branches. To do so would assume the author is keeping all their changes in all their branches in mind while they're working, and that defeats the point of branching.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Thanks for the elaborate response! That command is very helpful indeed. However, if I understand correctly, and my apologies if I wasn't clear enough with my explanation, I think your answer assumes that changes to the file were committed in more than one branch. Are you also indicating I would get conflicts even if _commits to changes in the file happened only in one branch_? Because my issue is when I merge master to a branch, the conflicts are between changes that were committed in that branch, which git should already know of given your explanation. – dsosa Nov 20 '20 at 13:46
  • @dsosa No, you won't get conflicts between commits in the same branch. That should be impossible. Check that you haven't misinterpreted something. The conflict markers will indicate where both changes came from. If you could show us the conflict markers, and the relevant `git log --oneline --graph --decorate` covering those commits, we can piece together what happened. – Schwern Nov 20 '20 at 20:04
  • Yesterday I changed a line in a file, committed it in branch "trunk", pushed it to origin "trunk", made a PR in ADO, got approved and merged into origin master. Today, to test it out, I switched to master locally, ran `git pull` (only my changes were there), switched to "trunk", changed content of the same line and file, committed it to "trunk", ran `git merge master` and got "Automatic merge failed" with conflicts in that file for that line. One marker says head and the other one master. Top of log is: `* c47e0296 (HEAD -> trunk) changed foo` `* d991b08a (origin/trunk) added foo` – dsosa Nov 20 '20 at 22:02
  • @dsosa The conflict markers show you have a conflict between your branch (HEAD) and a different branch (master). But it's difficult to follow as a comment. Please edit your question with the information. And please show the full conflict markers and enough of the graph so we can see how HEAD and master are related. You can obscure the content and commit messages. – Schwern Nov 21 '20 at 00:23
0

To go off of the answers in the comments (thanks @philip-wrage): merge conflicts happen when you are trying to merge two branches whose commits touch the same lines or make some changes which are not mutually exclusive. The words I'm using here are really vague, so it'd be a good idea to read up on the topic: https://www.atlassian.com/git/tutorials/using-branches/merge-conflicts.

If you are specifically interested in auto-resolving these conflicts so that your local changes always take precedence, this stackoverflow post might be useful.

Ali Dowair
  • 168
  • 9
  • 2
    You can also get conflicts if the surrounding lines, the context, change. If one branch changes line 5 and the other changes line 6 it may result in a conflict. Git has several different merge strategies and will take a guess at which one is the best. Ultimately, Git does not understand the code. A conflict is Git's way of saying "I need a human to tell me which one to pick." – Schwern Nov 18 '20 at 22:20