Quiz Quiz - 2 months ago 6
Git Question

Change the author for commits with specific message

I have many legacy commits from maven plugin which use real user credentials.
I know how to find commits by email and change the author (short version for example):

#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_EMAIL="your-correct-email@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --all


How can I filter commits by a message that starts with "[maven-plugin] ..."?

Answer

First, note that the way git filter-branch works is by copying commits. It extracts stuff out of the existing, to-be-filtered commits, runs each of the filters you've supplied, and then makes a new commit from the result. If the new commit exactly matches the old commit, the new commit's ID equals the old commit's ID, which means the new commit is the old commit; otherwise the new commit gets a new, different hash.

While all this is going on, filter-branch records a map: "old hash was X, new hash is Y". Then it runs through the references (branch and tag names and such) to be filtered and, if reference R used to point to X, filter-branch makes R point to Y instead.

You can, in fact, change pretty much anything. The tricky part is deciding which commits should get changed, and then actually changing the right things for only those commits. In this case, you want to modify the copies of commits whose message starts with a known string.

The standard --env-filter is invoked this way:

eval "$filter_env" < /dev/null ||
    die "env filter failed: $filter_env"

This means it does not have immediate access to the commit message. It does, however, have the commit's ID (in $GIT_COMMIT), so all you need to do is read the commit message and make your environment variable changes conditional on that:

if git log --no-walk --pretty=format:%b $GIT_COMMIT |
    grep '^\[maven-plugin] ' >/dev/null
then
    export GIT_AUTHOR_NAME="new author name" ... # set exports here
fi

Using git log --no-walk --format=<format>, you can extract anything you like from the previous commit. (If your git log command is very old you need the --pretty=format: or --pretty=tformat: spelling.)

For the set of things you can export, see the git commit-tree documentation.