0

I am in the midst of a big merge request and already resolved a bunch of conflicts, when I realised that I want to run the merge command again with -Xignore-all-space. If I run git merge --abort I would also have to resolve all the conflicts I already did. Is there a way to record these (which are staged already), abort the merge request, try with the new flag and reapply the old changes where it is possible?

uloco
  • 2,283
  • 4
  • 22
  • 37

1 Answers1

2

I'm assuming you don't have rerere's auto mode turned on.

git worktree add scratch @
git -C scratch merge otherbranch   
git -C scratch rerere
git worktree remove -f scratch

these will rerun your current merge to get an index showing the un-resolved conflicts and run git rerere to remember them. If your checkouts are immense there's ways to avoid that, hunt up minimum-checkout merging.

Then you can

git rerere

to remember the conflict resolutions you've staged. Every time git rerere runs, it hunts through its memory and the indexed snapshot, looking for conflicts and resolutions in each. Anything new it remembers, if it remembers a resolution for any unresolved conflicts it's seen before it applies them.

And then you can abort your merge, rerun it with the new options, and git rerere a third time to have it reuse the recorded resolutions.

If you say git config rerere.enabled true git will automatically do git rerere after any merge stops with a conflict and before committing any merge that had stopped with a conflict. If you say git config rerere.autoupdate true it will also automatically stage those reapplied resolutions for you.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • I thought of `git rerere`, too. But I fear that it might be of only limited help, because with `-Xignore-all-space` the conflicts will look differently and would not be found in the rerere database. – j6t Jul 12 '22 at 11:50
  • @j6t They won't. The conflicts are in the original content. The merge options change only what merge is willing to automerge for you, it doesn't change what histories you're merging so it doesn't change what conflicts show up. – jthill Jul 12 '22 at 11:53
  • Histories are the same, but conflicts are different: With `-Xignore-all-space`, `git merge` is able to automerge more otherwise conflicting changes and to reduce conflict ranges further than without. That makes the conflicts different so that they cannot be found in the rerere database. – j6t Jul 12 '22 at 12:04
  • I thought rerere is only helpful in scenarios where rebase is applied. I will try this and accept if things work out, thanks – uloco Jul 12 '22 at 12:17
  • My git config says `rerere.enabled=1`, so it was already enabled when I resolved conflicts and staged the changes (and did not commit ofc). Can I just abort and run `git rerere`? Because I thought `git merge --abort` would make rerere forget these resolutions. – uloco Jul 12 '22 at 12:24
  • @j6t the set of conflicts it won't automerge is different, but the histories it's merging haven't changed so the conflicts it's being asked to automerge are haven't changed. – jthill Jul 12 '22 at 12:50
  • 1
    @uloco Run `git rerere` *before* you abort the merge. This records the completed conflicts. The next `git merge` will automatically reuse the resolution of conflicts that it recognizes (finds in the database). – j6t Jul 12 '22 at 15:44
  • @jthill All you say is correct. The problem is, though, that the conflicts *before* rerere kicks in look potentially different when `-Xignore-all-space` is used due to different whitespace and reduced conflict regions. It is the literal text between `<<<<<<` and `>>>>>>` that is used to look up a resolution in the database, and if that changed, the resolution won't be found. – j6t Jul 12 '22 at 15:52
  • @j6t That can happen if changes that conflict in only one merge are very close to changes that conflict in both, yes. They'll get logged as one big conflict. Fortunately OP wasn't so unlucky here. – jthill Jul 12 '22 at 16:23