52

I'm a beginner at collaborative development, I started learning about merge conflicts. And I have this question.

Is it possible for a developer to deliberately postpone merging because he doesn't want to be the one resolving a potential conflict?

If this isn’t the solution, what are the strategies that work?

14
  • 54
    Oddly enough, my strategy was (and still is, to some extent) the opposite: to check in early and often, before a conflict could occur. If a merge conflict happened, it would happen to the other guy, not me. Nowadays I'm a bit more pragmatic (and nicer to my fellow programmers); I tell people what I'm working on, so that if they need to work on the same file, we can coordinate our efforts. Sep 28, 2020 at 3:04
  • 13
    You don't usually postpone a merge to avoid a merge conflict. Generally you know one is coming and you hurry up your code to get it in before. Although occasionally a lead/manager may know one is coming due to your code and ask you to wait to merge because the other PR is more important. In fact I was the lead asking for this just the other day- I was changing a cache implementation to be vectorized (work on multiple inputs at once). Someone else was moving the cache around. I needed my stuff to do perf testing for an important meeting, so I told him to wait until I landed. Sep 28, 2020 at 3:17
  • 6
    I don't understand. Surely the longer you wait with merging, the higher the risk it is up to you to resolve a merge conflict? As @RobertHarvey mentions: I try to merge my work before the other developer, so that they are faced with the merge conflict, not me.
    – gerrit
    Sep 28, 2020 at 13:14
  • 2
    Avoiding merge conflicts is good and right, but sometimes they still happen even with the best of intentions. And in those cases good tools help A LOT. I'm sorry that I'm about to sound like an advertisement, but I'm a big fan of Beyond Compare (not affiliated, just a fan). It's really head and shoulders above anything else I've come across. Somehow their magical algorithms can solve (or partially solve) many conflicts that no other tool can. And for the rest you have the ability to manually align the files which also helps a TON. No idea why nobody else has implemented that...
    – Vilx-
    Sep 28, 2020 at 22:34
  • 4
    Funny, I'm the opposite - I hold off sometimes so that I can be the one to fix the conflicts cos I know some of the gung ho devs I've worked with will just blindly hit the "resolve using mine" button, lose some of my changes thereby breaking what I was working on and then tell management "oh, that broken thing is CJ's problem" leaving the obvious impression...
    – Caius Jard
    Sep 29, 2020 at 7:36

11 Answers 11

107

Oh god yes.

I broke the build my first time. Made me so gun shy I was hiding versions in folders. Of course delaying my check-ins just made things worse. I was in hell until I figured out what I needed.

I needed a safe place to play.

I created my own toy project so that I could deliberately cause merge conflicts. Learned how to fix them the hard way. Soon people were asking me to help them fix their problems. All because I took the time to play with a toy.

Check in often. It will keep what needs fixing small. But take the time to learn your tools so you can see trouble coming.

16
  • 4
    Nice answer. I would only add that my experience with Git has gotten better over time. I never figured out whether it was because I understood Git better over time, or because the Visual Studio Git client got better over time. And I never got around to buying the 500 page Git book.. One of my bucket list goals is to never, ever have to do a rebase. So far, so good. My best advice? If you keep your files small and your dependencies spare, merge conflicts will never be a problem, even if one happens. Sep 28, 2020 at 2:59
  • 3
    And yes, I did the same exercise, creating a sandbox where I could deliberately cause merge conflicts and fix them. I'm not sure I would have ever wrapped my head around them otherwise. Sep 28, 2020 at 3:01
  • 4
    @RobertHarvey, what's your argument against rebasing? It's my go to strategy which produces much cleaner Git history (especially when fast-forward merging back into trunk).
    – Andy
    Sep 28, 2020 at 16:22
  • 3
    @RobertHarvey, rebasing is not that complicated, trust me (and it enables you to do all cool stuff such as squashing, moving, and cleaning up commits). Definitely worth the effort. If there's a rule of thumb of working in feature branches, one should never combine merging and rebasing target branch into the feature branch you're working on. Unless you do that, even if you choose rebasing the complexity is pretty much the same as merging. Choose one strategy for a feature branch and stick to it. :)
    – Andy
    Sep 28, 2020 at 16:36
  • 3
    @Andy: I appreciate your sympathy to my plight, but we already have a commit/merge strategy in place and it works just fine. And yes, we do follow it consistently. Sep 28, 2020 at 16:38
27

In general, individual developers will be responsible for merging their own work. Delaying things only means it's more likely for others to get code into your merge target, making the merge worse.

3
  • 1
    this is the ideal setup, but it's not in place everywhere and there can often be process steps where another person might take over. E.g. some places have code reviews set up such that the reviewer can do small modifications and after they are done merges the feature branch. If the original developer didn't wanna deal with any merge conflicts they could try to simply "forget" merging master and hope that the reviewer deals with them instead of playing the card back at him. Just as an example. Are there people, especially juniors, who try stuff like that, yes. Is it a good strategy, no. Sep 28, 2020 at 3:06
  • reviewer may just tell you to merge master into your branch and then resubmit,
    – Jasen
    Sep 28, 2020 at 9:49
  • 3
    I have a fairly strict process in my workflow. I commit, then pull the latest master, then merge the master into my branch, fix any issues, then commit again. I'm not afraid of merge conflicts because I can always cross-check with my original commit if things get confusing. In practice, merge-conflicts are usually small and easily solved because two developers as a rule won't be stepping on one another's toes. The odd line here or there is easily resolved.
    – Rowan
    Sep 28, 2020 at 14:03
23

Extreme Programming is (partly) based on the idea that if things are "hard" or "scary", we simply aren't practicing them enough.

That's the thing: practice makes perfect.

So, the approach that Extreme Programming takes, is that things that are hard should not be pushed back as far as possible to avoid them. Instead, they should be embraced and done as early and as often as possible so they become familiar and lose their "scariness".

Not only does doing things often make them familiar and gives you practice and experience, so that you get better at solving the problems you encounter, but at the same time, the problems get smaller!

Releasing is scary because after a year, you have forgotten all the steps and scripts and magic folders? Don't just release once a year, release every week! Not only will it help you remember all the arcane scripts, all the steps, all the magic folders, it will also force you to think very hard about whether all those arcane manual steps are really needed or if they can be either eliminated or automated.

Code review is scary because there is always a mountain of code, and it takes endless hours? Do it continuously while you program (pair programming), that way, there is always only one line of code to review and the review only takes half a second or less.

Merging is scary because there are always huge merge conflicts and it takes hours to resolve them? Merge as often as you can! Again, not only will you get better at merging by doing it more often, but also, the merge conflicts get smaller! If everybody on your team merges 5-10 times a day, how far can your code really diverge in that time frame?

So, let's say by merging often and gaining practice and experience, you become 3 times better at merging. (It's probably going to be even more than that.) Also, let's say that by merging more often, your merge conflicts become 3 times less frequent and 3 times smaller.

That means that merging becomes almost 100 times less scary.

That is the XP approach, at least. It works even if you don't follow all practices of XP, although of course all the practices are meant to work together and link into each other and reinforce each other.

23

Yes and no

In my experience, merge conflict are a result of not communicating. If you plan properly, you and your colleagues shouldn't have many merge conflict.

The reason people 'fear' them, is because it can be a puzzle to un-conflict them. Sometimes it's just 1 or 2 lines, but it could be a lot, multiple conflicts in one file, because you and a colleague had to work in the same file, both working/refactoring some code. Those can take time to unmangle again and if you do it wrong, the work of party A, B or both stops working properly. The bigger the conflict, the more testing needs to happen afterwards, and most are not fan of testing that extensively.

There are a few way to minimize merge conflicts:

  • Make small PRs/commits; Just make tiny adjustments. The smaller the changeset, the less merge conflicts can exists in the first place.
  • Make small PRs/commits; Small PRs can be merged more quickly, that means they dont get outdated that quickly. This also means that others:
  • Merge the master(or leading working branch) often into your work. You'll get new code (and possibly some fixes) more often and can reckon with others.
  • Talk about who does what in a job, possible decided that feature A is easier if B is made.
