Last active
August 29, 2015 14:07
-
-
Save nottrobin/11b9f9cc1dc8dd3d2601 to your computer and use it in GitHub Desktop.
git: amend-at-commit
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 | |
: <<'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