Last active
December 14, 2015 16:38
-
-
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
This file contains hidden or 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 | |
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 | |
This file contains hidden or 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
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