6 ms·
Merging with diff3: the “three-way merge”
- samsquire 4y agoI implemented this in Python based on his guide to the Myers algorithm. https://GitHub.com/samsquire/text-diff https://GitHub.com/samsquire/text-diff It's not complete and the colouring is probably not the right way round.
- politician 4y agoShoutout to kdiff3.
- natmaka 4y agoEmacs 'ediff' is quite convenient. https://www.gnu.org/software/emacs/manual/html_node/ediff/Merging-and-diff3.html https://www.gnu.org/software/emacs/manual/html_node/ediff/Me...
- TacticalCoder 4y agoIt is. I've got a Emacs setup to show 3-ways merge in ediff which differs from the default. I show, side by side, three columns: "variant A", "common ancestor", "variant B" and then, below, the result. I do really enjoy my wide screen while doing that. I'm literally moving to a 360 columns mode when I do that: 120 columns for each of variant A, common ancestor and variant B. It's the only time I make Emacs that wide. I like to have the common ancestor in the middle, so I can quickly see where both "variant A" and "variant B" are coming from. So I'm using Emacs's ediff to do 3-ways merge while showing four versions of the code.
- Icathian 4y agoMind sharing that? Merge resolver view is the only thing I'm still opening vscode for and I'd be very happy to finally kill that off.
- TacticalCoder 4y agoI basically just slightly modified the code in ediff-setup-windows-plain-merge from ediff-wind.el. Not too sure how to paste code on HN, here's the modified version which works for me. The orginal ediff-setup-windows-plain-merge may depend on your Emacs version though, so buyer beware (things may have changed and need to be revisited). Instead of showing: A B C D Ediff control panel I show: A B C D Ediff control panel As for Git AFAICT all I have is git config --global merge.conflictStyle diff3. Compare it to your version of ediff-setup-windows-plain-merge to see what I changed: (defun ediff-setup-windows-plain-merge (buf-A buf-B buf-C control-buffer) ;; skip dedicated and unsplittable frames (ediff-destroy-control-frame control-buffer) (let ((window-min-height 1) (with-Ancestor-p (with-current-buffer control-buffer ediff-merge-with-ancestor-job)) split-window-function merge-window-share merge-window-lines (buf-Ancestor (with-current-buffer control-buffer ediff-ancestor-buffer)) wind-A wind-B wind-C wind-Ancestor) (with-current-buffer control-buffer (setq merge-window-share ediff-merge-window-share ;; this lets us have local versions of ediff-split-window-function split-window-function ediff-split-window-function)) (delete-other-windows) (set-window-dedicated-p (selected-window) nil) (split-window-vertically) (ediff-select-lowest-window) (ediff-setup-control-buffer control-buffer) ;; go to the upper window and split it betw A, B, and possibly C (other-window 1) (setq merge-window-lines (max 2 (round (* (window-height) merge-window-share)))) (switch-to-buffer buf-A) (setq wind-A (selected-window)) (split-window-vertically (max 2 (- (window-height) merge-window-lines))) (if (eq (selected-window) wind-A) (other-window 1)) (setq wind-C (selected-window)) (switch-to-buffer buf-C) (select-window wind-A) (funcall split-window-function) (if (eq (selected-window) wind-A) (other-window 1)) (switch-to-buffer buf-B) (setq wind-B (selected-window)) (when (and ediff-show-ancestor with-Ancestor-p) (select-window wind-B) (split-window-horizontally) (when (eq (selected-window) wind-B) (other-window 1)) (switch-to-buffer buf-Ancestor) (setq wind-Ancestor (selected-window))) (balance-windows-area) (with-current-buffer control-buffer (setq ediff-window-A wind-A ediff-window-B wind-B ediff-window-C wind-C ediff-window-Ancestor wind-Ancestor)) (ediff-select-lowest-window) (minimize-window) (ediff-setup-control-buffer control-buffer) ))
- IshKebab 4y agoThe problem with 3-way merge (when it comes to rebasing and merging at least) is that you lose all the information about why "theirs" changed. You made a modification to the code. They made a conflicting modification. You want to know what they hell they were doing so you know how to rejig your edit. The normal tool to use here would be `git blame` but that just doesn't work. At least in any tool I have used. If anyone knows of one where it does work I'd love to know!
- js2 4y agoWhen I'm confused by a 3-way diff (I personally prefer FileMerge/opendiff on macOS) and need more info I like to use git log to examine the relevant commits using the "..." operator which returns the symmetric difference between two commits (in this case both sides of the merge) and their merge base: git log -p HEAD...MERGE_HEAD --path/to/file https://www.git-scm.com/docs/git-log https://www.git-scm.com/docs/git-log Another trick is doing multiple merges which each include fewer commits. Sometimes the problem is that you're just trying to merge too much at a time. The downside of this is that in files with a lot of churn you may have to deal with conflicts that you might otherwise not. So it's a bit of a two-edged sword.
- mambru 4y agoIIRC vscode with gitlens extension shows blame on hover, also for the conflicting lines.
- Gehinnn 4y agoThe new 3 way merge editor in VS Code tries to load the documents for base, yours and theirs from the corresponding commit URI, so that extensions such as gitlens can show the line history for each document - they don't even have to know about the merge editor. (disclaimer - I work on VS Code and its 3 way merge editor)
- magicalhippo 4y ago> for base, yours and theirs I really hate that relative terminology. Call them "working copy", "merging commit" and "common ancestor" or something similarly absolute. And give me the revision/commit id's for each, so it's crystal clear in case I want to check up manually. Not a dig on the vscode extension, but 3-way diff tools in general.
- secondcoming 4y agop4merge is one of the first tools I download when I have to set up a new environment.
- darekkay 4y agoWhat I like about p4merge is that it displays four panels: local/remote/result (what most 3-way merge tools use), but also the common ancestor of local and remote ("base"). It really helps with some more tricky merges. With that said, after using p4merge for years, I now tend to rely on the built-in merge tool in IntelliJ IDEA. Especially the "magic wand" is very handy.
- b3morales 4y agoThe diff listings are a bit confusing because the line numbers look like they're part of the text. For example in the first diff, '2. salmon 3. tomatoes' is right next to '4. salmon 5. tomatoes' but those aren't highlighted as a change.
- ChrisCinelli 4y agodiff3 is the way to go. When there are not trivial changes, it is hard to resolve conflicts if you do not know where the conflicting changes come from. I knew quite a few people that do not know that this option even exists. In my opinion it could make the life of engineers a lot better if this was the default.
- munhitsu 4y agoImagine the world where code is represented as a tree of operations, where every character have unique, immutable address. Diff becomes something way simpler. Welcome to the world of CRDT. I hope, one day we will have a thing like automerge but as file format with a native OS provided merging.
- forrestthewoods 4y agoAraxis Merge has been my go-to merge tool for 15 years. Everyone I work with pretty much uses either Araxis or Beyond Compare. BC has some nice features, but I've always found the Araxis UI easier to use. It'd be nice if there was a good, free merge tool. But so far every one I've tried is inferior. And companies are usually happy to pay for a productivity tool as critical as merge tools.
- tom_ 4y agoI've found Meld pretty good for free, but I only use it for hobby stuff so I've never needed to try out the 3-way aspect. But for side-by-side folder and file diffs I've found it decent enough relative to Araxis. And, like Araxis, both sides are editable, something not all diff tools get right. So you can experiment, and/or set up a blank diff and paste stuff in to see what you get. Main problem I've had is that it's slow for large files. I think it's written in Python. An outsize annoyance (which is objectively just a minor UX nit) is that the diff setup dialog displays names only, not full paths. Which is silly, because a very common use case for diff tools is diffing two files that have the same name, so I notice this on about 75% of uses.
- forrestthewoods 4y agoMeld is decent. A few folks on my team used it for a bit. Unfortunately it had some issues where its merges were actually wrong and broke things. :(
- gpvos 4y agokdiff3 never failed me, and having separate original, theirs, yours and result panels, I find it much clearer to work with than Meld. Often it even auto-resolves merges that Git couldn't.
- kmarc 4y agoˋgit mergetoolˋ runs your favourite editor/difftool to do a 3way merge. I found vim to be a perfect tool for doing this
- acdha 4y agoMy favorite merge tool remains Source Gear’s DiffMerge but it hadn’t been updated in years. I like some of what Kaleidoscope does but it’s not as good at automatic conflict resolution.
- BlueTemplar 4y agoThen, at least for VCS, there are Darcs and Pijul, which use a theory of patches. So Pijul manages to have lossless merges by actually storing a directed graph (though of course, you will still need to decide how to flatten that into a displayed file) : https://jneem.github.io/pijul/ https://jneem.github.io/pijul/ And because it uses more information about the history, it is able to do smarter merges (if I am not mistaken, even compared to the OP ?) : https://tahoe-lafs.org/~zooko/badmerge/simple.html https://tahoe-lafs.org/~zooko/badmerge/simple.html https://pijul.org/faq https://pijul.org/faq
- mkoubaa 4y agoAm I the only one that prefers manually resolving conflicts in a text editor? It sucks but I can't imagine a GUI that sucks less
- softfalcon 4y agoNope! I’ve done this for years now. It made the most sense to me. Some people are at a loss as to how I can resolve a conflict without any tools (other than git + text edit) though, feels like a super power!
- bmn__ 4y ago<https://apps.kde.org/kdiff3 https://apps.kde.org/kdiff3> is partially a text editor, try it out and develop an appreciation for it.
- mkoubaa 4y agoI have and use kdiff3 regularly for other purposes
- spyremeown 4y agoTry any of the recommendations here (my poison is Meld). It's actually one of the few tasks where I really, really do prefer a GUI over text.
- bmitc 4y agoI like using Perforce's three-way merge. The only thing confusing is Git's ridiculous naming for remote and local.
- taspeotis 4y ago> The central pane is a fully-functional editor where the results of resolving conflicts are displayed. Initially, the contents of this pane are the same as the base revision of the file, that is, the revision from which both conflicting versions are derived. https://www.jetbrains.com/help/rider/Resolve_conflicts.html https://www.jetbrains.com/help/rider/Resolve_conflicts.html
- 4y ago
- tome 4y agoAh, I wrote an article on resolving diff3 conflicts by hand: http://h2.jaguarpaw.co.uk/posts/git-rebase-conflicts/ http://h2.jaguarpaw.co.uk/posts/git-rebase-conflicts/
- BaculumMeumEst 4y agoi always want to use vimdiff with git mergetool but i’ve never been able to figure out how to use it when i launch the 3way split. i know there are commands to choose between local/base/remote for each conflict i dont know where my cursor is supposed to be or where i should be using those commands from. i always end up going back to emacs and just using smerge, with its super straightforward “go to next conflict” and “choose upper or lower” commands
- scotty79 4y agokdiff3 is a very good gui tool for that.
- 29athrowaway 4y agoI am just going to say one thing: pijul
- gpvos 4y agoLooks interesting but not quite finished.
- danra 4y agohttps://github.com/Peaker/git-mediate https://github.com/Peaker/git-mediate is an amazing secret weapon for making quick work of 3-way conflict resolution.
- prirai 4y agoThis was a saviour. I wanted to merge a previously done extensive change, say B for the original file A and also a different kind of change, say C for the same original file A. I had to merge both the changes. Diff3 came as a saviour.