git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] correctly calculate patches to rebase
@ 2012-07-18  7:27 Martin von Zweigbergk
  2012-07-18  7:27 ` [PATCH 1/7] git-rebase--am.sh: avoid special-casing --keep-empty Martin von Zweigbergk
  2012-07-18  7:32 ` [PATCH 0/7] correctly calculate patches to rebase Martin von Zweigbergk
  0 siblings, 2 replies; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk

These seven patches replace the broken one I sent in
http://thread.gmane.org/gmane.comp.version-control.git/200644/focus=200648. I
hope I got the handling of empty commits right this time.

Martin von Zweigbergk (7):
  git-rebase--am.sh: avoid special-casing --keep-empty
  git-rebase--interactive.sh: extract function for adding "pick" line
  git-rebase--interactive: group all $preserve_merges code
  git-rebase--interactive.sh: look up subject in add_pick_line
  rebase -p: use --cherry-mark for todo file
  rebase -p: don't request --left-right only to ignore left side
  rebase (without -p): correctly calculate patches to rebase

 git-am.sh                  | 10 +++++-
 git-rebase--am.sh          | 20 +++--------
 git-rebase--interactive.sh | 87 ++++++++++++++++++++--------------------------
 git-rebase--merge.sh       |  2 +-
 git-rebase.sh              | 11 +++---
 t/t3401-rebase-partial.sh  | 17 +++++++++
 t/t3406-rebase-message.sh  | 14 ++++----
 7 files changed, 81 insertions(+), 80 deletions(-)

-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] git-rebase--am.sh: avoid special-casing --keep-empty
  2012-07-18  7:27 [PATCH 0/7] correctly calculate patches to rebase Martin von Zweigbergk
@ 2012-07-18  7:27 ` Martin von Zweigbergk
  2012-07-18  7:27   ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Martin von Zweigbergk
  2012-07-18  7:32 ` [PATCH 0/7] correctly calculate patches to rebase Martin von Zweigbergk
  1 sibling, 1 reply; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk, Neil Horman

Since 0fbb95d (am: don't call mailinfo if $rebasing, 2012-06-26), the
patch body to apply when running 'git am --rebasing' is not taken from
the mbox, but directly from the commit. If such a commit is "empty",
'git am --rebasing' still happily applies it and commits. However,
since the input to 'git am --rebasing' only ever comes from 'git
format-patch', which completely leaves the commit out from its output
if it's empty, no empty commits are ever created by 'git am
--rebasing'. By teaching 'git am --rebasing' a --keep-empty option and
letting the caller decide whether or not to keep empty commits, we can
unify the two different mechanisms that git-rebase--am.sh uses for
rebasing.
---
 git-am.sh         | 10 +++++++++-
 git-rebase--am.sh | 20 ++++++--------------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/git-am.sh b/git-am.sh
index b6a5300..37641b7 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -37,7 +37,8 @@ abort           restore the original branch and abort the patching operation.
 committer-date-is-author-date    lie about committer date
 ignore-date     use current timestamp for author date
 rerere-autoupdate update the index with reused conflict resolution if possible
-rebasing*       (internal use for git-rebase)"
+rebasing*       (internal use for git-rebase)
+keep-empty*     (internal use for git-rebase)"
 
 . git-sh-setup
 . git-sh-i18n
@@ -375,6 +376,7 @@ git_apply_opt=
 committer_date_is_author_date=
 ignore_date=
 allow_rerere_autoupdate=
+keep_empty=
 
 if test "$(git config --bool --get am.keepcr)" = true
 then
@@ -414,6 +416,8 @@ do
 		abort=t ;;
 	--rebasing)
 		rebasing=t threeway=t ;;
+	--keep-empty)
+		keep_empty=t ;;
 	-d|--dotest)
 		die "$(gettext "-d option is no longer supported.  Do not use.")"
 		;;
@@ -669,6 +673,10 @@ do
 			echo "$commit" >"$dotest/original-commit"
 			get_author_ident_from_commit "$commit" >"$dotest/author-script"
 			git diff-tree --root --binary "$commit" >"$dotest/patch"
+			test -s "$dotest/patch" || test -n "$keep_empty" || {
+				go_next
+				continue
+			}
 		else
 			git mailinfo $keep $no_inbody_headers $scissors $utf8 "$dotest/msg" "$dotest/patch" \
 				<"$dotest/$msgnum" >"$dotest/info" ||
diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 392ebc9..37c1b23 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -17,20 +17,12 @@ skip)
 esac
 
 test -n "$rebase_root" && root_flag=--root
-
-if test -n "$keep_empty"
-then
-	# we have to do this the hard way.  git format-patch completely squashes
-	# empty commits and even if it didn't the format doesn't really lend
-	# itself well to recording empty patches.  fortunately, cherry-pick
-	# makes this easy
-	git cherry-pick --allow-empty "$revisions"
-else
-	git format-patch -k --stdout --full-index --ignore-if-in-upstream \
-		--src-prefix=a/ --dst-prefix=b/ \
-		--no-renames $root_flag "$revisions" |
-	git am $git_am_opt --rebasing --resolvemsg="$resolvemsg"
-fi && move_to_original_branch
+test -n "$keep_empty" && git_am_opt="$git_am_opt --keep-empty"
+git format-patch -k --stdout --full-index --ignore-if-in-upstream \
+	--src-prefix=a/ --dst-prefix=b/ \
+	--no-renames $root_flag "$revisions" |
+git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" &&
+move_to_original_branch
 
 ret=$?
 test 0 != $ret -a -d "$state_dir" && write_basic_state
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line
  2012-07-18  7:27 ` [PATCH 1/7] git-rebase--am.sh: avoid special-casing --keep-empty Martin von Zweigbergk
@ 2012-07-18  7:27   ` Martin von Zweigbergk
  2012-07-18  7:27     ` [PATCH 3/7] git-rebase--interactive: group all $preserve_merges code Martin von Zweigbergk
  2012-07-18 12:48     ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Neil Horman
  0 siblings, 2 replies; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk, Neil Horman

Extract the code that adds a possibly commented-out "pick" line to the
todo file. This lets us reuse it more easily later.
---
 git-rebase--interactive.sh | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index bef7bc0..fa722b6 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -828,23 +828,26 @@ else
 	revisions=$onto...$orig_head
 	shortrevisions=$shorthead
 fi
-git rev-list $merges_option --pretty=oneline --abbrev-commit \
-	--abbrev=7 --reverse --left-right --topo-order \
-	$revisions | \
-	sed -n "s/^>//p" |
-while read -r shortsha1 rest
-do
 
-	if test -z "$keep_empty" && is_empty_commit $shortsha1
+add_pick_line () {
+	if test -z "$keep_empty" && is_empty_commit $1
 	then
 		comment_out="# "
 	else
 		comment_out=
 	fi
+	printf '%s\n' "${comment_out}pick $1 $2" >>"$todo"
+}
 
+git rev-list $merges_option --pretty=oneline --abbrev-commit \
+	--abbrev=7 --reverse --left-right --topo-order \
+	$revisions | \
+	sed -n "s/^>//p" |
+while read -r shortsha1 rest
+do
 	if test t != "$preserve_merges"
 	then
-		printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
+		add_pick_line $shortsha1 "$rest"
 	else
 		sha1=$(git rev-parse $shortsha1)
 		if test -z "$rebase_root"
@@ -863,7 +866,7 @@ do
 		if test f = "$preserve"
 		then
 			touch "$rewritten"/$sha1
-			printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
+			add_pick_line $shortsha1 "$rest"
 		fi
 	fi
 done
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] git-rebase--interactive: group all $preserve_merges code
  2012-07-18  7:27   ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Martin von Zweigbergk
@ 2012-07-18  7:27     ` Martin von Zweigbergk
  2012-07-18  7:27       ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Martin von Zweigbergk
  2012-07-18 12:48     ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Neil Horman
  1 sibling, 1 reply; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk

The code in git-rebase--interactive that creates the todo file
contains if-blocks that depend on whether $preserve_merges is
active. There is only a very small amount of code in between that is
shared with non-merge-preserving code path, so remove the repeated
conditions and duplicate the small amount of shared code instead.
---
 git-rebase--interactive.sh | 69 ++++++++++++++++++++++------------------------
 1 file changed, 33 insertions(+), 36 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index fa722b6..4bb8e3f 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -793,28 +793,6 @@ mkdir "$state_dir" || die "Could not create temporary $state_dir"
 
 : > "$state_dir"/interactive || die "Could not mark as interactive"
 write_basic_state
-if test t = "$preserve_merges"
-then
-	if test -z "$rebase_root"
-	then
-		mkdir "$rewritten" &&
-		for c in $(git merge-base --all $orig_head $upstream)
-		do
-			echo $onto > "$rewritten"/$c ||
-				die "Could not init rewritten commits"
-		done
-	else
-		mkdir "$rewritten" &&
-		echo $onto > "$rewritten"/root ||
-			die "Could not init rewritten commits"
-	fi
-	# No cherry-pick because our first pass is to determine
-	# parents to rewrite and skipping dropped commits would
-	# prematurely end our probe
-	merges_option=
-else
-	merges_option="--no-merges --cherry-pick"
-fi
 
 shorthead=$(git rev-parse --short $orig_head)
 shortonto=$(git rev-parse --short $onto)
@@ -839,16 +817,30 @@ add_pick_line () {
 	printf '%s\n' "${comment_out}pick $1 $2" >>"$todo"
 }
 
-git rev-list $merges_option --pretty=oneline --abbrev-commit \
-	--abbrev=7 --reverse --left-right --topo-order \
-	$revisions | \
-	sed -n "s/^>//p" |
-while read -r shortsha1 rest
-do
-	if test t != "$preserve_merges"
+if test t = "$preserve_merges"
+then
+	if test -z "$rebase_root"
 	then
-		add_pick_line $shortsha1 "$rest"
+		mkdir "$rewritten" &&
+		for c in $(git merge-base --all $orig_head $upstream)
+		do
+			echo $onto > "$rewritten"/$c ||
+				die "Could not init rewritten commits"
+		done
 	else
+		mkdir "$rewritten" &&
+		echo $onto > "$rewritten"/root ||
+			die "Could not init rewritten commits"
+	fi
+	# No cherry-pick because our first pass is to determine
+	# parents to rewrite and skipping dropped commits would
+	# prematurely end our probe
+	git rev-list --pretty=oneline --abbrev-commit \
+		--abbrev=7 --reverse --left-right --topo-order \
+		$revisions |
+	sed -n "s/^>//p" |
+	while read -r shortsha1 rest
+	do
 		sha1=$(git rev-parse $shortsha1)
 		if test -z "$rebase_root"
 		then
@@ -868,12 +860,8 @@ do
 			touch "$rewritten"/$sha1
 			add_pick_line $shortsha1 "$rest"
 		fi
-	fi
-done
-
-# Watch for commits that been dropped by --cherry-pick
-if test t = "$preserve_merges"
-then
+	done
+	# Watch for commits that been dropped by --cherry-pick
 	mkdir "$dropped"
 	# Save all non-cherry-picked changes
 	git rev-list $revisions --left-right --cherry-pick | \
@@ -895,6 +883,15 @@ then
 			rm "$rewritten"/$rev
 		fi
 	done
+else
+	git rev-list --no-merges --cherry-pick --pretty=oneline --abbrev-commit \
+		--abbrev=7 --reverse --left-right --topo-order \
+		$revisions |
+	sed -n "s/^>//p" |
+	while read -r shortsha1 rest
+	do
+		add_pick_line $shortsha1 "$rest"
+	done
 fi
 
 test -s "$todo" || echo noop >> "$todo"
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line
  2012-07-18  7:27     ` [PATCH 3/7] git-rebase--interactive: group all $preserve_merges code Martin von Zweigbergk
@ 2012-07-18  7:27       ` Martin von Zweigbergk
  2012-07-18  7:27         ` [PATCH 5/7] rebase -p: use --cherry-mark for todo file Martin von Zweigbergk
  2012-07-20  8:14         ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Johannes Sixt
  0 siblings, 2 replies; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk

The todo file is generated using (more-or-less) 'git rev-list
$revisions --pretty=oneline --abbrev-commit --abbrev=7', i.e. by
letting 'git rev-list' output both the abbreviated sha1 and the
subject line. To allow us to more easily generate the list of commits
to rebase by using commands that don't support outputting the subject
line, move this logic into add_pick_line.
---
 git-rebase--interactive.sh | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 4bb8e3f..9715830 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -814,7 +814,8 @@ add_pick_line () {
 	else
 		comment_out=
 	fi
-	printf '%s\n' "${comment_out}pick $1 $2" >>"$todo"
+	line=$(git rev-list -1 --pretty=oneline --abbrev-commit --abbrev=7 $1)
+	printf '%s\n' "${comment_out}pick $line" >>"$todo"
 }
 
 if test t = "$preserve_merges"
@@ -835,13 +836,10 @@ then
 	# No cherry-pick because our first pass is to determine
 	# parents to rewrite and skipping dropped commits would
 	# prematurely end our probe
-	git rev-list --pretty=oneline --abbrev-commit \
-		--abbrev=7 --reverse --left-right --topo-order \
-		$revisions |
+	git rev-list $revisions --reverse --left-right --topo-order |
 	sed -n "s/^>//p" |
-	while read -r shortsha1 rest
+	while read -r sha1
 	do
-		sha1=$(git rev-parse $shortsha1)
 		if test -z "$rebase_root"
 		then
 			preserve=t
@@ -858,7 +856,7 @@ then
 		if test f = "$preserve"
 		then
 			touch "$rewritten"/$sha1
-			add_pick_line $shortsha1 "$rest"
+			add_pick_line $sha1
 		fi
 	done
 	# Watch for commits that been dropped by --cherry-pick
@@ -884,13 +882,12 @@ then
 		fi
 	done
 else
-	git rev-list --no-merges --cherry-pick --pretty=oneline --abbrev-commit \
-		--abbrev=7 --reverse --left-right --topo-order \
-		$revisions |
+	git rev-list $revisions --reverse --left-right --topo-order \
+		--no-merges --cherry-pick |
 	sed -n "s/^>//p" |
-	while read -r shortsha1 rest
+	while read -r sha1
 	do
-		add_pick_line $shortsha1 "$rest"
+		add_pick_line $sha1
 	done
 fi
 
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] rebase -p: use --cherry-mark for todo file
  2012-07-18  7:27       ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Martin von Zweigbergk
@ 2012-07-18  7:27         ` Martin von Zweigbergk
  2012-07-18  7:27           ` [PATCH 6/7] rebase -p: don't request --left-right only to ignore left side Martin von Zweigbergk
  2012-07-20  8:14         ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Johannes Sixt
  1 sibling, 1 reply; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk, Michael J Gruber

While building the todo file, 'rebase -p' needs to find the
cherry-picked commits in the branch that is about to be rebased. For
this, it calculates the set difference between the full set of commits
and the non-cherry-picked ones (as reported by 'git rev-list
--left-right --cherry-pick'). Now that have the 'git rev-list
--cherry-mark' option (since adbbb31 (revision.c: introduce
--cherry-mark, 2011-03-07)), we can instead use that option to get the
set of cherry-picked commits.
---
 git-rebase--interactive.sh | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 9715830..47beb58 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -859,17 +859,12 @@ then
 			add_pick_line $sha1
 		fi
 	done
-	# Watch for commits that been dropped by --cherry-pick
+	# Now drop cherry-picked commits
 	mkdir "$dropped"
-	# Save all non-cherry-picked changes
-	git rev-list $revisions --left-right --cherry-pick | \
-		sed -n "s/^>//p" > "$state_dir"/not-cherry-picks
-	# Now all commits and note which ones are missing in
-	# not-cherry-picks and hence being dropped
-	git rev-list $revisions |
+	git rev-list $revisions --cherry-mark --right-only | sed -ne "s/^=//p" |
 	while read rev
 	do
-		if test -f "$rewritten"/$rev -a "$(sane_grep "$rev" "$state_dir"/not-cherry-picks)" = ""
+		if test -f "$rewritten"/$rev
 		then
 			# Use -f2 because if rev-list is telling us this commit is
 			# not worthwhile, we don't want to track its multiple heads,
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] rebase -p: don't request --left-right only to ignore left side
  2012-07-18  7:27         ` [PATCH 5/7] rebase -p: use --cherry-mark for todo file Martin von Zweigbergk
@ 2012-07-18  7:27           ` Martin von Zweigbergk
  2012-07-18  7:27             ` [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase Martin von Zweigbergk
  0 siblings, 1 reply; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk, Michael J Gruber

While generating the todo file, rebase -p calls 'git rev-list
--left-right a...b' (with 'a' equal to $upstream or $onto and 'b'
equal to $orig_head) and its output is piped through 'sed -n
"s/^>//p"', making it equivalent to 'git rev-list --right-only
a...b'. Change the invocation to exactly that.

(One could alternatively change it to 'git rev-list a..b', which would
be even simpler, if it wasn't for the fact that we already have the
revision range expression in a variable.)
---
 git-rebase--interactive.sh | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 47beb58..cd5a2cc 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -836,8 +836,7 @@ then
 	# No cherry-pick because our first pass is to determine
 	# parents to rewrite and skipping dropped commits would
 	# prematurely end our probe
-	git rev-list $revisions --reverse --left-right --topo-order |
-	sed -n "s/^>//p" |
+	git rev-list $revisions --reverse --right-only --topo-order |
 	while read -r sha1
 	do
 		if test -z "$rebase_root"
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase
  2012-07-18  7:27           ` [PATCH 6/7] rebase -p: don't request --left-right only to ignore left side Martin von Zweigbergk
@ 2012-07-18  7:27             ` Martin von Zweigbergk
  2012-07-20  8:18               ` Johannes Sixt
  0 siblings, 1 reply; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:27 UTC (permalink / raw)
  To: git; +Cc: Martin von Zweigbergk, Knut Franke

The different types of rebase use different ways of calculating the
patches to rebase.

'git rebase' (without -m/-i/-p) uses

  git format-patch --ignore-if-in-upstream $upstream..$orig_head

'git rebase -m' uses

  git rev-list $upstream..$orig_head

'git rebase -i' (without -p) uses

  git rev-list $upstream...$orig_head --left-right --no-merges \
          --cherry-pick | sed -n "s/^>//p"

, which could also have been written

  git rev-list $upstream...$orig_head --right-only --no-merges \
          --cherry-pick

'git rebase -p' uses

  git rev-list $upstream...$orig_head --right-only

followed by cherry-picked commits found by

  git rev-list $upstream...$orig_head --cherry-mark --right-only |
  | sed -ne "s/^=//p"

As Knut Franke reported in [1], the fact that there is no
--ignore-if-in-upstream or equivalent when using merge-based rebase
means that unnecessary conflicts can arise due to commits
cherry-picked between $orig_head and $upstream.

With all the other types, there is a different problem with the method
of calculating the commits to rebase. Copying the example history from
[1]:

      .-c
     /
a---b---d---e---f
         \
          .-g---E

Commit E is here a cherry-pick of e. If we now run 'git rebase [-i|-p]
--onto c f E', the commits to rebase will be those on E that are not
equivalent to any of those in f, which in this case would be only
'g'. Commit 'E' would thus be lost.

To solve both of the above problems, we want to find the commits in
$upstream..$orig_head that are not cherry-picked in
$orig_head..$onto. There is unfortunately no direct way of finding
these commits using 'git rev-list', so we will have to resort to using
'git cherry' and filter for lines starting with '+'. This works for
all but 'rebase -p', since 'git cherry' ignores merges.

As a side-effect, we also avoid the cost of formatting patches.

Test case updates for 'rebase -m' by Knut, the rest by Martin.

 [1] http://thread.gmane.org/gmane.comp.version-control.git/161917

Helped-by: Knut Franke <Knut.Franke@gmx.de>
Signed-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>
---
 git-rebase--am.sh          |  6 ++----
 git-rebase--interactive.sh |  8 +++-----
 git-rebase--merge.sh       |  2 +-
 git-rebase.sh              | 11 ++++-------
 t/t3401-rebase-partial.sh  | 17 +++++++++++++++++
 t/t3406-rebase-message.sh  | 14 +++++++-------
 6 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 37c1b23..fe3fdd1 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -16,11 +16,9 @@ skip)
 	;;
 esac
 
-test -n "$rebase_root" && root_flag=--root
 test -n "$keep_empty" && git_am_opt="$git_am_opt --keep-empty"
-git format-patch -k --stdout --full-index --ignore-if-in-upstream \
-	--src-prefix=a/ --dst-prefix=b/ \
-	--no-renames $root_flag "$revisions" |
+generate_revisions |
+sed -e 's/\([0-9a-f]\{40\}\)/From \1 Mon Sep 17 00:00:00 2001/' |
 git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" &&
 move_to_original_branch
 
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index cd5a2cc..da32ca7 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -800,10 +800,8 @@ if test -z "$rebase_root"
 	# this is now equivalent to ! -z "$upstream"
 then
 	shortupstream=$(git rev-parse --short $upstream)
-	revisions=$upstream...$orig_head
 	shortrevisions=$shortupstream..$shorthead
 else
-	revisions=$onto...$orig_head
 	shortrevisions=$shorthead
 fi
 
@@ -822,6 +820,7 @@ if test t = "$preserve_merges"
 then
 	if test -z "$rebase_root"
 	then
+		revisions=$upstream...$orig_head
 		mkdir "$rewritten" &&
 		for c in $(git merge-base --all $orig_head $upstream)
 		do
@@ -829,6 +828,7 @@ then
 				die "Could not init rewritten commits"
 		done
 	else
+		revisions=$onto...$orig_head
 		mkdir "$rewritten" &&
 		echo $onto > "$rewritten"/root ||
 			die "Could not init rewritten commits"
@@ -876,9 +876,7 @@ then
 		fi
 	done
 else
-	git rev-list $revisions --reverse --left-right --topo-order \
-		--no-merges --cherry-pick |
-	sed -n "s/^>//p" |
+	generate_revisions |
 	while read -r sha1
 	do
 		add_pick_line $sha1
diff --git a/git-rebase--merge.sh b/git-rebase--merge.sh
index b10f2cf..bf4ec4b 100644
--- a/git-rebase--merge.sh
+++ b/git-rebase--merge.sh
@@ -131,7 +131,7 @@ echo "$onto_name" > "$state_dir/onto_name"
 write_basic_state
 
 msgnum=0
-for cmt in `git rev-list --reverse --no-merges "$revisions"`
+for cmt in $(generate_revisions)
 do
 	msgnum=$(($msgnum + 1))
 	echo "$cmt" > "$state_dir/cmt.$msgnum"
diff --git a/git-rebase.sh b/git-rebase.sh
index 1cd0633..0fdff87 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -530,6 +530,10 @@ then
 	GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
 fi
 
+generate_revisions () {
+	git cherry $onto $orig_head $upstream | sed -ne 's/^+ //p'
+}
+
 test "$type" = interactive && run_specific_rebase
 
 # Detach HEAD and reset the tree
@@ -546,11 +550,4 @@ then
 	exit 0
 fi
 
-if test -n "$rebase_root"
-then
-	revisions="$onto..$orig_head"
-else
-	revisions="$upstream..$orig_head"
-fi
-
 run_specific_rebase
diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh
index 7f8693b..9c5d815 100755
--- a/t/t3401-rebase-partial.sh
+++ b/t/t3401-rebase-partial.sh
@@ -50,4 +50,21 @@ test_expect_success 'rebase ignores empty commit' '
 	test $(git log --format=%s C..) = "D"
 '
 
+test_expect_success 'rebase --onto does not re-apply patches in $onto' '
+	git checkout C &&
+	test_commit C2 C.t &&
+	git checkout -B my-topic-branch master &&
+	test_commit E &&
+	git rebase --onto C2 A2 &&
+	test "$(git log --format=%s C2..)" = E
+'
+
+test_expect_success 'rebase --onto does not lose patches in $upstream' '
+	git rebase --onto A2 E &&
+	test "$(git log --format=%s A2..)" = "E
+C2
+C
+B"
+'
+
 test_done
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 6898377..3eecc66 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -5,8 +5,10 @@ test_description='messages from rebase operation'
 . ./test-lib.sh
 
 quick_one () {
-	echo "$1" >"file$1" &&
-	git add "file$1" &&
+	fileno=$2
+	test -z "$fileno" && fileno=$1
+	echo "$1" >"file$fileno" &&
+	git add "file$fileno" &&
 	test_tick &&
 	git commit -m "$1"
 }
@@ -16,21 +18,19 @@ test_expect_success setup '
 	git branch topic &&
 	quick_one X &&
 	quick_one A &&
-	quick_one B &&
+	quick_one B A &&
 	quick_one Y &&
 
 	git checkout topic &&
 	quick_one A &&
-	quick_one B &&
+	quick_one B A &&
 	quick_one Z &&
 	git tag start
 
 '
 
 cat >expect <<\EOF
-Already applied: 0001 A
-Already applied: 0002 B
-Committed: 0003 Z
+Committed: 0001 Z
 EOF
 
 test_expect_success 'rebase -m' '
-- 
1.7.11.1.104.ge7b44f1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] correctly calculate patches to rebase
  2012-07-18  7:27 [PATCH 0/7] correctly calculate patches to rebase Martin von Zweigbergk
  2012-07-18  7:27 ` [PATCH 1/7] git-rebase--am.sh: avoid special-casing --keep-empty Martin von Zweigbergk
@ 2012-07-18  7:32 ` Martin von Zweigbergk
  1 sibling, 0 replies; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-18  7:32 UTC (permalink / raw)
  To: git

Argh! Sorry about the sendemail.chainreplyto=true. I must have read
that warning message incorrectly :-(.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line
  2012-07-18  7:27   ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Martin von Zweigbergk
  2012-07-18  7:27     ` [PATCH 3/7] git-rebase--interactive: group all $preserve_merges code Martin von Zweigbergk
@ 2012-07-18 12:48     ` Neil Horman
  1 sibling, 0 replies; 15+ messages in thread
From: Neil Horman @ 2012-07-18 12:48 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: git

On Wed, Jul 18, 2012 at 12:27:30AM -0700, Martin von Zweigbergk wrote:
> Extract the code that adds a possibly commented-out "pick" line to the
> todo file. This lets us reuse it more easily later.
> ---
>  git-rebase--interactive.sh | 21 ++++++++++++---------
>  1 file changed, 12 insertions(+), 9 deletions(-)
> 
> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> index bef7bc0..fa722b6 100644
> --- a/git-rebase--interactive.sh
> +++ b/git-rebase--interactive.sh
> @@ -828,23 +828,26 @@ else
>  	revisions=$onto...$orig_head
>  	shortrevisions=$shorthead
>  fi
> -git rev-list $merges_option --pretty=oneline --abbrev-commit \
> -	--abbrev=7 --reverse --left-right --topo-order \
> -	$revisions | \
> -	sed -n "s/^>//p" |
> -while read -r shortsha1 rest
> -do
>  
> -	if test -z "$keep_empty" && is_empty_commit $shortsha1
> +add_pick_line () {
> +	if test -z "$keep_empty" && is_empty_commit $1
>  	then
>  		comment_out="# "
>  	else
>  		comment_out=
>  	fi
> +	printf '%s\n' "${comment_out}pick $1 $2" >>"$todo"
> +}
>  
> +git rev-list $merges_option --pretty=oneline --abbrev-commit \
> +	--abbrev=7 --reverse --left-right --topo-order \
> +	$revisions | \
> +	sed -n "s/^>//p" |
> +while read -r shortsha1 rest
> +do
>  	if test t != "$preserve_merges"
>  	then
> -		printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
> +		add_pick_line $shortsha1 "$rest"
>  	else
>  		sha1=$(git rev-parse $shortsha1)
>  		if test -z "$rebase_root"
> @@ -863,7 +866,7 @@ do
>  		if test f = "$preserve"
>  		then
>  			touch "$rewritten"/$sha1
> -			printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
> +			add_pick_line $shortsha1 "$rest"
>  		fi
>  	fi
>  done
> -- 
> 1.7.11.1.104.ge7b44f1
> 
> 

Thanks!
Acked-by: Neil Horman <nhorman@tuxdriver.com>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line
  2012-07-18  7:27       ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Martin von Zweigbergk
  2012-07-18  7:27         ` [PATCH 5/7] rebase -p: use --cherry-mark for todo file Martin von Zweigbergk
@ 2012-07-20  8:14         ` Johannes Sixt
  2012-07-20 15:47           ` Martin von Zweigbergk
  1 sibling, 1 reply; 15+ messages in thread
From: Johannes Sixt @ 2012-07-20  8:14 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: git

Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:
> @@ -814,7 +814,8 @@ add_pick_line () {
>  	else
>  		comment_out=
>  	fi
> -	printf '%s\n' "${comment_out}pick $1 $2" >>"$todo"
> +	line=$(git rev-list -1 --pretty=oneline --abbrev-commit --abbrev=7 $1)
> +	printf '%s\n' "${comment_out}pick $line" >>"$todo"

I don't like this. On Windows, rebase -i is already slow, and these extra
processes will make it even slower.

> +	git rev-list $revisions --reverse --left-right --topo-order |
>  	sed -n "s/^>//p" |
> -	while read -r shortsha1 rest
> +	while read -r sha1
>  	do
> -		sha1=$(git rev-parse $shortsha1)
>  		if test -z "$rebase_root"
...
> -			add_pick_line $shortsha1 "$rest"
> +			add_pick_line $sha1
>  		fi

This is 'rebase -p' case, and you trade the new processes for some old ones.

> +	git rev-list $revisions --reverse --left-right --topo-order \
> +		--no-merges --cherry-pick |
>  	sed -n "s/^>//p" |
> -	while read -r shortsha1 rest
> +	while read -r sha1
>  	do
> -		add_pick_line $shortsha1 "$rest"
> +		add_pick_line $sha1
>  	done

But in the regulare case, you don't; the processes are really new.

Anything that can be done about this? Perhaps the rev-list call can
generate all of the full SHA1, the short SHA1, and the subject with a
--pretty format?

-- Hannes

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase
  2012-07-18  7:27             ` [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase Martin von Zweigbergk
@ 2012-07-20  8:18               ` Johannes Sixt
  2012-07-20 15:58                 ` Martin von Zweigbergk
  0 siblings, 1 reply; 15+ messages in thread
From: Johannes Sixt @ 2012-07-20  8:18 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: git, Knut Franke

Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:
> diff --git a/git-rebase--am.sh b/git-rebase--am.sh
> index 37c1b23..fe3fdd1 100644
> --- a/git-rebase--am.sh
> +++ b/git-rebase--am.sh
> @@ -16,11 +16,9 @@ skip)
>  	;;
>  esac
>  
> -test -n "$rebase_root" && root_flag=--root
>  test -n "$keep_empty" && git_am_opt="$git_am_opt --keep-empty"
> -git format-patch -k --stdout --full-index --ignore-if-in-upstream \
> -	--src-prefix=a/ --dst-prefix=b/ \
> -	--no-renames $root_flag "$revisions" |
> +generate_revisions |
> +sed -e 's/\([0-9a-f]\{40\}\)/From \1 Mon Sep 17 00:00:00 2001/' |
>  git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" &&
>  move_to_original_branch

Just curious (as all tests pass): What does this do? It looks like
format-patch is not called anymore and git-am sees only SHA1s. Does it
force git-am to cherry-pick the patches?

-- Hannes

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line
  2012-07-20  8:14         ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Johannes Sixt
@ 2012-07-20 15:47           ` Martin von Zweigbergk
  2012-07-22 20:51             ` Junio C Hamano
  0 siblings, 1 reply; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-20 15:47 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Git, Michael J Gruber

Thanks for reviewing.

On Fri, Jul 20, 2012 at 1:14 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:
>> @@ -814,7 +814,8 @@ add_pick_line () {
>>       else
>>               comment_out=
>>       fi
>> -     printf '%s\n' "${comment_out}pick $1 $2" >>"$todo"
>> +     line=$(git rev-list -1 --pretty=oneline --abbrev-commit --abbrev=7 $1)
>> +     printf '%s\n' "${comment_out}pick $line" >>"$todo"
>
> I don't like this. On Windows, rebase -i is already slow, and these extra
> processes will make it even slower.

I don't like it either :-(.

> Anything that can be done about this? Perhaps the rev-list call can
> generate all of the full SHA1, the short SHA1, and the subject with a
> --pretty format?

After patch 7/7, cherry is used instead of rev-list. Ideally, I would
have liked to teach "git rev-list --cherry-pick" to somehow use a
<limit> just like cherry does, but I couldn't think of a generic way
of doing that (in this case, we want to say something like "range
a..b, but drop commits that are equivalent to any in b..c"). I
actually don't remember if I gave up because I couldn't think of a
sensible way of specifying ranges like that, or if I just ran out of
time (not familiar with the revision-walking code). Now it seems to me
that something like "git rev-list a..b --not-cherry-picks b..c" makes
sense, but maybe it's just too specific and we should just support the
limited (no pun intended) case we need to emulate "git cherry", i.e.
something like "git rev-list --cherry-with-limit=a c...b". Feedback
appreciated.

Martin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase
  2012-07-20  8:18               ` Johannes Sixt
@ 2012-07-20 15:58                 ` Martin von Zweigbergk
  0 siblings, 0 replies; 15+ messages in thread
From: Martin von Zweigbergk @ 2012-07-20 15:58 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, Knut Franke

On Fri, Jul 20, 2012 at 1:18 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:
> Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:
>> diff --git a/git-rebase--am.sh b/git-rebase--am.sh
>> index 37c1b23..fe3fdd1 100644
>> --- a/git-rebase--am.sh
>> +++ b/git-rebase--am.sh
>> @@ -16,11 +16,9 @@ skip)
>>       ;;
>>  esac
>>
>> -test -n "$rebase_root" && root_flag=--root
>>  test -n "$keep_empty" && git_am_opt="$git_am_opt --keep-empty"
>> -git format-patch -k --stdout --full-index --ignore-if-in-upstream \
>> -     --src-prefix=a/ --dst-prefix=b/ \
>> -     --no-renames $root_flag "$revisions" |
>> +generate_revisions |
>> +sed -e 's/\([0-9a-f]\{40\}\)/From \1 Mon Sep 17 00:00:00 2001/' |
>>  git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" &&
>>  move_to_original_branch
>
> Just curious (as all tests pass): What does this do? It looks like
> format-patch is not called anymore and git-am sees only SHA1s. Does it
> force git-am to cherry-pick the patches?

That probably deserves to be mentioned in the commit message. Or maybe
in as a comment in the code. Either way, since 0fbb95d (am: don't call
mailinfo if $rebasing, 2012-06-26), 'git am --rebasing' never looks at
anything but the sha1, so most of the output from 'git format-patch'
is currently ignored. It doesn't do cherry-pick, though, but runs 'git
diff-tree' and other commands and then feeds the result to 'git
apply', just like a regular 'git am' invocation would.

Martin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line
  2012-07-20 15:47           ` Martin von Zweigbergk
@ 2012-07-22 20:51             ` Junio C Hamano
  0 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2012-07-22 20:51 UTC (permalink / raw)
  To: Martin von Zweigbergk; +Cc: Johannes Sixt, Git, Michael J Gruber

Martin von Zweigbergk <martin.von.zweigbergk@gmail.com> writes:

> After patch 7/7, cherry is used instead of rev-list. Ideally, I would
> have liked to teach "git rev-list --cherry-pick" to somehow use a
> <limit> just like cherry does, but I couldn't think of a generic way
> of doing that (in this case, we want to say something like "range
> a..b, but drop commits that are equivalent to any in b..c"). I
> actually don't remember if I gave up because I couldn't think of a
> sensible way of specifying ranges like that, or if I just ran out of
> time (not familiar with the revision-walking code).

Why not use patch-id output instead, then?  Grab patch-id for
commits b..c to make a mapping from patch-id to commits, do the same
for a..b and use the mapping to filter?

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2012-07-22 20:51 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-18  7:27 [PATCH 0/7] correctly calculate patches to rebase Martin von Zweigbergk
2012-07-18  7:27 ` [PATCH 1/7] git-rebase--am.sh: avoid special-casing --keep-empty Martin von Zweigbergk
2012-07-18  7:27   ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Martin von Zweigbergk
2012-07-18  7:27     ` [PATCH 3/7] git-rebase--interactive: group all $preserve_merges code Martin von Zweigbergk
2012-07-18  7:27       ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Martin von Zweigbergk
2012-07-18  7:27         ` [PATCH 5/7] rebase -p: use --cherry-mark for todo file Martin von Zweigbergk
2012-07-18  7:27           ` [PATCH 6/7] rebase -p: don't request --left-right only to ignore left side Martin von Zweigbergk
2012-07-18  7:27             ` [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase Martin von Zweigbergk
2012-07-20  8:18               ` Johannes Sixt
2012-07-20 15:58                 ` Martin von Zweigbergk
2012-07-20  8:14         ` [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line Johannes Sixt
2012-07-20 15:47           ` Martin von Zweigbergk
2012-07-22 20:51             ` Junio C Hamano
2012-07-18 12:48     ` [PATCH 2/7] git-rebase--interactive.sh: extract function for adding "pick" line Neil Horman
2012-07-18  7:32 ` [PATCH 0/7] correctly calculate patches to rebase Martin von Zweigbergk

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).