Instantly share code, notes, and snippets.
Last active
August 13, 2021 14:04
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save liamnewmarch/69df7ddfa3662ab22196f54ba22bcf86 to your computer and use it in GitHub Desktop.
Correct git author name and email for a branch by rewriting its history.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# shellcheck disable=SC2016 | |
# Rewrite git history. | |
readonly VERSION='2.0.5' | |
# Exit immediately if a command exits with a non-zero status. | |
set -e | |
exit_with_help_text() { | |
printf ' | |
usage: | |
git fix-author (--set-name=<name> | --set-email=<email>) [<args>] | |
args: | |
-v, --version Print version number. | |
-h, --help Print this help text. | |
-n, --set-name Rewrite commits to have this author name. | |
-e, --set-email Rewrite commits to have this author email. | |
-N, --filter-name Only rewrite commits originally by this author name. | |
-E, --filter-email Only rewrite commits originally by this author email. | |
description: | |
This command corrects git author name and email for a branch by by rewriting | |
its history. By default it will update all commits; use the optional filter | |
flags to update commits from a specific author. | |
example: | |
git fix-author -e bob@example.com -E alice@example.com | |
' | |
exit 0 | |
} | |
exit_with_version_text() { | |
printf '%s\n' "$VERSION" | |
exit 0 | |
} | |
exit_with_unknown_param_error() { | |
printf 'Error: Unknown parameter %s.\n' "$1" | |
exit 1 | |
} | |
clean_up() { | |
unset filter replace_email replace_name search_email search_name | |
} | |
get_params() { | |
for _; do | |
case "$1" in | |
# Version param. | |
-v|--version) | |
exit_with_version_text | |
;; | |
# Help param. | |
-h|--help) | |
exit_with_help_text | |
;; | |
# Replacement email. | |
-e|--set-email) | |
shift | |
replace_email=$1 | |
;; | |
--set-email=*) | |
replace_email="${1#*=}" | |
;; | |
# Replacement name. | |
-n|--set-name) | |
shift | |
replace_name=$1 | |
;; | |
--set-name=*) | |
replace_name="${1#*=}" | |
;; | |
# Search email. | |
--filter-email) | |
shift | |
search_email=$1 | |
;; | |
--filter-email=*) | |
search_email="${1#*=}" | |
;; | |
# Search name. | |
--filter-name) | |
shift | |
search_name=$1 | |
;; | |
--filter-name=*) | |
search_name="${1#*=}" | |
;; | |
# Unknown params. | |
*) | |
exit_with_unknown_param_error "$1" | |
;; | |
esac | |
shift | |
done | |
# Exit with help text if neither replace_name nor replace_email has been set. | |
if [[ -z "$replace_name" ]] && [[ -z "$replace_email" ]]; then | |
exit_with_help_text | |
fi | |
} | |
create_commit_filter() { | |
# We use double quoted strings to build our filter and these variables need | |
# to be passed verbatim to git filter-branch. It's convenient to store these | |
# as variables to avoid escaping later. | |
local git_author_email='"$GIT_AUTHOR_EMAIL"' | |
local git_author_name='"$GIT_AUTHOR_NAME"' | |
local default_filter='git commit-tree "$@"' | |
# Starting point for the commit filter. | |
filter="$default_filter;" | |
# If specified, add name replacing to filter command. | |
if [[ -n "$replace_name" ]]; then | |
filter=" | |
GIT_COMMITTER_NAME='$replace_name'; | |
GIT_AUTHOR_NAME='$replace_name'; | |
$filter | |
" | |
fi | |
# If specified, add email replacing to filter command. | |
if [[ -n "$replace_email" ]]; then | |
filter=" | |
GIT_COMMITTER_EMAIL='$replace_email'; | |
GIT_AUTHOR_EMAIL='$replace_email'; | |
$filter | |
" | |
fi | |
# If specified, add name search to filter command. | |
if [[ -n "$search_name" ]]; then | |
filter=" | |
if [[ $git_author_name = '$search_name' ]]; then | |
$filter | |
else | |
$default_filter; | |
fi | |
" | |
fi | |
# If specified, add email search to filter command. | |
if [[ -n "$search_email" ]]; then | |
filter=" | |
if [[ $git_author_email = '$search_email' ]]; then | |
$filter | |
else | |
$default_filter; | |
fi | |
" | |
fi | |
} | |
execute_commit_filter() { | |
git filter-branch --commit-filter "$filter" --force HEAD | |
} | |
main() { | |
get_params "$@" | |
create_commit_filter | |
execute_commit_filter | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment