9 ms·
Take the pain out of Git conflict resolution: use diff3 (2017)
- pkrumins 5y agoI hope someone solves the merge conflict problem once and for all. Each time there’s a merge conflict the project stops for days as no one knows how to resolve them. In the end the solution always is to delete the git repository and clone it again.
- loh 5y agoI'm confused by your comment. What kind of merge conflicts stop a project for days? And why would the solution to a merge conflict be to delete the repository and clone it again? Or are you being sarcastic?
- pkrumins 5y agoAll merge conflicts. You can never resolve them as everything is screwed. Takes days to figure it out. You usually just delete the repo and start all over again from a working commit.
- ZeroGravitas 5y agoYou can set a flag in git so it won't start a merge if it can't finish it with a simple fast forward. This avoids this situation. git pull --rebase can be used to get local changes on top of new remote work. But just deleting (or renaming the branch) and checking out again is all that is necessary if you end up in a messed up merge.
- pkrumins 4y agoThanks!
- metadat 5y agoNot sure if I like this better. It seems even more complicated to track 3 context points in time rather than 2. I'm open to changing my mind, but would need reasons. Botched rebases aren't a common issue for me (though merge conflict resolution can be unpleasant).
- patrickthebold 5y agoOh, I love diff3. Having the common base (usually) makes it easier to see "what _change_ happened in the other branch", and "what _change_ happened in my branch". Then it's (usually) straight forward to apply one change to the other. Of course, if seeing my code and their code works for you, then by all means keep doing what works.
- orblivion 5y agoI don't really feel comfortable without it. It seems imprudent not to know the common base.
- kazinator 5y agoYou don't know the entire common base; only small windows of it where merge conflicts occurred. Elsewhere, a machine automatically merged it. That machine prudently had the common base, but didn't understand any of it.
- exclipy 5y agoI don't see how there is any room for opinion. If you read the article, it opens with an example where it is impossible to determine the correct merge from the given information without diff3.
- hashhar 5y agoBold of you to assume people read articles before commenting. diff3 has another advantage in the general case as well since it allows you to better understand if something outside of the hunk you're applying also needs to be changed when backporting something.
- kevincox 5y agoI like the idea but it is clearly incomplete. It gets the fact that there are 3 versions (and that it wants you to generate a 4th) but it misses the important thing which is that you want to see the differences. This option basically leaves you to do the diff yourself. Now the sinple option of just showing the two diffs probably isn't optimal either as the context will be duplicated noise, but I think that is already better. In fact I think the merge diff representation would work well here except for the fact that you want to be able to compile and test the code which you can do with the diff markers.
- IshKebab 5y agoSure, diff3 is better than nothing. zdiff3 is even better. But there's so much scope for better diffs still. For starters we could have semantically aware diffs that take into account where blocks are (I think there are some efforts to do this). But even diff3 is missing information. Lets say the code started as A, you changed it to B. Then you rebase and `master` is C. You'll get basically "It's C now! But you changed it from A to B." That's not enough information. Why was it changed to C? I don't know how to update my diff without that information. Really you need to see the change that changed it to C too. There's so much scope for an advanced conflict resolution tool. Git gets it wrong in so many situations where you could do better.
- exclipy 5y agoIf you know A and B, and you know C, then you know the diff from A to C.
- IshKebab 5y agoSure but that often isn't enough because it doesn't tell you which commit actually made the change.
- golergka 5y agodifftastic (https://difftastic.wilfred.me.uk https://difftastic.wilfred.me.uk) is an awesome tool to display diffs in syntax-aware way.
- IshKebab 5y agoOooo looks nice. I'm going to try it.
- difflens 5y agoDifflens (https://github.com/marketplace/difflens https://github.com/marketplace/difflens) is a step in this direction. It produces syntax aware diffs for TS/JS and CSS at the moment.
- thriftwy 5y agokdiff3 is ok-ish as a GUI option.
- usr1106 5y agoOr meld. But I fall back to GUI only in nasty cases. Over 90% I feel comfortable with diff3 formatted output by git.
- gpvos 5y agoI haven't used meld for a long time; the website says its three-way merge is still in development, while kdiff3 has had that for more than twenty years and it's (for me) the main reason I use it. The three-pane display with the merge result in a fourth pane at the bottom is just so easy to use. (The second reason I use it is that it allows you to mark lines that should align with each other.)
- usr1106 5y agoAs I wrote I rarely use the GUI tool for conflict resolution because I am most of the time just fine with diff3 textual format in my editor. So I have no experience which tool would be best. I used kdiff3 15 years ago (mostly pre-git) and have drifted over to meld over the years. The reason for that has been lost in history, not sure whether it would stay that way if I started to systematically compare them today. Meld certainly does allow to manually align lines. But sometimes I have struggled when doing several alignments in a single diff. Not sure whether kdiff3 would do better or it's just user error. Where meld certainly fails is huge files. Its performance can be horrible. But that affects generated files like logs, not source you would have in git.
- lolive 5y agoI personally never had to leave IntelliJ Idea for merge conflict resolution. So I am super used to it and think it is very convenient. [as far as I understand this is similar in philosophy to a diff3. True?] And while searching a bit, it seems that a similar UI is planned for VScode later in May 2022. Cf https://github.com/microsoft/vscode/issues/37350 https://github.com/microsoft/vscode/issues/37350 [Btw, a comment mentions that Sublime Merge already has a UI similar to the one in IntelliJ]
- miked85 5y agoI'm not clear how this solution removes pain, it could make things more confusing for many.
- usr1106 5y agoWe never use merge except fast forward merges. So we never have merge conflicts. Of course that means that we might need to rebase and that could hit conflicts. With diff3 style rebase conflicts are generally [1] easy to understand. When a commit does not apply cleanly the diff3 style output gives you 3 sections: 1. What the code looks like after the previous commit that has already been rebased to the new branch under work 2. What the code looked like in the original branch 3. What it looked like 1 commit later in the original branch. Now the question the human is: You (or some one else) changed it from 2 to 3 in the past. Now your code is not 2 but 1. How do you introduce an equivalent change from 1 to something that works like 3? Once I have learned that principle I could no longer understand why diff3 is not the default or how anyone can survive without it. [1] Of course there can always be tricky changes. If an automatic diff tool choses unlucky alignments the result is not ideal for humans. But diff3 does not make things worse and generally it does not happen that often. Edit: A couple of iterations needed. Don't try to type somewhat complex comments on your phone...
- mathstuf 5y ago> We never use merge except fast forward merges. Hmm. I've never really liked this pattern. We never use fast-forward merges for anything other than bringing a release branch forward to track the "current release" state[1] (the old HEAD gets renamed to a stable branch name with the version number in its name). Benefits as far as I'm concerned: - the merge commit can record information about the topic as a whole (e.g., the MR number, `Acked-by` and related reviews, etc.) - it records the merge as a distinct event - reverting a topic is just a single revert command of the merge itself (unless there's some magic to divine what sequence of commits is a "topic" in linear history these days?) - backporting branches is just "branch off of the old release, merge into all relevant branches" instead of individual rebases and tandem merge requests [1] This is possible because we keep "the primary branch can reach all branches" as a property as well. We do this with `-s ours` "syncup" merges whenever a non-primary branch is merged into. This is, of course, all done at once by merging a topic into all target branches, performing syncup merges and pushing with `--atomic` to avoid race conditions.
- 5y ago
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- kodah 5y agoIf you're getting a lot of conflicts then you have folks working on the same code and diverging it significantly. I honestly don't think that's a problem tooling will improve because it's really an organizational/communication problem. Engineers have to know when to rebase (or merge in changes from the target) if they're working on code with other engineers. If you merge in/rebase sooner, then things tend to be painless. If it's been weeks or months then let the Circus O' Pain begin. This should be fairly easy to recognize in stand up, eg: "Oh, you're working on that module? I need to track your changes, so am I."
- _0w8t 5y agoFrequent and complex merges are inevitable if one maintains a few patches to an actively developed upstream and the upstream either does not want them or the patches are too specific to the product to be a part of the upstream.
- skierguy 5y agoIt's much more complicated at scale. Many conflicts can come from things like backporting or working on a feature in a codebase that deals with a lot of churn (like some drivers or the Linux kernel). Some open source projects have internal versions of the code within the company that eventually gets upstreamed after internal validation takes place, but that version of the code may not rebase for a while for some very good reasons (unresolved instability on the main branch, for instance). In that case, the code base is now both significantly ahead (with internal changes) and significantly behind (due to the other changes that have come from other massive organizations working on the same project). I have published on the topic of merge conflicts a couple times, and even I didn't understand how inevitable massive merge conflicts can be until I joined a kernel integration team at a large company. Open source is a helluva drug :)
- jrockway 5y agoYeah. Something that I've told myself never to do but have continued to do for the last decade is to take some code that's in review ('cause reviewers be slow) and then branch off of it and write something else. There is always "one little thing" in the code that's out for review, and merging that into the future work that you branched off is always a colossal pain. Every time I do it I regret it. (Is it just me, or is it not a social norm to treat code reviews like interrupts? I do that; I have Github connected to Slack and treat "I need my code reviewed" at the same level of priority as something like a production outage. It takes 5 minutes and unblocks an entire developer. But that favor seems rarely returned to me. I can usually get a fast review if I whine and nag, but it should just be automatic. And this isn't an artifact of any particular job, it's been like that at every job. I guess we could just stop doing code reviews, but they are pretty valuable for fixing dumb mistakes and sharing knowledge. But I digress...)
- Ycros 5y agoThe article suggests a good first step, but I recommend using a 3-way capable merge tool for an even better experience. 3-way merging with a reasonable UI should be the default, I don't really understand why it still isn't. It makes large and complex merges easy. My merge tool of choice was kdiff3 for the longest time, though these days I'm using Beyond Compare which is a commercial product.
- dikei 5y agoI've been using kdiff3 for over a decades, it's just so good for a free tool.
- jraph 5y agoMeld here, for years. It is capable of editing in place and three way compare. It's a very good tool, and quite lightweight too. I'd rather use KDE software though, since my desktop environment of choice is Plasma. I haven't found the edition-in-place feature in KDiff3. Is it there? Kate also being my code editor of choice, that would be amazing. If it's not there, how do you solve merge conflicts with KDiff3 if you don't have editing in place?
- Nursie 5y agoMeld is a great, free tool available on pretty much all platforms. Been using it for a long old time now and can't recommend it enough. 2-way, 3-way and folder diff, in-place editing, it has all I need.
- dikei 5y agoKdiff3 can absolutely do edit in place: just type directly in the merge output window and save the result as usual.
- onetom 5y agoThe 3-way diff in JetBrains products, like IntelliJ, are the best, IMHO, because it helps you edit the resolved result, while updating both left and right diffs. Their diff tool also has a magic-wand icon, which resolves trivial conflicts automatically. I still wonder why git doesn't do that by default... It's such a pain to resolve conflicts without that feature. Also, you get syntax highlighting, structural editing, help, definition quick-lookup and similar IDE features available, while working on the resolved version of the code, which is syntactically correct usually, because there are no explicit, textual conflict markers in the resolved text.
- hnrodey 5y agoBeyond Compare also offers 3-way merge conflict resolution. Very helpful.
- deleted 5y ago[deleted]
- jlkuester7 5y ago+1 Beyond Compare is straight-up amazing! Its 3-way merge conflict resolution does 90% of the work for you. Best in its class at what it does!
- deleted 5y ago[deleted]
- pavon 5y agoMy experience is that the conflict files (with <<<< ===== >>>>) that git generates do have all the trivial conflicts resolved. In fact, before I learned what the the magic-wand icon did, the IntelliJ merge conflict tool really annoyed me since it showed all sorts of conflicts that git didn't.
- theptip 5y agoJetBrains resolves conflicts that git can’t IME. For example multiple branches modifying the same import lines in a Python file (most common merge conflict I see), JetBrains can resolve this. I’d be interested to know how they solve it, I suspect they run some language-aware logic to do the merge on a given hunk.
- mkoubaa 5y agoEmbrace the pain. If you try to let a tool help you too much with conflicts you may end up regretting it.
- jlkuester7 5y agoI fail to see how "embracing the pain" could be preferable to making more informed decisions (like knowing what the "merged common ancestor" looked like). We are not talking about some magical button that uses "AI" to resolve the conflicts for you. diff3 just gives you more context about the conflict so you can make a more informed decision....
- pkrumins 5y agoDiff3 is good but diff4 is life-changing.
- SamReidHughes 5y agoI've found configuring merge.conflictstyle diff3 without a tool to be superior than tools like kdiff3 and such. This was without any fancy merge conflict rendering. Nowadays some editors will also highlight the changes in a 3-way diff. The reason no-tool is better is that you don't have to read files in whatever order kdiff3 shows them to you -- they're just files, and you open them.
- benibela 5y agoThe best is a 4-way diff It you merge a file in two commits A and B, it would show version A, version B, the common ancestor, and the resulting merged file in four different views. xxdiff could do that.