I was midway through working on a project I had been calling
commentate, but then one of my coworkers suggested a much better name,
ahnnotate. Instead of a single large commit to rename each file and each class name, I thought it'd be cool to rewrite history and pretend that it had the cool name all along. But I have to admit, it wasn't quite as straightforward as I had expected.
To fully rename this project, we'll need to take the following steps:
We'll mostly be using
git filter-branch. It's kinda similar to
git rebase in that it allows you to rewrite history, but it's a bit of a "sharper" tool. I found this article quite helpful in understanding exactly what it does.
By the way, I'm using macOS, but I'm using
gsed which takes the same arguments as Linux's
⚠️ ⚠️ ⚠️ One more warning! I'm very freely using "force" flags and deleting git's automatic backups. Be careful, and don't run stuff without a decent understanding of what's happening! Make sure you make a backup! ⚠️ ⚠️ ⚠️
Before starting, it's a bit easier if you have no remotes, no tags, and only one branch.
git branch --list git tag --list git remote -v
You'll also need to delete whatever files are ignored via
.gitignore. According to the
git filter-branch docs,
--tree-filter will add whatever files are present in the working directory, even if they're ignored.
First, we'll replace
git filter-branch --tree-filter 'ag -l -s commentate | xargs gsed -i "s/commentate/ahnnotate/g"' HEAD
Next, we'll replace
Ahnnotate. But git will complain something about a backup already existing, so we need to add the
-f flag. You can also optionally delete the backup with
rm -rf .git/refs/original.
git filter-branch -f --tree-filter 'ag -l -s Commentate | xargs gsed -i "s/Commentate/Ahnnotate/g"' HEAD
We'll need to do this over and over for each capitalization variation you care about. One thing that kinda bit me though is that I used
commentate as a verb,
commentating. I had to do an additional search/replace for that since the
i broke the pattern.
I found this resource quite helpful, and this following example is basically copied from there.
git filter-branch -f --index-filter 'git ls-files -s | sed "s/commentate/ahnnotate/g" | GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
Lastly, we'll update the commit message contents. You'll need to repeat this for whatever capitalization combinations you have.
git filter-branch -f --msg-filter 'sed s/commentate/ahnnotate/g' HEAD
Cool! Hopefully we're done now. Now we just need to check.
We'll know we're done once the following commands return the same result:
# Lists the number of commits in master git rev-list --count master # Lists the number of commits in the entire repository git rev-list --all --count
An easy first step is to delete the
.git/refs/original directory. Hopefully, this will be the only step you have to do. For some reason, I had a bunch of lines in
.git/info/refs and had to delete all the lines except the one containing
I also found
git reflog expire --expire-unreachable=now --all and
git gc --prune=now helpful in removing commits that weren't reachable through the master branch.
Last was the actual verification. None of the following commands should give you any output. If it does, you'll probably need to go back and re-run some commands.
# Search file contents git grep commentate $(git rev-list --all) # Search file/directory names git log --all --full-history --oneline -- '*commentate*' # Search commit message contents git log --all --grep='commentate'