8
  • 6
    This ^. Extensive merge conflicts are a clear sign something went terribly wrong in coordinating tasks. My team generally lump related tasks on the same developer so that the person most familiar with the code is the one doing it and nobody is picking up adjacent tasks and accidentally stepping on code being written for another task. Asking if a developer fears merge conflicts is like asking if a dancer is afraid of stepping on their partner's toes...it can happen, but it's a coordination problem and experience will iron out most of it.
    – Rowan
    Sep 28, 2020 at 14:06
  • 2
    "People, especially people who are familiar with reserved checkouts, often wonder how often conflicts occur if unreserved checkouts are used, and how difficult they are to resolve. The experience with many groups is that they occur rarely and usually are relatively straightforward to resolve. The rarity of serious conflicts may be surprising, until one realizes that they occur only when two developers disagree on the proper design for a given section of code; such a disagreement suggests that the team has not been communicating properly in the first place." (from the gnu CVS manual) Sep 28, 2020 at 15:23
  • 6
    I do not believe that merge conflicts are a result of not communicating. Merge conflicts are not a "problem." They are just something that happen in development.
    – emory
    Sep 28, 2020 at 19:07
  • How should one avoid conflicts in situations where e.g. a safety-check is redundantly performed at two places in the code, and two people who are working on the code each decide to eliminate one of them? Either removal would be entirely appropriate if performed in operation, but merging the changes would result in the program being left with no safety checks.
    – supercat
    Sep 28, 2020 at 19:32
  • I never state they never happen :) But the bigger ones can often be reduced to communication
    – Martijn
    Sep 28, 2020 at 20:23
12

The difficulty of a merge grows with the square of the number of merge conflicts. So it doesn't matter whether you fear merge conflicts, you resolve them as soon as you can.

Where I work, you branch from the development branch, make changes to your branch, and create a pull request. If the pull request has merge conflicts then it is your job to merge the current developement branch into your branch to remove the conflicts. So there's no way that merge conflicts in your code go away without you resolving them.

Best strategies are:

  1. If your development takes time, merge the development branch into your branch from time to time. That keeps the merges, even with conflicts, a lot easier.
  2. In cases like bug fixes, where 90% of the work is finding the problem and 10% fixing it, create your branch only when you start fixing, that reduces the chances of conflicts.
  3. If someone wants to do some refactoring that is likely to create large numbers of conflicts, organise things so this doesn't happen while other long-term branches are opened. Pick a time when all big changes are merged and do the refactoring as quick as possible.
  4. Don't add new functions at the end of the source file or header file, but at the place where they belong. That's because if we both add things at the end of a file, we'll have an avoidable merge conflict.
  5. If you use an IDE that makes changes on its own, make sure that all developers set up their IDE in an identical way, to avoid unnecessary changes leading to unnecessary conflicts.
  6. If you have files that are modified by tools creating lots of irrelevant changes, only start changing such files after agreeing with others that they are not touching them at the same time.
2
  • With #4, it's also the case that more experienced developers are able to easily recognize trivial merge conflicts at the bottom of a file and have the experience using tools to resolve them quickly, while beginners may take more time to understand what's happened and figure out how to use the version control system to resolve it. "Oh, we both added new strings to the bottom of the string file" is not a big deal if you've seen it a few dozen times, and potentially panic inducing the first time your commit fails. Sep 29, 2020 at 6:15
  • The difficulty of a merge grows with the square of the number of merge conflicts. Seriously? Is that all? From my experience, "The difficulty of a merge grows exponentially with the number of merge conflicts" is a better way to say it. Check in often, merge often. Sep 29, 2020 at 10:34
6

A nice tip to make merge conflicts easier.

git config --global merge.conflictstyle=diff3. Without this set you will see your code and their code only. With it being set you will also see the original. For more info see this StackOverflow answer. Here's an example. The first is what it would look like normally.

<<<<<<< HEAD
log.info(String.format("%s entered password: %s on attempt %d", user, password, attempt));
=======
log.info(user + " entered password: " + mask(password));
>>>>>>> blah

Compare to this which is what looks like with it on.

<<<<<<< HEAD
log.info(String.format("%s entered password: %s on attempt %d", user, password, attempt));
||||||| merged common ancestors
log.info(user + " entered password: " + password);
=======
log.info(user + " entered password: " + mask(password));
>>>>>>> blah

Now it is more clear. Comparing the middle (the original) to the bottom (the incoming) we see that they masked the password. We should do that in ours also.

log.info(String.format("%s entered password: %s on attempt %d", user, mask(password), attempt));
5

Do developers fear merge conflicts?

