May 9 at 17:50

Weld Merge: GNOME Meld in Visual Studio Code

TL;DR: I forked Meld and put it in vscode!

  • https://github.com/pknowles/weld-merge
  • https://marketplace.visualstudio.com/items?itemName=pknowles.meld-auto-merge
  • https://open-vsx.org/extension/pknowles/meld-auto-merge

I love meld merge. It’s simple, intuitive and does a remarkably better job at initial conflict resolution than any other tool I’ve used. You can even set it up with tabs for base <-> local and base <-> remote comparison is fantastic to see the intent of each branch before choosing what the merged result should look like. Here’s my git config for that:

[diff]
    tool = meld_diff
[difftool "meld_diff"]
    cmd = meld $LOCAL $REMOTE --output $MERGED
[merge]
    conflictstyle = diff3
    tool = meld_merge
[mergetool]
    keepBackup = false
[mergetool "meld_merge"]
    keepBackup = false
    cmd = meld --auto-merge $LOCAL $BASE $REMOTE --output=$MERGED --diff $BASE $LOCAL --diff $BASE $REMOTE

My biggest problem is when I want to handle merge conflicts remotely. Most of my time coding is now spent in vscode remote development over SSH, or a fork like cursor and antigravity. I then need to run meld on the remote machine. Using meld is still possible in some cases:

  • sshfs; run locally (sloow; linux only)
  • X forwarding (slooow; linux only)
  • VNC (sloow)
  • RDP (slow)

Yes, AI can now resolve conflicts but I often want to do some myself or check up on what it’s doing. In many cases the merge is easy and can actually auto-resolve with Meld’s algorithms whereas the default resolution would fail.

What I really want is meld but inside visual studio code with its implicit remote development support. A few months back I started work and the result is now live. It’s currently in alpha, still with a few bugs. Check the readme and release version! You can install it already just by searching for Weld Merge in the extensions list. More instructions on github.com/pknowles/weld-merge.

What follows is some cherry-picked dev log entries. As usual with AI it went fast at first, then slowed with features and finally went backwards as AI started adding more bugs than it was fixing. The issue was letting bad patterns fester due to not reviewing closely enough. Maybe one day we won’t have to but until then AI has a lot of questionable code to learn on and unless it has clean examples in the same repo it will become an unmaintainable mess.

VSCode and the CustomTextEditor

VSCode doesn’t allow direct extension of regular editor windows. Instead, they’re written from scratch in a custom “webview” panel. Yes, this means Weld Merge has a full blob of the monaco text editor embedded in the extension. Maybe I could pull this out of vscode itself but I haven’t figured that out yet.

To make the webview panel behave like a regular text editor, vscode provides a custom editor API. This keeps all editors, or “views”, of the backing TextDocument in sync. Now, I’d expect vscode to make this nice and easy for common use-cases, but to my surprise their samples take a gigantic shortcut: the entire document contents is copied every time there is a change 🤯! Clearly the intent of the API is to pass incremental updates of changes, but there is no sample code and I have not been able to find a single example of someone doing this correctly online.

OK. I’ll have to do it myself…

TODO (the code is written so if you need answers quickly there are comments describing what I came up with)

Restoring Git Merge Conflicts

It’s fairly common to finish resolving merge conflicts and realise you messed up. E.g. when you run tests before git rebase --continue. At this point you want to go back to the 3-way merge editor and fix your mistake, but the file is already resolved with the new content. What do you do?

git checkout -m path/to/file

Nice and easy. Don’t forget to git rerere forget if you already recorded the resolution during a rebase. One problem for the Weld Merge UI however is that after resolving conflicts and staging the file there is no way to ask git which files were originally conflicted, the user can be presented with a list and a button to restore the conflict. The workaround currently used is:

Scrape .git/MERGE_MSG for the # Conflicts: block. Eek. It’s not pretty but it works for now.

Another problem: what if the conflict is a file “deleted by us/them”? What if the conflict is a submodule? git checkout -m does not work in these cases. For these, we have to understand how git actually records conflicts, where you see “both modified” in the status for example.

TODO

There are no comments yet.