Skip to content

Instantly share code, notes, and snippets.

@vojtajina
Created November 5, 2011 08:21
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 vojtajina/1341268 to your computer and use it in GitHub Desktop.
Save vojtajina/1341268 to your computer and use it in GitHub Desktop.
Simple git script for rewriting history
#!/bin/sh
#
# Simple script for rewriting history :-D
# Might be helpful when using "rebasing" strategy to keep your history nice and flat...
#
# Instalation
# >> sudo bash -c "curl https://raw.github.com/gist/1341268/git-edit.sh > /usr/local/bin/git-edit"
# >> sudo chmod a+x /usr/local/bin/git-edit
#
# Usage
# Let's say you are on "master" branch, which looks like this:
# A -> B -> C -> D(HEAD master)
#
# You decide you want to change commit "B"...
#
# >> git edit <B>
#
# Now, ammend the commit, add more commits, etc...
# Let's say you changed "B" to "B1" and added one more commit "B2"
#
# >> git edit --done
# Will rebase "master" branch on the top of your latest changes, so the result will be:
# A -> B1 -> B2 -> C -> D(HEAD master)
#
GIT_DIR=`git rev-parse --git-dir`
ORIGINAL_REF_FILE="$GIT_DIR/refs/EDIT_ORIGINAL"
BRANCH_NAME_FILE="$GIT_DIR/EDIT_BRANCH"
start() {
# edit commit
ORIGINAL_REF=`git rev-parse --verify $1 2> /dev/null`
if test "$ORIGINAL_REF" = ""; then
error "Unknown revision or path \"$1\""
fi
# head
BRANCH_NAME=$(git_current_branch)
if test "$BRANCH_NAME" = ""; then
error "You are in 'detached HEAD' state, can not edit commit"
fi
# must be on the same path
if test `git merge-base $ORIGINAL_REF $BRANCH_NAME` != "$ORIGINAL_REF"; then
error "\"$ORIGINAL_REF\" is not predecessor of \"$BRANCH_NAME\" branch"
fi
git checkout -q $ORIGINAL_REF || exit 1
echo "You are now on \"$ORIGINAL_REF\". Feel free to ammend or add new commits :-D"
echo "When done, to rebase \"$BRANCH_NAME\" branch, run:"
echo " git edit --done"
# save refs
echo $ORIGINAL_REF > $ORIGINAL_REF_FILE
echo $BRANCH_NAME > $BRANCH_NAME_FILE
}
finish() {
ORIGINAL_REF=`cat $ORIGINAL_REF_FILE 2> /dev/null`
BRANCH_NAME=`cat $BRANCH_NAME_FILE 2> /dev/null`
NEW_REF=`git rev-parse HEAD`
if test "$ORIGINAL_REF" = "" || test "$BRANCH_NAME" = ""; then
error "Not in the editing process"
fi
git checkout -q $BRANCH_NAME
git rebase --onto $NEW_REF $ORIGINAL_REF
# clean up
rm $ORIGINAL_REF_FILE
rm $BRANCH_NAME_FILE
}
git_current_branch() {
git branch --no-color | grep '^\* ' | grep -v 'no branch' | sed 's/^* //g'
}
error() {
echo "Error: $1 !"
exit 1
}
if test $# -eq 0; then
echo "Usage: git edit [--done] [<commit-to-edit>]"
exit 1
fi
if test "$1" = "--done"; then
finish
else
start $1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment