git like a pro: rewrite author history

In this little post I am going to show you why you sometimes need to rewrite the author or committer history, how you do it and where it will not work as expected.

Article series
Git like a pro

  1. Git like a pro
  2. Sort git tags by date
  3. Rewrite author history

TL;DR

The complete source including command-generation can be found at github:
cytopia/git-rewrite-author cytopia

Latest Stable Version

Why would I rewrite the git author history?

First things first, why would you ever want to rewrite the git author history? Think of the following scenario:

You are going to do a very urgent fix directly on the server deployed git repository. It seems to work fine and you commit it to the local repository and push it to remote. But wait… You totally forgot that you acted as root and when you issue a git log it will show the following:

commit a0925c315107fcdcfb7a3b2dcd435995c8216ad2
Author: root <root@localhost>
Date:   Sat Oct 10 21:39:43 2015 +0200

    fixed xss on index.php

Damn’ that was a mistake. You should have taken the time and have done it on your local machine, pushed to remote and checked out on the server as your seniors always told you. Don’t worry, this can be fixed.

Rewriting the author history

This time you better do it locally. Make sure your local repository is up to date with the remote and quickly list all git authors:

$ git log --pretty=full | grep  -E '(Author|Commit): (.*)$' | sed 's/Author: //g' | sed 's/Commit: //g' | sort -u

Junior Dev <junior.dev@yourcompany.tld>
Senior Dev <senior.dev@yourcompany.tld>
root <root@localhost>

OK, you need to get rid of root and rewrite it to your git account Junior Dev. The command for this case will look like this:

$ git filter-branch --env-filter '
    if [ "$GIT_COMMITTER_EMAIL" = "root@localhost" ]; then
        export GIT_COMMITTER_NAME="Junior Dev"
        export GIT_COMMITTER_EMAIL="junior.dev@yourcompany.tld"
    fi
    if [ "$GIT_AUTHOR_EMAIL" = "root@localhost" ]; then
        export GIT_AUTHOR_NAME="Junior Dev"
        export GIT_AUTHOR_EMAIL="junior.dev@yourcompany.tld"
    fi
' --tag-name-filter cat -f -- --all

OK, you have done it, let’s double check by listing the authors again:

$ git log --pretty=full | grep  -E '(Author|Commit): (.*)$' | sed 's/Author: //g' | sed 's/Commit: //g' | sort -u

Junior Dev <junior.dev@yourcompany.tld>
Senior Dev <senior.dev@yourcompany.tld>

OK, its gone. Now get it to the remote.

Rewriting the remote author history

Once you have rewritten the local git author history, you will only have to make a forced push of all refs including tags:

$ git push --force --tags origin 'refs/heads/*'

That’s it.

Where does it come short?

Be aware that if any of the commits or tags of an author you want to change are signed, it will mess up the commit message in the history. It will take the gpg signature of the commit and prepend it to the commit message and will look something like this:

commit 4ac785bf03d4b4f814fa9d139db9b9c7b53df733
Author: cytopia <cytopia@everythingcli.org>
Date:   Fri Jul 10 16:03:09 2015 +0200

     iQIcBAABCgAGBQJVn9CdAAoJEKrf9Tsovxef+7AP/0rHHruS1o1P28iHPJS7JEuw
     FKg1a2MG8DeqwfA93O+chkyl2KfvPEG6yrf369XLAdgR4WkmpCDvK9qYNBxde8NZ
     X5S7rGVMKvgdH031o7hYExhMKo1QJrXWzCa7KoEas0/SIAKaqWHojBEpQJO9nBw/
     60XMpwxo7MY+Y4a/W603yL3ZgPYgHFHun3pb5sxlFyL4uhdPJXPhPUhAkXdlI4TE
     vGt/DwJJ2puDfaQsiOe3Iz6VEYk5s5L22OcYZjBnkgeM14Db9FHAK/KGVgJg0Md0
     64HRSyNDCO92CEwCMdv7cqP8cnm2zsk0TvEYpvp7zz1rWkvXK2VAiMfSy8RrUTP8
     rE6qDwL7mF27aFAPuVohtddwYMKdcDijffQ/hT7tWeW8zKiI8NcbSENqJ6/SQbqP
     mn2WC3vyl2X33WCF3j01BPzq+02B2gMxTr0vnnxewpVDgWKPYGxhxRHXcapo9dva
     t8nC6jOXktzHSffWGYFVX/nK1iVoeIrGEPi4n5w3tMX5+HgZUNQCltXRTuUCGCot
     LYGMPCRRbSJ8i5KarRHxvxQp5YisQe/pED3NZMg0gEtD2jx9P4Yv7tZwt7CQYnwW
     5S336fVLkpJfinrwoaebRgdzd6/rbjsBPd92XPQTYSYG4q5m2EJ6JoaorUCE1H0U
     0svoJ7gt7KVVc4urtCiH
     =o0wB
     -----END PGP SIGNATURE-----

    Redirect Errors and Warnings to stderr

The rewriting has created an unsigned multiline commit of the previously signed single-line commit.

Keep that in mind before going to rewrite signed commits.

_

Tweet about this on TwitterShare on RedditShare on FacebookShare on Google+Pin on PinterestShare on LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *