{"thread":{"id":"10737","subject":"[PATCH] rebase: operate on a detached HEAD","startedAt":"2007-11-08T18:19:08Z","lastAt":"2007-11-08T18:28:55Z","messageCount":2,"participants":["Johannes Schindelin","Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"58922","messageId":"Pine.LNX.4.64.0711081818330.4362@racer.site","threadId":"10737","inReplyTo":null,"subject":"[PATCH] rebase: operate on a detached HEAD","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-11-08T18:19:08Z","receivedAt":"2007-11-08T18:19:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe interactive version of rebase does all the operations on a detached\nHEAD, so that after a successful rebase, <branch>@{1} is the pre-rebase\nstate.  The reflogs of \"HEAD\" still show all the actions in detail.\n\nThis teaches the non-interactive version to do the same.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n git-rebase.sh           |   56 ++++++++++++++++++++++++++++++++++++++++++----\n t/t3402-rebase-merge.sh |    7 +++++-\n 2 files changed, 57 insertions(+), 6 deletions(-)\n\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 8814be9..3684a31 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -88,7 +88,7 @@ call_merge () {\n \tcmt=\"$(cat \"$dotest/cmt.$1\")\"\n \techo \"$cmt\" > \"$dotest/current\"\n \thd=$(git rev-parse --verify HEAD)\n-\tcmt_name=$(git symbolic-ref HEAD)\n+\tcmt_name=$(git symbolic-ref HEAD 2> /dev/null || echo HEAD)\n \tmsgnum=$(cat \"$dotest/msgnum\")\n \tend=$(cat \"$dotest/end\")\n \teval GITHEAD_$cmt='\"${cmt_name##refs/heads/}~$(($end - $msgnum))\"'\n@@ -116,7 +116,24 @@ call_merge () {\n \tesac\n }\n \n+move_to_original_branch () {\n+\ttest -z \"$head_name\" &&\n+\t\thead_name=\"$(cat \"$dotest\"/head-name)\" &&\n+\t\tonto=\"$(cat \"$dotest\"/onto)\" &&\n+\t\torig_head=\"$(cat \"$dotest\"/orig-head)\"\n+\tcase \"$head_name\" in\n+\trefs/*)\n+\t\tmessage=\"rebase finished: $head_name onto $onto\"\n+\t\tgit update-ref -m \"$message\" \\\n+\t\t\t$head_name $(git rev-parse HEAD) $orig_head &&\n+\t\tgit symbolic-ref HEAD $head_name ||\n+\t\tdie \"Could not move back to $head_name\"\n+\t\t;;\n+\tesac\n+}\n+\n finish_rb_merge () {\n+\tmove_to_original_branch\n \trm -r \"$dotest\"\n \techo \"All done.\"\n }\n@@ -175,16 +192,23 @@ do\n \t\t\tfinish_rb_merge\n \t\t\texit\n \t\tfi\n-\t\tgit am -3 --skip --resolvemsg=\"$RESOLVEMSG\"\n+\t\thead_name=$(cat .dotest/head-name) &&\n+\t\tonto=$(cat .dotest/onto) &&\n+\t\torig_head=$(cat .dotest/orig-head) &&\n+\t\tgit am -3 --skip --resolvemsg=\"$RESOLVEMSG\" &&\n+\t\tmove_to_original_branch\n \t\texit\n \t\t;;\n \t--abort)\n \t\tgit rerere clear\n \t\tif test -d \"$dotest\"\n \t\tthen\n+\t\t\tmove_to_original_branch\n \t\t\trm -r \"$dotest\"\n \t\telif test -d .dotest\n \t\tthen\n+\t\t\tdotest=.dotest\n+\t\t\tmove_to_original_branch\n \t\t\trm -r .dotest\n \t\telse\n \t\t\tdie \"No rebase in progress?\"\n@@ -320,6 +344,19 @@ then\n \tGIT_PAGER='' git diff --stat --summary \"$mb\" \"$onto\"\n fi\n \n+# move to a detached HEAD\n+orig_head=$(git rev-parse HEAD^0)\n+head_name=$(git symbolic-ref HEAD 2> /dev/null)\n+case \"$head_name\" in\n+'')\n+\thead_name=\"detached HEAD\"\n+\t;;\n+*)\n+\tgit checkout \"$orig_head\" > /dev/null 2>&1 ||\n+\t\tdie \"could not detach HEAD\"\n+\t;;\n+esac\n+\n # Rewind the head to \"$onto\"; this saves our current head in ORIG_HEAD.\n echo \"First, rewinding head to replay your work on top of it...\"\n git-reset --hard \"$onto\"\n@@ -329,14 +366,21 @@ git-reset --hard \"$onto\"\n if test \"$mb\" = \"$branch\"\n then\n \techo >&2 \"Fast-forwarded $branch_name to $onto_name.\"\n+\tmove_to_original_branch\n \texit 0\n fi\n \n if test -z \"$do_merge\"\n then\n \tgit format-patch -k --stdout --full-index --ignore-if-in-upstream \"$upstream\"..ORIG_HEAD |\n-\tgit am $git_am_opt --binary -3 -k --resolvemsg=\"$RESOLVEMSG\"\n-\texit $?\n+\tgit am $git_am_opt --binary -3 -k --resolvemsg=\"$RESOLVEMSG\" &&\n+\tmove_to_original_branch\n+\tret=$?\n+\ttest 0 != $ret -a -d .dotest &&\n+\t\techo $head_name > .dotest/head-name &&\n+\t\techo $onto > .dotest/onto &&\n+\t\techo $orig_head > .dotest/orig-head\n+\texit $ret\n fi\n \n # start doing a rebase with git-merge\n@@ -345,8 +389,10 @@ fi\n mkdir -p \"$dotest\"\n echo \"$onto\" > \"$dotest/onto\"\n echo \"$onto_name\" > \"$dotest/onto_name\"\n-prev_head=`git rev-parse HEAD^0`\n+prev_head=$orig_head\n echo \"$prev_head\" > \"$dotest/prev_head\"\n+echo \"$orig_head\" > \"$dotest/orig-head\"\n+echo \"$head_name\" > \"$dotest/head-name\"\n \n msgnum=0\n for cmt in `git rev-list --reverse --no-merges \"$upstream\"..ORIG_HEAD`\ndiff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh\nindex 0779aaa..7b7d072 100755\n--- a/t/t3402-rebase-merge.sh\n+++ b/t/t3402-rebase-merge.sh\n@@ -48,9 +48,14 @@ test_expect_success 'reference merge' '\n \tgit merge -s recursive \"reference merge\" HEAD master\n '\n \n+PRE_REBASE=$(git rev-parse test-rebase)\n test_expect_success rebase '\n \tgit checkout test-rebase &&\n-\tgit rebase --merge master\n+\tGIT_TRACE=1 git rebase --merge master\n+'\n+\n+test_expect_success 'test-rebase@{1} is pre rebase' '\n+\ttest $PRE_REBASE = $(git rev-parse test-rebase@{1})\n '\n \n test_expect_success 'merge and rebase should match' '\n-- \n1.5.3.5.1634.g0fa78\n"},{"id":"58924","messageId":"alpine.LFD.0.9999.0711081328060.21255@xanadu.home","threadId":"10737","inReplyTo":"Pine.LNX.4.64.0711081818330.4362@racer.site","subject":"Re: [PATCH] rebase: operate on a detached HEAD","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-11-08T18:28:55Z","receivedAt":"2007-11-08T18:28:55Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Thu, 8 Nov 2007, Johannes Schindelin wrote:\n\n> \n> The interactive version of rebase does all the operations on a detached\n> HEAD, so that after a successful rebase, <branch>@{1} is the pre-rebase\n> state.  The reflogs of \"HEAD\" still show all the actions in detail.\n> \n> This teaches the non-interactive version to do the same.\n\nI like this.\n\n\nNicolas\n"}]}