3

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.

CharlesB
  • 86,532
  • 28
  • 194
  • 218
Walt D
  • 4,491
  • 6
  • 33
  • 43
  • 1
    Magic bullets are available on aisle three. Buy a whole case; they're cheap! – Todd A. Jacobs Jan 15 '13 at 07:14
  • I would check out the commit before, edit and commit, and then merge the current commit with it. – Ignacio Vazquez-Abrams Jan 15 '13 at 07:16
  • Not asking for a magic bullet here. I just figured this was a problem a lot of people would have run into, and someone might be able to point me in the right direction. Ignacio, I don't understand what you're suggesting. Can you please expand? Thanks! – Walt D Jan 15 '13 at 07:25
  • Not sure why this is being voted to be closed. It's a very good question and shows the potential misunderstanding the role of rerere. – Adam Dymitruk Jan 15 '13 at 07:48
  • @AdamDymitruk It's speculative. There's no code. There's no error message. There isn't even a representative sample of a conflict. The question, as currently written, boils down to "I want to filter/rebase my repository, but I haven't actually tried it because I don't want to risk conflicts." As it stands, the question is not about `rerere`, and there are already tons of questions and answers about `filter-branch`. – Todd A. Jacobs Jan 15 '13 at 07:58
  • 1
    I still see this as something that could help someone who hits this via google. With git, you can't always make a code sample match a question and answer. On other tech like programming languages, SDKs, libraries, etc, you are 100% right. – Adam Dymitruk Jan 15 '13 at 08:00
  • Yeah, I'm not sure how to post a relevant code sample or error message. My error is essentially hundreds of "CONFLICT (content): Merge conflict in Foobar.cpp" during rebase that are impractical to resolve by hand. Am I supposed to make a sample repo and post it on github purely for the sake of this question? – Walt D Jan 15 '13 at 08:06
  • Edited question with an example conflict error. Perhaps that will make it easier to Google. Thanks for the feedback, CodeGnome. – Walt D Jan 15 '13 at 08:17

3 Answers3

4

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.

Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141
  • Thank you! With some clever scripting, this looks like it should work for the particular changes I need to make, since none of those changes involve actual source code. (Just modifying commit messages, squashing commits, and removing binary files.) – Walt D Jan 15 '13 at 07:49
  • I'm not sure you would want to squash commits. but you can instruct filter branch to remove empty commits. These can occur if a file you are removing had commits that only affected it. These will be empty commits after this. So you may want to enable that option to remove them. You probably know this already, but make sure to make backups of your repo before playing with filter-branch. – Adam Dymitruk Jan 15 '13 at 07:52
0

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 [...]

Guillaume Berche
  • 3,049
  • 2
  • 17
  • 18
-1

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.
Andreas Wederbrand
  • 38,065
  • 11
  • 68
  • 78