Sometimes, I need to change the author/committer email and name (assume author=committer always) for all commits in a repository. I need to do this once for repo, but I may need to do it for multiple repos. I'm using this great answer:
How to amend several commits in Git to change author
git filter-repo --commit-callback '
if commit.author_email == b"incorrect@email":
commit.author_email = b"correct@email"
commit.author_name = b"Correct Name"
commit.committer_email = b"correct@email"
commit.committer_name = b"Correct Name"
'
However, every time I want to run this command for a new repository, I need to manually change incorrect@email, correct@email and Correct Name in the command above. I want to put this in a shell script, which:
- accepts arguments
old_email,new_emailandauthor. - has default values for these arguments, if one or more is not passed
- if a different argument is passed, it generates an error
How can I do that?
EDIT: I cooked up a preliminary implementation, but it doesn't work:
#!/bin/bash
# Define default values for email and name
old_email="incorrect@email"
new_email="correct@email"
new_name="Correct Name"
# Parse named arguments with getopts
while getopts ":o:n:e:" opt; do
case $opt in
o) old_email="$OPTARG" ;;
n) new_name="$OPTARG" ;;
e) new_email="$OPTARG" ;;
\?) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
esac
done
# Shift arguments to remove processed options
shift $((OPTIND-1))
# Check if any remaining arguments (unexpected)
if [ $# -gt 0 ]; then
echo "Unexpected arguments provided." >&2
exit 1
fi
# Construct the filter command using here-string
filter_cmd=$(cat << EOF '
if commit.author_email == b"$old_email":
commit.author_email = b"$new_email"
commit.author_name = b"$new_name"
commit.committer_email = b"$new_email"
commit.committer_name = b"$new_name"
'
EOF
)
# Run git filter-repo with the constructed command
echo "git filter-repo --commit-callback "$filter_cmd""
git filter-repo --commit-callback "$filter_cmd"
# Run git log to confirm that filtering worked
git log
Running this in a git repository gives me:
cat: ''$'\n''if commit.author_email == b"$old_email":'$'\n'' commit.author_email = b"$new_email"'$'\n'' commit.author_name = b"$new_name"'$'\n'' commit.committer_email = b"$new_email"'$'\n'' commit.committer_name = b"$new_name"'$'\n': No such file or directory
You can do this all in one shot by using
elifandelsein the callback, as demonstrated in thegit-filter-repodocumentation examples, like this:Add additional swaps in
elifblocks and the default in theelseblock.Side Note: In the example in your question, you are setting both the Author and Committer based on the Author alone. Perhaps they are always the same in your repo in which case it doesn't matter. If they do ever differ though, you may wish to handle them separately.