Skip to content

Instantly share code, notes, and snippets.

@fcamblor
Last active December 14, 2015 16:38
Show Gist options
  • Save fcamblor/5116081 to your computer and use it in GitHub Desktop.
Save fcamblor/5116081 to your computer and use it in GitHub Desktop.
This bash script will allow you to make a "late amend" of a commit (not the latest) in your git history
#!/bin/bash
targetSha1=$1
currentSha1=`git rev-parse HEAD`
previousSha1=`git rev-parse HEAD^`
currentBranchName=`git rev-parse --abbrev-ref HEAD`
sha1ToApply=
if [ "" == "$1" ]
then
echo "Usage: late-amend <sha1WhichShouldBeAltered> [<sha1OfTheCommitToApply>]"
exit 0
fi
if [ "" != "$2" ]
then
sha1ToApply=$2
else
sha1ToApply=$currentSha1
fi
# Ensuring there is no pending changes in index
currentStatus=`git status -s | wc -l`
currentIgnorableStatus=`git status -s | grep "??" | wc -l`
if [ "$currentStatus" != "$currentIgnorableStatus" ]
then
echo "Pending changes in index !"
exit -1
fi
echo "No pending changes in index... processing..."
# Going to targetSha1 and creating a branch from there
echo "Creating temporary branch late-amend..."
git checkout $targetSha1 && git branch late-amend && git checkout late-amend || exit
# Cherry picking current commit and amending target commit with it
echo "Amending commit ... (git cherry-pick $sha1ToApply --no-commit && git commit --amend)"
(git cherry-pick $sha1ToApply --no-commit && git commit --amend) ||
{
echo "Failed to amend commit ! Please fix this problem then run following commands manually :"
echo " git commit --amend"
if [ "$targetSha1" != `git rev-parse $sha1ToApply` ]
then
echo " git cherry-pick $targetSha1..$sha1ToApply^"
fi
if [ "$currentSha1" != "$sha1ToApply" ]
then
echo " git cherry-pick $sha1ToApply..$currentSha1"
fi
echo " git checkout $currentBranchName && git reset --hard late-amend && git branch -D late-amend"
exit
}
# Re-applying every commit through current branch name -1... only if there is something to apply
# (we could be in the special case where $sha1ToApply^ == $targetSha1 => in that case, cherry pick will
# be useless and we should avoid it !)
if [ "$targetSha1" != `git rev-parse $sha1ToApply^` ]
then
echo "Rewinding commits ... (git cherry-pick $targetSha1..$sha1ToApply^)"
git cherry-pick $targetSha1..$sha1ToApply^ ||
{
echo "Failed to rewind commits ! Please fix this problem then run following commands manually :"
echo " git cherry-pick --continue"
if [ "$currentSha1" != "$sha1ToApply" ]
then
echo " git cherry-pick $sha1ToApply..$currentSha1"
fi
echo " git checkout $currentBranchName && git reset --hard late-amend && git branch -D late-amend"
exit
}
fi
# If sha1ToApply is not current sha1, we should cherry pick commits from sha1ToApply through currentSha1
if [ "$currentSha1" != "$sha1ToApply" ]
then
echo "Rewinding commits after $sha1ToApply... (git cherry-pick $sha1ToApply..$currentSha1)"
git cherry-pick $sha1ToApply..$currentSha1 ||
{
echo "Failed to rewind commits ! Please fix this problem then run following commands manually :"
echo " git cherry-pick --continue"
echo " git checkout $currentBranchName && git reset --hard late-amend && git branch -D late-amend"
exit
}
fi
# Updating current branch name reference
git checkout $currentBranchName && git reset --hard late-amend && git branch -D late-amend || exit
Use case :
o <- HEAD
|
....
|
o <- (2) Here, you fixed something wrong in (1)
|
....
|
o <- (1) Here, you've done something wrong
|
|
o
And you want to transform this into :
old HEAD -> o o <- HEAD
| |
.. ..
| |
old (2) -> o |
| |
.. ..
| |
old (1) -> o o <- (1+2) Amended commit with fix included for (1)
| |
\|
o
_Obviously, your remote origin/XXX branch is located *before* the commit (1) ... that is to say : you didn't pushed anything yet !_
Warning : if you have refs (branches/tags) located between (1) and HEAD, they won't be moved to the (1+2) branch !
Use script above and pass SHA1 of (1) as first parameter, and SHA1 of (2) as second parameter (eventually, you can omit second parameter if commit fixing (1) is located on your HEAD)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment