natmaka a year ago
  • TacticalCoder a year ago

    It 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.

    • User23 a year ago

      That’s really cool. As an aside I’m convinced there’s no such thing as too much screen space for any kind of cognitive work. Letting the optic nerve offload work from your short term memory is a huge gain.

      I’ll still occasionally print out source and lay it out on a table to annotate by hand when I’m learning a complex code base.

      • TacticalCoder a year ago

        > I’ll still occasionally print out source and lay it out on a table to annotate by hand when I’m learning a complex code base.

        I've got fond memories of printing programs on continuous form paper (the one with holes on the side that the printer would use to advance the paper) and then reading it to find my bug(s) : )

        • Razengan a year ago

          Literally scrolling

    • Icathian a year ago

      Mind 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 a year ago

        I 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)
                ))
        • Icathian a year ago

          Awesome, I'll play with this a bunch on Monday. Thank you!

IshKebab a year ago

The 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 a year ago

    When 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

    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 a year ago

    IIRC vscode with gitlens extension shows blame on hover, also for the conflicting lines.

    • Gehinnn a year ago

      The 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 a year 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.

        • IshKebab a year ago

          Yeah I 100% agree. Especially as Git gets it backwards in some cases! It's not even consistent about the names. Sometime I see "current" and "incoming" which is not really any better.

          > And give me the revision/commit id's for each

          It could show the branch names! `change on master`, `change on myfeature` or whatever.

          • Gehinnn a year ago

            The 3 way merge editor actually shows the branch name!

      • IshKebab a year ago

        Maybe I'll give it another got but to be honest I found the new merge editor even more confusing than just reading zdiff3. Sorry!

    • IshKebab a year ago

      That's what I'm using. Unfortunately it doesn't. :-/

ChrisCinelli a year ago

diff3 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.

  • loeg a year ago

    Yeah, it's one of the first things I change in .gitconfig or .hgrc:

      [merge]
       conflictstyle = diff3
    • pabs3 a year ago

      The git zdiff3 conflictstyle is a newer better version of diff3.

      • loeg a year ago

        Cool.

BlueTemplar a year ago

Then, 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/

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://pijul.org/faq

b3morales a year ago

The 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.

mkoubaa a year ago

Am 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

  • spyremeown a year ago

    Try 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.

  • askvictor a year ago

    A triple-panel editor has made this much less scary for me over the years. Jetbrains do it really well, I think I've used VS Code for this too.

    • Too a year ago

      You actually need four panels; common ancestor, yours, theirs, and finally the merge-result.

      This is how Kdiff3 and Beyond compare does it and it is far superior to just having three panels.

      A lot of other tools leave out the base or combine it with the result-panel, making it very hard to see what has changed from each side once you start resolving conflicts.

      A 4K monitor is also a must.

      • gpvos a year ago

        I think there's a terminology confusion here. I call kdiff3 and BC a three-panel display, because it shows the original and the two changed versions as three panels next to each other. Since the result is shown separately below, I don't include it in the panel count. I only realized that strictly speaking you could also count it as a panel from your post.

  • softfalcon a year ago

    Nope! 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!

  • taspeotis a year 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

  • bmitc a year ago

    I like using Perforce's three-way merge. The only thing confusing is Git's ridiculous naming for remote and local.

  • fhaldridge7 a year ago

    Same for me. Always used a text editor.

forrestthewoods a year ago

Araxis 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_ a year ago

    I'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 a year ago

      Meld 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 a year ago

        kdiff3 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.

acdha a year ago

My 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.

secondcoming a year ago

p4merge is one of the first tools I download when I have to set up a new environment.

  • darekkay a year ago

    What 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.

prirai a year ago

This 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.

BaculumMeumEst a year ago

i 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

kmarc a year ago

ˋgit mergetoolˋ runs your favourite editor/difftool to do a 3way merge. I found vim to be a perfect tool for doing this

29athrowaway a year ago

I am just going to say one thing: pijul

  • gpvos a year ago

    Looks interesting but not quite finished.

scotty79 a year ago

kdiff3 is a very good gui tool for that.

munhitsu a year ago

Imagine 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.