Hell yeah. It didn't help that one of my two senior engineers was built like a linebacker. Grey hairs and balding but shoulders and neck merged together like a linebacker without fat, just epic traps, always spotted in the gym doing bench presses and deadlifts with veins popping out of his forehead, while joking around that he'd kill anyone who breaks the build.

But you know, social stuff. I remember being fresh out of uni and being afraid to talk to people. What a load of bollocks now in hindsight. Talk to people. We might not all be the strongest that way being the types to imagine worlds in our computers. You try and get better. Don't delay a merge. Talk to somebody. Get over the fear. You don't have anything to fear if you talk to people all the time.

What makes people upset usually is unpredictable stuff. There was no heads up. That's how I get upset anyway and that's how lots of people seem to get upset. So it's not the merge conflict that ever pissed me off. It's a merge conflict with someone who never gave me that heads up. Communication is the solution as hippie as that sounds.

Actually, I just revisited your question and one part confused me:

Is it possible for a developer to deliberately postpone merging because he doesn't want to be the one resolving a potential conflict?

If you postpone your merges you get more conflicts, no? I would think it would be more tempting to rush merges to avoid conflicts and bounce them to other people making changes to the same code. If you postpone, you tend to defer more conflicts to yourself. As one who started out passive and very shy and not wanting to interfere with anyone else's work, I used to do that. It's like I didn't want to inconvenience other people on my team so I would postpone my merges and resolve their conflicts so that I wouldn't introduce conflicts to them. In hindsight, I think just talking to them was the superior solution.

6
  • 9
    "If you postpone your merges you get more conflicts, no?" - yes, but you don't get them now. It's absolutely not uncommon for self-defeating behaviour to be that obvious. Someone people avoid opening their mail for months or years because they're afraid of bills they can't pay. Sep 28, 2020 at 7:31
  • 2
    @MichaelBorgwardt That might be like a psychological thing where I'm different a bit. It's more stressful for me to put off paying the rent than it is to just pay it and eat nothing but $2 bread for 2 weeks (true story). But thanks for clearing that up! I am Japanese so maybe it is different. I was so afraid when I first joined the first company of my merges causing people to get conflicts. So I waited so that I could absorb the tedium of resolving them. I put it off because I was afraid to cause them stress. I was willing to make my life as stressful as possible to reduce theirs.
    – user321630
    Sep 28, 2020 at 7:43
  • 1
    @MichaelBorgwardt It was for American company. I got trampled. I learned to stand up for myself. Maybe I got a bit arrogant along the way. :-D
    – user321630
    Sep 28, 2020 at 7:46
  • 3
    I don't really understand the psychology of wanting to put things off if there is a merge conflict. I understand the psychology of not wanting to upset people so you absorb more work for yourself, but I've found that to be a problem too. It is a difficult cultural thing I've learned spending almost a decade in the US. There is that concept of "doormat". I mistook being kind for being "doormat". I learned the hard way not just with work but also girlfriends that you can't be so eager to serve and be loyal and devoted. It is good to be kind of an "ass" (just in my Japanese opinion).
    – user321630
    Sep 28, 2020 at 7:54
  • Have you found that the case? I have found that if your boss is like, "Jump!", and you are like, "How high?" (total Japanese subservient way), they treat you as less than the one who asks why they should even jump in the first place who they treat like royalty. So I have learned to be defiant and rebellious even though it is not natural to me. So I say "kiss my ass" and I have found that got me fired before until they got used to it. Now I have a boss who thinks it's funny when I tell him to kiss my ass but I always feel rude when I say it.
    – user321630
    Sep 28, 2020 at 8:05
5

There is more than one kind of merge conflict, and most of them can be trivially resolved because to a human it is obvious what should happen, but to the computer it's not.

Strategies for resolving these:

  • rebase everything instead of merging

No merge commits, ever. Instead, a branch is tested on its own, and when it's ready for submission, it is rebased first. This way, you are presented the conflicts of new commits on the branch individually rather than all at once, that is a lot less work.

  • rebase slowly

My favourite git command these days is

for i in $(git rev-list --reverse $(git merge-base HEAD origin)..origin); \
do \
    git rebase $i || break; \
done

This will rebase the current branch by moving ahead one commit on "origin/HEAD" at a time, stopping on conflicts. That way, you can only see the conflicts introduced by two commits, not "one branch and one commit", so it should be significantly less. If it stops, resolve normally, continue the current rebase and then run the command again to get back into the loop.

  • enforce coding style in separate commits

