#!/usr/bin/env bash # This essentially makes the current commit empty so you can see the full diff # of the commit to be amended. # # This allows something similar to "Amend Last Commit" of git gui. set -euo pipefail old_commit=$(git rev-parse HEAD) git-fmt() { git show -s --format="$1" } title=$(git-fmt %s) message=$(git-fmt %B) GIT_AUTHOR_NAME=$(git-fmt %an) GIT_AUTHOR_EMAIL=$(git-fmt %ae) GIT_AUTHOR_DATE=$(git-fmt %aD) GIT_COMMITTER_NAME=$(git-fmt %cn) GIT_COMMITTER_EMAIL=$(git-fmt %ce) GIT_COMMITTER_DATE=$(git-fmt %cD) export \ GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE \ GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE git reset --soft HEAD~1 new_commit=$(git commit-tree -p HEAD 'HEAD^{tree}' -m "$message") git update-ref -m "amend-last: $title" HEAD "$new_commit" # If we're rebasing, git stores the current commit in rebase-merge/amend to # know whether --continue should result in an amend. If we don't update this, # --continue will complain that we have unstaged changes instead. if git rev-parse -q --verify rebase-merge/amend; then git update-ref rebase-merge/amend "$new_commit" "$old_commit" fi