How do I edit a Git commit that is hundreds of merges and merge conflicts into the past?

136 views Asked by At

I need to modify a commit near the very beginning of my repository's history. Since that commit there have been probably hundreds of branches, merges, and merge conflicts.

I tried using interactive rebase with the --preserve-merges option, but I still get hundreds of conflict errors akin to "CONFLICT (content): Merge conflict in Foobar.cpp". Re-resolving them again manually is hugely impractical if not impossible.

I've heard of the 'rerere' feature, but only just now, so I haven't had it enabled.

3

There are 3 answers

2
Adam Dymitruk On BEST ANSWER

Rerere will not help you here.

You are looking for git filter-branch. Depending on your change, you may be able use the index-filter which will be faster than the tree filter. You will alter all of your subsequent SHA-1s by doing this.

Make sure to include the --all parameter so all of the references get updated. This is going to ruin any repo that uses this repo as a submodule as the SHA-1s will be referencing non-existent ones. You will need to do some more scripting to fix that.

Also, if anyone you work with had any unpushed commits, they will have to git rebase --onto their outstanding work onto the new place in the history.

In the coming years, we will hopefully see more support for performing such shenanigans - especially when submodules are involved.

1
Andreas Wederbrand On

This is what I would try. There is no guarantee but worth a try

  1. Enable rerere (git config rerere.enabled true)
  2. Enable rerere.autoupdate (git config rerere.autoupdate true)
  3. Go back to the old commit and fix it, then just merge away. Hopefully rerere will learn as you go and start resolving the conflicts automatically.
0
Guillaume Berche On

newren/git-filter-repo seems to share the same objectives as git filter-branch, with a simpler user experience and better performance (see Why filter-repo instead of other alternatives? ):

See user manual extracts below for removing a password leak from git history

If you want to modify file contents, you can do so based on a list of expressions in a file, one per line. For example, with a file named expressions.txt containing

p455w0rd
foo==>bar
glob:*666*==>
regex:\bdriver\b==>pilot
literal:MM/DD/YYYY==>YYYY-MM-DD
regex:([0-9]{2})/([0-9]{2})/([0-9]{4})==>\3-\1-\2

then running

git filter-repo --replace-text expressions.txt

will go through and replace p455w0rd with REMOVED [...]