Rename variable in all commits on a given branch

Issue

My repo looks something like this:

         (develop) D - E - F - G - H
                  /
(master) A - B - C

In the course of a code review (where I propose to merge develop into master), I was asked to change the name of a variable that was introduced in D (e.g. change foo to bar) . If I were patient, I could look through all the commits in D, E, F, G and H, create fixup commits for each and then rebase away foo entirely so that only bar remains in the history.

It seems like there should be a better way. A little googling makes me believe that I should be able to make something work with git filter-branch, but as I’m re-writing history and all — I’d prefer to be able to get it right the first time instead of doing a bunch of weird stuff and messing up my repo entirely…

A few helpful constraints for the purposes of this problem:

  • We can assume that the names foo and bar are globally unique. e.g. if I did a sed -i 's/foo/bar/g' FILE, I’ll be left with the result I want without worrying about names like foobar being incorrectly translated to barbar.
  • I’m using OS-X — So POSIX compliant invocations of shell utilities are preferred (though I can work to translate from GNU variants if I must)

Solution

You were already quite close with your attempt.

git filter-branch --tree-filter 'sed -i "s/foo/bar/g" $FILES'  D^..H HEAD

assuming you are on your develop branch and you replace D and H with the commit index.

If you mess something up, there is always the reflog. You can also branch before or hand-write the commit reference before as a safeguard. I would recommend performing this in a separate branch, however.

$FILES here is a list of files containing your variable. I guess you could replace it with $(git grep --name-only foo). I didn’t try it however, and you might have to escape the $ symbol. The simplest option is to hand-write a list of files there, of course.

Edit: just tried. It works without escaping. sed however fails if there is no input file, aborting the process. You also get a copy of your old refs in .git/refs/original/, so you might need to add -f after git filter-branch if this is not your first attempt, in order to overwrite the copy.

Answered By – MayeulC

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published