git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: Johannes Sixt <j.sixt@viscovery.net>,
	Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
Subject: [PATCH] rebase [--onto O] A B: omit needless checkout
Date: Sat, 15 Mar 2008 13:42:11 -0700	[thread overview]
Message-ID: <7vk5k3n2ho.fsf_-_@gitster.siamese.dyndns.org> (raw)
In-Reply-To: <20080315103954.GD14769@ins.uni-bonn.de> (Ralf Wildenhues's message of "Sat, 15 Mar 2008 11:39:55 +0100")

This teaches "git rebase [--onto O] A B" to omit an unnecessary checkout
of branch B before it goes on.

"git-rebase" originally was about rebasing the current branch to somewhere
else, and when the extra parameter to name which branch to rebase was
added, it defined the semantics to the safest but stupid "first switch to
the named branch and then operate exactly the same way as if we were
already on that branch".

But the first thing the real part of "rebase" does is to reset the work
tree and the index to the "onto" commit.  Which means the "rebase that
branch" form switched the work tree to the tip of the branch only to
immediately switch again to another commit.  This was wasteful.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * Almost untested as I do not use this form very often.  Feedback would
   be good.

 git-rebase.sh |   51 +++++++++++++++++++++++++++++++--------------------
 1 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/git-rebase.sh b/git-rebase.sh
index ff66af3..9273852 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -309,22 +309,41 @@ then
 	}
 fi
 
-# If the branch to rebase is given, first switch to it.
+# If the branch to rebase is given, that is the branch we will rebase
+# $branch_name -- branch being rebased, or HEAD (already detached)
+# $orig_head -- commit object name of tip of the branch before rebasing
+# $head_name -- refs/heads/<that-branch> or "detached HEAD"
+switch_to=
 case "$#" in
 2)
+	# Is it "rebase other $branchname" or "rebase other $commit"?
 	branch_name="$2"
-	git-checkout "$2" || usage
+	switch_to="$2"
+
+	if branch=$(git rev-parse --verify "refs/heads/$2" 2>/dev/null)
+	then
+		head_name="refs/heads/$2"
+	elif branch=$(git rev-parse --verify "$2" 2>/dev/null)
+	then
+		head_name="detached HEAD"
+	else
+		usage
+	fi
 	;;
 *)
+	# Do not need to switch branches, we are already on it.
 	if branch_name=`git symbolic-ref -q HEAD`
 	then
+		head_name=$branch_name
 		branch_name=`expr "z$branch_name" : 'zrefs/heads/\(.*\)'`
 	else
+		head_name="detached HEAD"
 		branch_name=HEAD ;# detached
 	fi
+	branch=$(git rev-parse --verify "${branch_name}^0") || exit
 	;;
 esac
-branch=$(git rev-parse --verify "${branch_name}^0") || exit
+orig_head=$branch
 
 # Now we are rebasing commits $upstream..$branch on top of $onto
 
@@ -335,6 +354,8 @@ if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
 	# linear history?
 	! git rev-list --parents "$onto".."$branch" | grep " .* " > /dev/null
 then
+	# Lazily switch to the target branch if needed...
+	test -z "$switch_to" || git checkout "$switch_to"
 	echo >&2 "Current branch $branch_name is up to date."
 	exit 0
 fi
@@ -346,22 +367,11 @@ 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.
+# Detach HEAD and reset the tree
 echo "First, rewinding head to replay your work on top of it..."
-git-reset --hard "$onto"
+git checkout "$onto^0" >/dev/null 2>&1 ||
+	die "could not detach HEAD"
+# git reset --hard "$onto^0"
 
 # If the $onto is a proper descendant of the tip of the branch, then
 # we just fast forwarded.
@@ -374,7 +384,8 @@ fi
 
 if test -z "$do_merge"
 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 --rebasing --resolvemsg="$RESOLVEMSG" &&
 	move_to_original_branch
 	ret=$?
@@ -397,7 +408,7 @@ 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`
+for cmt in `git rev-list --reverse --no-merges "$upstream..$orig_head"`
 do
 	msgnum=$(($msgnum + 1))
 	echo "$cmt" > "$dotest/cmt.$msgnum"
-- 
1.5.4.4.718.ga6ccf

  reply	other threads:[~2008-03-15 20:43 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-12 19:10 optimized checkout+rebase? Ralf Wildenhues
2008-03-13  7:20 ` Johannes Sixt
2008-03-15 10:39   ` Ralf Wildenhues
2008-03-15 20:42     ` Junio C Hamano [this message]
2008-03-15 22:21       ` [PATCH] rebase [--onto O] A B: omit needless checkout Ralf Wildenhues
2008-03-16  3:56         ` Junio C Hamano
2008-03-19 12:54       ` Johannes Sixt
2008-03-19 19:19         ` Junio C Hamano
2008-03-20  7:41           ` Johannes Sixt
2008-03-20  7:53             ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7vk5k3n2ho.fsf_-_@gitster.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=Ralf.Wildenhues@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=j.sixt@viscovery.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).