Conflicts between a functional change and a whitespace change can be resolved by adding whitespace change commits and merging them separately.

The truly difficult conflicts are a matter of failure to communicate with other developers -- someone removing an API that another is using. One thing I do for refactoring commits is to split them up into

  1. add new API
  2. move component A to new API
  3. move component B to new API
  4. move component C to new API
  5. remove old API

That way, the last commit can go into a separate merge request, and I can ask other developers if this is okay to merge yet or if it breaks their branches.

2
  • 1
    I strongly disagree with the always-rebase approach. For the simple fact that you are never testing the intermediate commits that you are producing. They might not even compile, and git bisect won't be able to differentiate between them. That said, I do agree that your git rebase -i loop can be very useful, when you are working with an SVN upstream, that is. Being forced to deliver linear feature branches is a pita that I only know too well, and that loop can kill the pain quite significantly. In any case, never forget to actually run your test suite on every single commit after rebasing. Sep 28, 2020 at 22:59
  • 1
    @cmaster-reinstatemonica, the rebased branch should be tested as well, true. I normally run git rebase -x 'make check' or similar in the end, and I'm working on a CI system that actually tests each commit it sees, so this can be automated. Sep 29, 2020 at 4:44
3

Code formatting standards

(Partial answer, just adding to others.)

This may sound stupid, but in my experience a lot of merge difficulty (I've seen quite a few instances of regression and new bugs introduced way back...) was caused by code format changes between different developers and the merge tool not being syntax aware enough to handle them gracefully. An easy answer is to simply enforce a coding style/format standard with little or no discretion left to developers. One example would be the Google Java Formatter, which can also be hooked into your build or check-in process so that it is simply automated and no one can "forget" to do it. (A compromise format that all developers can agree to, even if grudgingly.)

This is a "low-hanging fruit" that will go a good way to ease some of the pain, in addition to the techniques put forward in other answers.

0

They are complete disaster, because fixing them wrongly may result the code that ok compiles but now contains bugs (lost or duplicated lines that are not declarations often do not break the build itself). They also take lots of valuable time to fix.

Any technical improvement that would allow to solve merge conflicts easier or automatically is the most welcome. I also think that some organizational approaches should be taken to minimize the possibility of the merge conflicts.

7
  • 4
    Have you ever heard or used Crystal? It's a tool that can tell you at any given moment if you merge now you'll be in conflict with dev A.
    – YsfEss
    Sep 28, 2020 at 13:21
  • No but will definitely look at it!
    – h22
    Sep 28, 2020 at 13:22
  • 1
    @YoussefEsseddiq do you have more detailed keywords on this tool or a link? There are crystal reports, a crystal programming language... all filling my internet search with false matches.
    – puck
    Sep 28, 2020 at 17:13
  • @Youssef Esseddiq: Can you provide a link (or at least the name of the vendor)? A lot of software related stuff goes by the name "Crystal". Sep 28, 2020 at 21:04
  • You are not still using SVN or similar, are you? I've never produced a lost or duplicated line when merging with git, and boy, I've had to deal with veritable monsters of merge conflicts. (This was largely due to the fact that the repo was still managed with SVN. I did a git-svn clone, and was happy on my side. But I still had to tell suitable lies to the SVN server in the end...) Sep 28, 2020 at 22:46
0

Even when I handle a repository where I'm the only collaborator and have multiple branch, I really avoid having to switch branch mid work, unless of course it can't be avoided.

The horror of doing the switch ASAP due to something urgent and just commit the change first then switching, then suddenly something weird on the list of changes pops up, this happened to me yesterday, it was the worst, like the last x minutes during your instant commit flashes before your eyes, and I try to think hard and stay cool but inside I'm like "wtf, I just committed everything why there's still something on the change list!!!"

My personal advice when you do encounter conflict and have to merge is to really do it calm and collected, really focus and don't try to shortcut or do this ASAP like I did, also when handling other's codes be sure to know what they've been doing and if needed, contact them.

Merging can be a silent killer since everything will run correctly because after merge, you'll compile it until it works on your side thinking maybe the merge did something to your code if any error occurs, people tend to focus on their work hence we often forget merging means someone's work is now in our hands.

Not the answer you're looking for? Browse other questions tagged or ask your own question.