rebase: allow starting from a dirty tree.

This uses the new "git stash create" interface to stash away the dirty state
you have in your working tree before starting a rebase, and then replaying
it when you are done with stashing.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Junio C Hamano 2007-07-09 00:51:23 -07:00
parent bc9e7399af
commit 6c9ad166db
1 changed files with 58 additions and 14 deletions

View File

@ -116,10 +116,30 @@ call_merge () {
} }


finish_rb_merge () { finish_rb_merge () {
if test -f "$dotest/stash"
then
stash=$(cat "$dotest/stash")
git stash apply --index "$stash"
fi
rm -r "$dotest" rm -r "$dotest"
echo "All done." echo "All done."
} }


read_stash () {
if test -f "$1"
then
cat "$1"
fi
}
unstash_and_exit () {
err=$?
if test -f "$1" && test $err = 0
then
git stash apply --index "$1"
fi
exit $err
}

is_interactive () { is_interactive () {
test -f "$dotest"/interactive || test -f "$dotest"/interactive ||
while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
@ -154,8 +174,9 @@ do
finish_rb_merge finish_rb_merge
exit exit
fi fi
stash=$(read_stash ".dotest/stash")
git am --resolved --3way --resolvemsg="$RESOLVEMSG" git am --resolved --3way --resolvemsg="$RESOLVEMSG"
exit unstash_and_exit "$stash"
;; ;;
--skip) --skip)
if test -d "$dotest" if test -d "$dotest"
@ -174,21 +195,31 @@ do
finish_rb_merge finish_rb_merge
exit exit
fi fi
stash=$(read_stash ".dotest/stash")
git am -3 --skip --resolvemsg="$RESOLVEMSG" git am -3 --skip --resolvemsg="$RESOLVEMSG"
exit unstash_and_exit "$stash"
;; ;;
--abort) --abort)
git rerere clear git rerere clear
if test -d "$dotest" if test -d "$dotest"
then then
if test -f "$dotest/stash"
then
stash=$(cat "$dotest/stash")
fi
rm -r "$dotest" rm -r "$dotest"
elif test -d .dotest elif test -d .dotest
then then
if test -f ".dotest/stash"
then
stash=$(cat ".dotest/stash")
fi
rm -r .dotest rm -r .dotest
else else
die "No rebase in progress?" die "No rebase in progress?"
fi fi
git reset --hard ORIG_HEAD git reset --hard ORIG_HEAD
test -z "$stash" || git stash apply --index "$stash"
exit exit
;; ;;
--onto) --onto)
@ -254,16 +285,6 @@ else
fi fi
fi fi


# The tree must be really really clean.
git update-index --refresh || exit
diff=$(git diff-index --cached --name-status -r HEAD)
case "$diff" in
?*) echo "cannot rebase: your index is not up-to-date"
echo "$diff"
exit 1
;;
esac

# The upstream head must be given. Make sure it is valid. # The upstream head must be given. Make sure it is valid.
upstream_name="$1" upstream_name="$1"
upstream=`git rev-parse --verify "${upstream_name}^0"` || upstream=`git rev-parse --verify "${upstream_name}^0"` ||
@ -273,11 +294,19 @@ upstream=`git rev-parse --verify "${upstream_name}^0"` ||
onto_name=${newbase-"$upstream_name"} onto_name=${newbase-"$upstream_name"}
onto=$(git rev-parse --verify "${onto_name}^0") || exit onto=$(git rev-parse --verify "${onto_name}^0") || exit


# The tree must be clean enough for us to create a stash
stash=$(git stash create) || exit
if test -n "$stash"
then
echo >&2 "Stashed away your working tree changes"
fi

# If a hook exists, give it a chance to interrupt # If a hook exists, give it a chance to interrupt
if test -x "$GIT_DIR/hooks/pre-rebase" if test -x "$GIT_DIR/hooks/pre-rebase"
then then
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || { "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
echo >&2 "The pre-rebase hook refused to rebase." echo >&2 "The pre-rebase hook refused to rebase."
test -z "$stash" || git stash apply --index "$stash"
exit 1 exit 1
} }
fi fi
@ -286,7 +315,10 @@ fi
case "$#" in case "$#" in
2) 2)
branch_name="$2" branch_name="$2"
git-checkout "$2" || usage git-checkout "$2" || {
test -z "$stash" || git stash apply --index "$stash"
usage
}
;; ;;
*) *)
if branch_name=`git symbolic-ref -q HEAD` if branch_name=`git symbolic-ref -q HEAD`
@ -309,6 +341,7 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null ! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null
then then
echo >&2 "Current branch $branch_name is up to date." echo >&2 "Current branch $branch_name is up to date."
test -z "$stash" || git stash apply --index "$stash"
exit 0 exit 0
fi fi


@ -328,6 +361,7 @@ git-reset --hard "$onto"
if test "$mb" = "$branch" if test "$mb" = "$branch"
then then
echo >&2 "Fast-forwarded $branch_name to $onto_name." echo >&2 "Fast-forwarded $branch_name to $onto_name."
test -z "$stash" || git stash apply --index "$stash"
exit 0 exit 0
fi fi


@ -335,7 +369,16 @@ if test -z "$do_merge"
then then
git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD | git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD |
git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG"
exit $? err=$?

if test $err = 0
then
test -z "$stash" || git stash apply --index "$stash"
exit
else
test -z "$stash" || echo "$stash" >.dotest/stash
exit $err
fi
fi fi


# start doing a rebase with git-merge # start doing a rebase with git-merge
@ -346,6 +389,7 @@ echo "$onto" > "$dotest/onto"
echo "$onto_name" > "$dotest/onto_name" echo "$onto_name" > "$dotest/onto_name"
prev_head=`git rev-parse HEAD^0` prev_head=`git rev-parse HEAD^0`
echo "$prev_head" > "$dotest/prev_head" echo "$prev_head" > "$dotest/prev_head"
test -z "$stash" || echo "$stash" >"$dotest/stash"


msgnum=0 msgnum=0
for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD` for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD`