'
SUBDIRECTORY_OK=Yes
+OPTIONS_SPEC=
. git-sh-setup
set_reflog_action rebase
require_work_tree
die "$RESOLVEMSG"
fi
- cmt=`cat $dotest/current`
- if ! git diff-index --quiet HEAD
+ cmt=`cat "$dotest/current"`
+ if ! git diff-index --quiet HEAD --
then
if ! git-commit -C "$cmt"
then
}
call_merge () {
- cmt="$(cat $dotest/cmt.$1)"
+ cmt="$(cat "$dotest/cmt.$1")"
echo "$cmt" > "$dotest/current"
hd=$(git rev-parse --verify HEAD)
- cmt_name=$(git symbolic-ref HEAD)
- msgnum=$(cat $dotest/msgnum)
- end=$(cat $dotest/end)
+ cmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)
+ msgnum=$(cat "$dotest/msgnum")
+ end=$(cat "$dotest/end")
eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
- eval GITHEAD_$hd='"$(cat $dotest/onto_name)"'
+ eval GITHEAD_$hd='$(cat "$dotest/onto_name")'
export GITHEAD_$cmt GITHEAD_$hd
git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
rv=$?
esac
}
+move_to_original_branch () {
+ test -z "$head_name" &&
+ head_name="$(cat "$dotest"/head-name)" &&
+ onto="$(cat "$dotest"/onto)" &&
+ orig_head="$(cat "$dotest"/orig-head)"
+ case "$head_name" in
+ refs/*)
+ message="rebase finished: $head_name onto $onto"
+ git update-ref -m "$message" \
+ $head_name $(git rev-parse HEAD) $orig_head &&
+ git symbolic-ref HEAD $head_name ||
+ die "Could not move back to $head_name"
+ ;;
+ esac
+}
+
finish_rb_merge () {
- if test -f "$dotest/stash"
- then
- stash=$(cat "$dotest/stash")
- git stash apply --index "$stash"
- fi
+ move_to_original_branch
rm -r "$dotest"
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 () {
test -f "$dotest"/interactive ||
- while case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
- do
+ while :; do case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
shift
done && test -n "$1"
}
is_interactive "$@" && exec git-rebase--interactive "$@"
-while case "$#" in 0) break ;; esac
+while test $# != 0
do
case "$1" in
--continue)
}
if test -d "$dotest"
then
- prev_head="`cat $dotest/prev_head`"
- end="`cat $dotest/end`"
- msgnum="`cat $dotest/msgnum`"
- onto="`cat $dotest/onto`"
+ prev_head=$(cat "$dotest/prev_head")
+ end=$(cat "$dotest/end")
+ msgnum=$(cat "$dotest/msgnum")
+ onto=$(cat "$dotest/onto")
continue_merge
while test "$msgnum" -le "$end"
do
finish_rb_merge
exit
fi
- stash=$(read_stash ".dotest/stash")
- git am --resolved --3way --resolvemsg="$RESOLVEMSG"
- unstash_and_exit "$stash"
+ head_name=$(cat .dotest/head-name) &&
+ onto=$(cat .dotest/onto) &&
+ orig_head=$(cat .dotest/orig-head) &&
+ git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
+ move_to_original_branch
+ exit
;;
--skip)
+ git reset --hard HEAD || exit $?
if test -d "$dotest"
then
git rerere clear
- prev_head="`cat $dotest/prev_head`"
- end="`cat $dotest/end`"
- msgnum="`cat $dotest/msgnum`"
+ prev_head=$(cat "$dotest/prev_head")
+ end=$(cat "$dotest/end")
+ msgnum=$(cat "$dotest/msgnum")
msgnum=$(($msgnum + 1))
- onto="`cat $dotest/onto`"
+ onto=$(cat "$dotest/onto")
while test "$msgnum" -le "$end"
do
call_merge "$msgnum"
finish_rb_merge
exit
fi
- stash=$(read_stash ".dotest/stash")
- git am -3 --skip --resolvemsg="$RESOLVEMSG"
- unstash_and_exit "$stash"
+ head_name=$(cat .dotest/head-name) &&
+ onto=$(cat .dotest/onto) &&
+ orig_head=$(cat .dotest/orig-head) &&
+ git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
+ move_to_original_branch
+ exit
;;
--abort)
git rerere clear
if test -d "$dotest"
then
- if test -f "$dotest/stash"
- then
- stash=$(cat "$dotest/stash")
- fi
+ move_to_original_branch
rm -r "$dotest"
elif test -d .dotest
then
- if test -f ".dotest/stash"
- then
- stash=$(cat ".dotest/stash")
- fi
+ dotest=.dotest
+ move_to_original_branch
rm -r .dotest
else
die "No rebase in progress?"
fi
git reset --hard ORIG_HEAD
- test -z "$stash" || git stash apply --index "$stash"
exit
;;
--onto)
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.
upstream_name="$1"
upstream=`git rev-parse --verify "${upstream_name}^0"` ||
onto_name=${newbase-"$upstream_name"}
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 test -x "$GIT_DIR/hooks/pre-rebase"
then
"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
echo >&2 "The pre-rebase hook refused to rebase."
- test -z "$stash" || git stash apply --index "$stash"
exit 1
}
fi
case "$#" in
2)
branch_name="$2"
- git-checkout "$2" || {
- test -z "$stash" || git stash apply --index "$stash"
- usage
- }
+ git-checkout "$2" || usage
;;
*)
if branch_name=`git symbolic-ref -q HEAD`
! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null
then
echo >&2 "Current branch $branch_name is up to date."
- test -z "$stash" || git stash apply --index "$stash"
exit 0
fi
GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
fi
+# move to a detached HEAD
+orig_head=$(git rev-parse HEAD^0)
+head_name=$(git symbolic-ref HEAD 2> /dev/null)
+case "$head_name" in
+'')
+ head_name="detached HEAD"
+ ;;
+*)
+ git checkout "$orig_head" > /dev/null 2>&1 ||
+ die "could not detach HEAD"
+ ;;
+esac
+
# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
echo "First, rewinding head to replay your work on top of it..."
git-reset --hard "$onto"
if test "$mb" = "$branch"
then
echo >&2 "Fast-forwarded $branch_name to $onto_name."
- test -z "$stash" || git stash apply --index "$stash"
+ move_to_original_branch
exit 0
fi
if test -z "$do_merge"
then
git format-patch -k --stdout --full-index --ignore-if-in-upstream "$upstream"..ORIG_HEAD |
- git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG"
- 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
+ git am $git_am_opt --binary -3 -k --resolvemsg="$RESOLVEMSG" &&
+ move_to_original_branch
+ ret=$?
+ test 0 != $ret -a -d .dotest &&
+ echo $head_name > .dotest/head-name &&
+ echo $onto > .dotest/onto &&
+ echo $orig_head > .dotest/orig-head
+ exit $ret
fi
# start doing a rebase with git-merge
mkdir -p "$dotest"
echo "$onto" > "$dotest/onto"
echo "$onto_name" > "$dotest/onto_name"
-prev_head=`git rev-parse HEAD^0`
+prev_head=$orig_head
echo "$prev_head" > "$dotest/prev_head"
-test -z "$stash" || echo "$stash" >"$dotest/stash"
+echo "$orig_head" > "$dotest/orig-head"
+echo "$head_name" > "$dotest/head-name"
msgnum=0
for cmt in `git rev-list --reverse --no-merges "$upstream"..ORIG_HEAD`