Subject: [PATCH RFC] rebase: add --revisions flag

From: "Michael S. Tsirkin" <[email-masked]>
Date: Tue, 8 Dec 2009 16:47:42 +0200

Add --revisions flag to rebase, so that it can be used
to apply an arbitrary range of commits on top
of a current branch.

Signed-off-by: Michael S. Tsirkin <[email-masked]>
---

I've been wishing for this functionality for a while now,
so here goes. This isn't yet properly documented and I didn't
write a test, but the patch seems to work fine for me.
Any early flames/feedback?

 git-rebase.sh |   36 ++++++++++++++++++++++++------------
 1 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/git-rebase.sh b/git-rebase.sh
index b121f45..d99d04b 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -3,12 +3,13 @@
 # Copyright (c) 2005 Junio C Hamano.
 #
 
-USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]'
+USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [--revisions <revision range>] [<upstream>|--root] [<branch>] [--quiet | -q]'
 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
 same name.  When the --onto option is provided the new branch starts
 out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
 It then attempts to create a new commit for each commit from the original
-<branch> that does not exist in the <upstream> branch.
+<branch> that does not exist in the <upstream> branch, or for
+each commit matching <revision range> when the --revisions options is provided.
 
 It is possible that a merge failure will prevent this process from being
 completely automatic.  You will have to resolve any such merge failure
@@ -41,6 +42,7 @@ If you would prefer to skip this patch, instead run \"git rebase --skip\".
 To restore the original branch and stop rebasing run \"git rebase --abort\".
 "
 unset newbase
+unset revisions
 strategy=recursive
 do_merge=
 dotest="$GIT_DIR"/rebase-merge
@@ -291,6 +293,11 @@ do
 		newbase="$2"
 		shift
 		;;
+	--revisions)
+		test 2 -le "$#" || usage
+		revisions="$2"
+		shift
+		;;
 	-M|-m|--m|--me|--mer|--merg|--merge)
 		do_merge=t
 		;;
@@ -459,12 +466,24 @@ case "$#" in
 esac
 orig_head=$branch
 
+if test -z "$revisions"
+then
+	if test -n "$rebase_root"
+	then
+		revisions="$onto..$orig_head"
+	else
+		revisions="$upstream..$orig_head"
+	fi
+	mb=$(git merge-base "$onto" "$branch")
+else
+	mb=""
+fi
+
 # Now we are rebasing commits $upstream..$branch (or with --root,
 # everything leading up to $branch) on top of $onto
 
 # Check if we are already based on $onto with linear history,
 # but this should be done only when upstream and onto are the same.
-mb=$(git merge-base "$onto" "$branch")
 if test "$upstream" = "$onto" && test "$mb" = "$onto" &&
 	# linear history?
 	! (git rev-list --parents "$onto".."$branch" | sane_grep " .* ") > /dev/null
@@ -489,10 +508,10 @@ if test -n "$diffstat"
 then
 	if test -n "$verbose"
 	then
-		echo "Changes from $mb to $onto:"
+		echo "Changes $revisions:"
 	fi
 	# We want color (if set), but no pager
-	GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+	GIT_PAGER='' git diff --stat --summary "$revisions"
 fi
 
 # If the $onto is a proper descendant of the tip of the branch, then
@@ -504,13 +523,6 @@ then
 	exit 0
 fi
 
-if test -n "$rebase_root"
-then
-	revisions="$onto..$orig_head"
-else
-	revisions="$upstream..$orig_head"
-fi
-
 if test -z "$do_merge"
 then
 	git format-patch -k --stdout --full-index --ignore-if-in-upstream \
-- 
1.6.6.rc1.43.gf55cc