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
master), I was asked to change the name of a variable that was introduced in
D (e.g. change
bar) . If I were patient, I could look through all the commits in
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
barare 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
foobarbeing incorrectly translated to
- 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)
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
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
git filter-branch if this is not your first attempt, in order to overwrite the copy.
Answered By – MayeulC