Last active
April 3, 2024 18:48
-
-
Save hoegaarden/5c75d61ad223dc9ccca1c9fde9e501c4 to your computer and use it in GitHub Desktop.
git rebase, but keep author, committer & dates
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
#!/usr/bin/env bash | |
set -eu | |
set -o pipefail | |
usage() { | |
local me="$( basename "$0" | sed 's/^git-//' )" | |
cat <<EOF | |
git $me [target] | |
Does an interactive git rebase onto [target], but tries to keep the same | |
author, committer and author- and commit-dates as on the original commits | |
before the rebase. | |
This should give you somewhat the same UX as with a normal git rebase, the | |
todo list will just be a bit longer and inject \`exec\`s which after each | |
\`pick\` which reset the author & committer data back to the original. | |
EOF | |
} | |
genTodoList() { | |
local pick='pick %h %s' | |
local envAuthor="GIT_AUTHOR_NAME='%an' GIT_AUTHOR_EMAIL='%ae' GIT_AUTHOR_DATE='format:iso8601:%aI'" | |
local envCommitter="GIT_COMMITTER_NAME='%cn' GIT_COMMITTER_EMAIL='%ce' GIT_COMMITTER_DATE='format:iso8601:%cI'" | |
local amend="exec ${envAuthor} ${envCommitter} git commit --quiet --amend --reset-author --no-edit" | |
git log \ | |
--reverse \ | |
--format="${pick}%n${amend}%n" \ | |
"${1}..HEAD" | |
} | |
genEditor() { | |
cat <<'EOF' | sed -e "s@__TODO__@${1}@g" -e "s@__EDITOR__@${2}@g" | |
#!/usr/bin/env bash | |
set -eu | |
set -o pipefail | |
sed 's/^/# /g' "$1" > '__TODO__.org' | |
{ | |
cat '__TODO__' | |
echo | |
echo '# ----[ original todo list ]----' | |
cat '__TODO__.org' | |
} > "$1" | |
exec '__EDITOR__' "$@" | |
EOF | |
} | |
findDefaultEditor() { | |
[ -n "${GIT_EDITOR:-}" ] && { echo "$GIT_EDITOR" ; return ; } | |
[ -n "${EDITOR:-}" ] && { echo "$EDITOR" ; return ; } | |
[ -n "${VISUAL:-}" ] && { echo "$VISUAL" ; return ; } | |
command -v sensible-editor >/dev/null && { echo sensible-editor ; return ; } | |
echo 'vi' | |
} | |
main() { | |
if [ "$#" -ne 1 ] | |
then | |
usage >&2 | |
exit 1 | |
fi | |
local tempDir todo todoEditor defaultEditor target | |
tempDir="$( mktemp -d )" | |
# shellcheck disable=SC2064 | |
trap "rm -rf -- '$tempDir'" EXIT | |
todo="${tempDir}/todo" | |
todoEditor="${tempDir}/editor" | |
defaultEditor="$( findDefaultEditor )" | |
target="$1" | |
genTodoList "$target" > "$todo" | |
genEditor "$todo" "$defaultEditor" > "$todoEditor" | |
chmod +x "$todoEditor" | |
GIT_EDITOR="$todoEditor" git rebase --interactive "${target}" | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment