Skip to content

Instantly share code, notes, and snippets.

@joelrebel
Last active February 25, 2024 18:13
Show Gist options
  • Save joelrebel/8f73986cb2ec0fb02868e525b1f464c1 to your computer and use it in GitHub Desktop.
Save joelrebel/8f73986cb2ec0fb02868e525b1f464c1 to your computer and use it in GitHub Desktop.
Resolve go.mod, go.sum conflicts with mergetool

About

Conflicts in go.mod, go.sum conflicts can be tedious to fix, the steps below help setup a custom git mergtool which helps fix those conflicts.

ref: golang/go#32485

Caveats: this is by no means an exhaustive solution.

Steps

  1. Create an executable Git mergetool script in $PATH, /usr/local/sbin/gomod-mergetool
#!/bin/bash
set -e
fileMerge=$4 ## The file containing the conflict markers

echo "$fileMerge: purging conflict markers.."
awk '!/======/' $fileMerge | awk '!/>>>>>>/' | awk '!/<<<<<<</' > ${fileMerge}_union
mv ${fileMerge}_union ${fileMerge}
exit 0
  1. Declare mergetool in ~/.gitconfig as gomod (or whatever else, make sure to reference it with the same name in step 4.)
[mergetool "gomod"]
    cmd = /usr/local/sbin/gomod-mergetool "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
    trustExitCode = true
  1. Now attempt the rebase (or another merge command) which introduces the conflicts in go.mod, go.sum
❯ git rebase -i main
hint: Waiting for your editor to close the file... vim-latex-live-preview: python required
Press ENTER or type command to continue
Auto-merging go.mod
CONFLICT (content): Merge conflict in go.mod
Auto-merging go.sum
CONFLICT (content): Merge conflict in go.sum
error: could not apply 61713a0... go: update deps
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 61713a0... go: update deps
  1. Finally, run the gomod mergetool with go mod tidy
❯ git mergetool -t gomod go.mod go.sum && go mod tidy
  1. If the above command returned with no errors, you can continue with the rebase/merge
❯ git status

...

Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
        both modified:   go.mod
        both modified:   go.sum
❯ git add go.mod go.sum && \ 
   git commit -m "fixes merge conflicts in go.mod, go.sum" && \
   git rebase --continue
@wizardishungry
Copy link

Do you have an example of an actual tool that does this?

@joelrebel
Copy link
Author

joelrebel commented Dec 18, 2023

edit: if you mean a Go tool that would handle this, nope I don't - it'd be pretty useful if there was.

Do you have an example of an actual tool that does this?

you can find a bunch here https://github.com/git/git/tree/master/mergetools

@dnephin
Copy link

dnephin commented Dec 31, 2023

Using https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver might allow you to automate more of this. Instead of having to run git mergetool:

  1. You can set this command as a custom merge driver in .git/config: https://git-scm.com/docs/gitattributes#_defining_a_custom_merge_driver
  2. Create a .gitattributes for go.mod and go.sum that sets this driver to be used on conflicts: https://git-scm.com/docs/gitattributes#Documentation/gitattributes.txt-String-1

I'd probably have the driver call go mod tidy itself, and use the exit code to determine if the merge was successful or not.

@ryancurrah
Copy link

@dnephin running go mod tidy in the script wont work as you need both files to be conflict-free before running it and the script executes on a single file. It would work if you run the script manually instead of using the merge tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment