GIT rebase changes

Robert Shearman rob at codeweavers.com
Wed Jan 18 10:28:39 CST 2006


Mike McCormack wrote:

>
> Hi GIT users,
>
> The GIT guys have made rebase and pull incompatible, and to use rebase 
> (which is likely what we want to do for Wine), you must use "fetch" 
> then "rebase", not "pull" (which does a merge).


And on a slightly related note, I wrote a script which works kinda like 
rebase (and is based on the old version of rebase) that allows you to 
coalesce two patches in your tree. This is useful in two situations:
1. You commit a new feature and then realise after some extensive 
testing that there is a bug, so you commit a fix, don't want to send the 
two separate patches to wine-patches (maybe to save face :-), or maybe 
to reduce noise).
2. You revert a patch in your tree but don't want both the revert and 
the old patch in your patch queue as shown by git-format-patch or by 
Mike's mm-send-patch.

Note that the first commit chronologically must be the first commit on 
the command line.

-- 
Rob Shearman

-------------- next part --------------
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano.
# Copyright (c) 2005 Robert Shearman.
#

. git-sh-setup || die "Not a git archive."

usage="usage: $0 "'<commit1> <commit2>

Combines two commits into one commit (commit1 MUST occur before commit2)'

git-update-index --refresh || exit

case "$#" in
2) ;;
*)
    die "$usage" ;;
esac

commit1=`git-rev-parse --verify "$1"` &&
commit1parent=`git-rev-list --max-count=2 $commit1 | tail -n1` &&
commit2=`git-rev-parse --verify "$2"` &&
ours=`git-rev-parse --verify HEAD` || exit
# FIXME: verify commit1 occurs before commit2
different1=$(git-diff-index --name-only --cached "$ours") &&
different2=$(git-diff-index --name-only "$ours") &&
test "$different1$different2" = "" ||
die "Your working tree does not match HEAD."

git-read-tree -m -u $ours $commit1parent &&
new_head=$(git-rev-parse --verify "$commit1parent^0") &&
git-update-ref HEAD "$new_head" || exit

tmp=.rebase-tmp$$
fail=$tmp-fail
trap "rm -rf $tmp-*" 1 2 3 15

>$fail

coalesce_succeeded=t
S=$(git-rev-parse --verify HEAD) &&
git-cherry-pick --no-commit --replay $commit1 || {
# shouldn't happen
	echo >&2 "* Not applying the patch and continuing."
	echo $commit1 >>$fail
	git-reset --hard $S
	coalesce_succeeded=f
}
echo "Coalescing $commit1 and $commit2" > .coalescemsg
echo "First commit:" >> .coalescemsg
echo >> .coalescemsg
cat .msg >> .coalescemsg
S=$(git-rev-parse --verify HEAD) &&
git-cherry-pick --no-commit --replay $commit2  || {
	echo >&2 "* Not applying the patch and continuing."
	echo $commit2 >>$fail
	git-reset --hard $S
	coalesce_succeeded=f
}
echo >> .coalescemsg
echo "Second commit:" >> .coalescemsg
echo >> .coalescemsg
cat .msg >> .coalescemsg

case "$coalesce_succeeded" in
t)
	git-commit --no-verify -F .coalescemsg --edit
	;;
esac
rm -f .coalescemsg


git-cherry -v $commit1parent $ours |
while read sign commit msg
do
	echo "$commit: $msg"
	case "$commit" in
	$commit1|$commit2)
		continue ;;
	esac

	case "$sign" in
	-)
		echo >&2 "* Already applied: $msg"
		continue ;;
	esac
	echo >&2 "* Applying: $msg"
	S=$(git-rev-parse --verify HEAD) &&
	git-cherry-pick --replay $commit || {
		echo >&2 "* Not applying the patch and continuing."
		echo $commit >>$fail
		git-reset --hard $S
}
done
if test -s $fail
then
	echo >&2 Some commits could not be rebased, check by hand:
	cat >&2 $fail
	echo >&2 "(the same list of commits are found in $tmp)"
	exit 1
else
	rm -f $fail
fi


More information about the wine-devel mailing list