I have a repository where there are some (actually a lot) commits generated by a program that look like:
Adding new domains: example.com
It happened (because of a wrong configuration) that these commits were made in the name of a co-worker. Now, I want to change these commits author:
Some Bot <[email protected]>
Github has a public script posted here to change the commits filtered by an old author. In this case, I want to change the author of commits whom messages start with a pattern: Adding new domains:. How can I do that?
You can use the --env-filter
and rev-list
arguments (--grep=<pattern>
in this case) to limit the commits to the ones you want to modify:
#!/bin/sh
git filter-branch --env-filter '
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
' --tag-name-filter cat -- --branches --tags --grep='Adding new domains'
You could save this script with the git- prefix and place it somewhere in your PATH, eg. /usr/local/bin/git-change-author
(make sure it's executable) and run it from your repository as:
git change-author
Don't forget to git push --force
since you rewrote the history.
In this case I think you will have to use the --commit-filter
filter. This is the only way to get your hands on both the commit message (from stdin) and the environment variables at the same time. The new script will have to completely replicate all the functionality of commit-tree
. Fortunately, it won't look all that different from the GitHub script you linked.
First, read the entire commit message into a Bash variable:
commitmsg=$(cat)
Now get the first line of it and test whether it matches:
firstline=$(echo "$commitmsg" | head -n1 | grep "Adding new domains:")
if [ "$firstline" ]; then
We matched the commit message, so do the regular replacement, like in GitHub's script.
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
Now we must call git commit-tree
. The commit message is provided on stdin, just like we got it. Since our script is acting as a commit-tree
surrogate, we need to pass all arguments on as well. The environment variables we (may have) modified will take care of themselves.
echo "$commitmsg" | git commit-tree "$@"
This will emit the hash onto stdout, just like we are required to do. At this point, we're done!
Here's a copy of the completed script. YMMV, of course, but I tested it and it works fine.
#!/bin/bash
git filter-branch --commit-filter '
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="[email protected]"
commitmsg=$(cat)
firstline=$(echo "$commitmsg" | head -n1 | grep "Adding new domains:")
if [ "$firstline" ]; then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
echo "$commitmsg" | git commit-tree "$@"
' --tag-name-filter cat -- --branches --tags
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With