#/usr/bin/env sh
#
# If you want to change a commit within a reviewed branch, use this
# script as follows:
#
#  - invoke it with a commit id as argument
#  - the commit is checked out, make, test and stage your changes...
#  - invoke the script again without any arguments
#
# Author: Stephan Beyer

MODEFILE="$(git rev-parse --git-dir)/GIT-FIX-COMMIT-DATA"
if [ ! -f "$MODEFILE" ]
then # start
	COMMITSHA="$1"
	FEATUREBRANCH="$(git rev-parse --abbrev-ref HEAD)"
	if [ -z "$COMMITSHA" ]
	then
		cat <<EOF
Usage information:

Make sure you are on a feature branch.
Let <commit-id> be the SHA of the commit you want to change.
Run

	$0 <commit-id>

The commit to change is checked out.
Make your changes and stage them (using git add).
Make sure you do not have a dirty working tree (no unstaged changes).
Then run

	$0

And that's it.
EOF
		exit 1
	fi

	if [ "$FEATUREBRANCH" = "HEAD" -o "$FEATUREBRANCH" = "master" ]
	then
		echo "Error: please checkout a feature branch!"
		exit 1
	fi

	if ! git rev-list master.."$FEATUREBRANCH" | grep -q "$(git rev-parse "$COMMITSHA")"
	then
		echo "Error: the commit is not on the feature branch!"
		exit 1
	fi

	git checkout "$COMMITSHA" || exit
	echo "$COMMITSHA" > "$MODEFILE"
	echo "$FEATUREBRANCH" >> "$MODEFILE"
	cat <<EOF
================================================================'

The commit to change ($COMMITSHA) is checked out.
Make your changes and stage all changes you want to apply
(using, for example, git add -p).
When you are done, make sure that you have no unstaged changes
and invoke

	$0

without any arguments.
EOF
else # finish
	COMMITSHA="$(head -n 1 "$MODEFILE")"
	FEATUREBRANCH="$(tail -n 1 "$MODEFILE")"

	if [ -z "$COMMITSHA" ]
	then
		cat <<EOF
There is already a fix-commit session in progress
where the commit $COMMITSHA had to be changed
in branch $FEATUREBRANCH.

Make your changes and stage them (using, e.g., git add -p).
Make sure you do not have a dirty working tree (no unstaged changes).
Then run

	$0

and that's it.

If you want to abort the fix-commit session instead, make sure
you have no uncommited changes and run

	rm \"$MODEFILE\"
	git checkout \"$FEATUREBRANCH\"
EOF
		exit 1
	else
		if ! git diff --quiet
		then
			echo "Error: there are unstaged changes!"
			echo
			echo "You can use 'git stash --keep-index' to stash them away."
			exit 2
		fi

		git commit --amend &&
		git rebase --onto HEAD "$COMMITSHA" "$FEATUREBRANCH"
		rm -f "$MODEFILE"
	fi
fi
