diff options
author | Johannes Schindelin <Johannes.Schindelin@gmx.de> | 2007-11-08 18:19:08 +0000 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2007-11-09 01:30:31 -0800 |
commit | 6fd2f5e60d4d574ff9e5dd8ce1e229328c785d69 (patch) | |
tree | 8f8845588cab44b7ad392ce52fb89316ad1c5600 /git-rebase.sh | |
parent | c238dad407aec1ccf6e364f9c95e10e7f84eac8f (diff) | |
download | git-6fd2f5e60d4d574ff9e5dd8ce1e229328c785d69.tar.gz |
rebase: operate on a detached HEAD
The interactive version of rebase does all the operations on a detached
HEAD, so that after a successful rebase, <branch>@{1} is the pre-rebase
state. The reflogs of "HEAD" still show all the actions in detail.
This teaches the non-interactive version to do the same.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'git-rebase.sh')
-rwxr-xr-x | git-rebase.sh | 56 |
1 files changed, 51 insertions, 5 deletions
diff --git a/git-rebase.sh b/git-rebase.sh index 224cca98ee..c02be31f33 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -87,7 +87,7 @@ call_merge () { cmt="$(cat "$dotest/cmt.$1")" echo "$cmt" > "$dotest/current" hd=$(git rev-parse --verify HEAD) - cmt_name=$(git symbolic-ref HEAD) + 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))"' @@ -115,7 +115,24 @@ call_merge () { 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 () { + move_to_original_branch rm -r "$dotest" echo "All done." } @@ -173,16 +190,23 @@ do finish_rb_merge exit fi - git am -3 --skip --resolvemsg="$RESOLVEMSG" + 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 + move_to_original_branch rm -r "$dotest" elif test -d .dotest then + dotest=.dotest + move_to_original_branch rm -r .dotest else die "No rebase in progress?" @@ -318,6 +342,19 @@ then 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" @@ -327,14 +364,21 @@ git-reset --hard "$onto" if test "$mb" = "$branch" then echo >&2 "Fast-forwarded $branch_name to $onto_name." + 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" - exit $? + 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 @@ -343,8 +387,10 @@ fi 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" +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` |