Skip to content

Instantly share code, notes, and snippets.

@nottrobin
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nottrobin/11b9f9cc1dc8dd3d2601 to your computer and use it in GitHub Desktop.
Save nottrobin/11b9f9cc1dc8dd3d2601 to your computer and use it in GitHub Desktop.
git: amend-at-commit
#!/bin/bash
: <<'HELP'
Amend at commit
===
If you stage some files to be committed with git
this script will then cycle back to a specific commit,
apply those changes to that commit.
I keep this file at ~/bin/git-amend-at-commit.sh, with +x set
and I have ~/bin in my path, which allows me to run the script directly.
Direct usage
---
To run the script directly, make sure you've staged the changes you
want to add to the amended commit, and that you don't have any
other changes in your working tree.
# After staging your changes
$ git-amend-at-commit.sh <commit-id-to-amend>
Git alias
---
You can add this script as a git alias by adding the following to your
`~/.gitconfig`:
[alias]
amend-at-commit = !~/bin/git-amend-at-commit.sh
Now you can run this as a git alias:
# After staging your changes
$ git amend-at-commit <commit-id-to-amend>
Recovering from failure
---
The script will output the current commit ID as one of the first things it does:
# Current HEAD:
5cd9050ae53f39aced2a1b80b78d8e9f65b2eec5
If things go wrong, you should be able to just jump back to this commit
and hopefully everything will be fine:
$ git cherry-pick --abort # Abort any existing cherry-pick commands
$ git reset --keep 5cd9050ae53f39aced2a1b80b78d8e9f65b2eec5
The script will also back-up the entire git log to `/tmp`,
and tell you where it is:
# Backing up log:
at/tmp/.1413462171.gitlog
HELP
if [ -z "$1" ]; then
echo "No commit ID specified"
exit 1
fi
if ! git diff --exit-code > /dev/null 2>&1; then
echo 'Unstaged changes, exiting.'
exit 1
fi
if git diff --cached --exit-code > /dev/null 2>&1; then
echo 'Nothing staged, exiting.'
exit 1
fi
COMMIT_TO_AMEND=`git rev-parse ${1}`
OLD_HEAD=`git rev-parse HEAD`
BACKUP_PATH=/tmp/.$(date +%s).gitlog
echo -e "\n# Current HEAD:"
echo ${OLD_HEAD}
echo -e "\n# Backing up log at:"
echo "${BACKUP_PATH}"
git log >> ${BACKUP_PATH}
echo -e "\n# Resetting to ${COMMIT_TO_AMEND}"
git reset --keep ${COMMIT_TO_AMEND}
echo -e "\n# Staging files"
git add .
echo -e "\n# Status before amend:"
git s
echo -e "\n# Amend commit ${COMMIT_TO_AMEND}"
git commit --amend --no-edit
echo -e "\n# New commit ID:"
git rev-parse HEAD
echo -e "\n# Cherry-pick from ${COMMIT_TO_AMEND} back to ${OLD_HEAD}"
git cherry-pick --allow-empty ${COMMIT_TO_AMEND}..${OLD_HEAD}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment