Rebasing tags in Git repositories

UPDATE: I didn’t realize that git-filter-branch(1) has the option built in: --tag-name-filter. The moral of the story is: RTFM to avoid writing unnecessary code. :-/


Perhaps you’ve noticed commits in your Git repository that you or a team member created with the wrong credentials. Perhaps you see personal email addresses instead of corporate email addresses among the commit authors. Perhaps — for reasons known only to you and the empty bottle of Jägermeister in your recycle bin — there is a commit whose author name is that ridiculous nickname you acquired in high school. These can be career-limiting maneuvers.

How to fix these commits? git-filter-branch(1) is the answer. Mr Google can tell you about how to use it.

After you’ve used git-filter-branch(1) to rewrite history, you’ll notice that all the tags you had created on that branch are gone!

Don’t panic. The tags still exist, but they are pointing to the original commits prior to your rewriting exercise. You have to manually update these tags to point to the rewritten commits. You might try the following:

  1. git tag -l to list all your tags.
  2. For each tag, git show TAG_NAME to see the details of the old commit. Make note of the subject line, date, and hash of the old commit.
  3. Page through git log looking for that subject line and date. Make note of the hash of the new commit when you find it.
  4. git tag --force TAG_NAME NEW_COMMIT_HASH to update the tag.
  5. Hope that you have not mistaken one commit for another with a similar subject line and date.

This is a seriously mind-numbing and error-prone process, especially if you have a dozen or more tags: freebasing not rebasing.

What you really want is a --tags option for git-rebase(1) that would do this work for you: git rebase --tags NAME_OF_REWRITTEN_BRANCH.

I’ve written a script that fills the bill. You invoke it with git-rebase-tags NAME_OF_REWRITTEN_BRANCH. If there is exactly one commit on that branch whose tree hash (i.e., diff) is identical to a tag, the tag gets repointed to that commit.

A votre santé! end of article

Follow Me on GitHub