{"thread":{"id":"31048","subject":"[PATCH 3/7] git-rebase--interactive: group all $preserve_merges code","startedAt":"2012-07-18T07:27:28Z","lastAt":"2012-07-22T20:51:31Z","messageCount":15,"participants":["Martin von Zweigbergk","Neil Horman","Johannes Sixt","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"195260","messageId":"1342596455-17046-1-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":null,"subject":"[PATCH 0/7] correctly calculate patches to rebase","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:28Z","receivedAt":"2012-07-18T07:27:28Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"These seven patches replace the broken one I sent in\nhttp://thread.gmane.org/gmane.comp.version-control.git/200644/focus=200648. I\nhope I got the handling of empty commits right this time.\n\nMartin von Zweigbergk (7):\n  git-rebase--am.sh: avoid special-casing --keep-empty\n  git-rebase--interactive.sh: extract function for adding \"pick\" line\n  git-rebase--interactive: group all $preserve_merges code\n  git-rebase--interactive.sh: look up subject in add_pick_line\n  rebase -p: use --cherry-mark for todo file\n  rebase -p: don't request --left-right only to ignore left side\n  rebase (without -p): correctly calculate patches to rebase\n\n git-am.sh                  | 10 +++++-\n git-rebase--am.sh          | 20 +++--------\n git-rebase--interactive.sh | 87 ++++++++++++++++++++--------------------------\n git-rebase--merge.sh       |  2 +-\n git-rebase.sh              | 11 +++---\n t/t3401-rebase-partial.sh  | 17 +++++++++\n t/t3406-rebase-message.sh  | 14 ++++----\n 7 files changed, 81 insertions(+), 80 deletions(-)\n\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195264","messageId":"1342596455-17046-2-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-1-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 1/7] git-rebase--am.sh: avoid special-casing --keep-empty","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:29Z","receivedAt":"2012-07-18T07:27:29Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"Since 0fbb95d (am: don't call mailinfo if $rebasing, 2012-06-26), the\npatch body to apply when running 'git am --rebasing' is not taken from\nthe mbox, but directly from the commit. If such a commit is \"empty\",\n'git am --rebasing' still happily applies it and commits. However,\nsince the input to 'git am --rebasing' only ever comes from 'git\nformat-patch', which completely leaves the commit out from its output\nif it's empty, no empty commits are ever created by 'git am\n--rebasing'. By teaching 'git am --rebasing' a --keep-empty option and\nletting the caller decide whether or not to keep empty commits, we can\nunify the two different mechanisms that git-rebase--am.sh uses for\nrebasing.\n---\n git-am.sh         | 10 +++++++++-\n git-rebase--am.sh | 20 ++++++--------------\n 2 files changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/git-am.sh b/git-am.sh\nindex b6a5300..37641b7 100755\n--- a/git-am.sh\n+++ b/git-am.sh\n@@ -37,7 +37,8 @@ abort           restore the original branch and abort the patching operation.\n committer-date-is-author-date    lie about committer date\n ignore-date     use current timestamp for author date\n rerere-autoupdate update the index with reused conflict resolution if possible\n-rebasing*       (internal use for git-rebase)\"\n+rebasing*       (internal use for git-rebase)\n+keep-empty*     (internal use for git-rebase)\"\n \n . git-sh-setup\n . git-sh-i18n\n@@ -375,6 +376,7 @@ git_apply_opt=\n committer_date_is_author_date=\n ignore_date=\n allow_rerere_autoupdate=\n+keep_empty=\n \n if test \"$(git config --bool --get am.keepcr)\" = true\n then\n@@ -414,6 +416,8 @@ do\n \t\tabort=t ;;\n \t--rebasing)\n \t\trebasing=t threeway=t ;;\n+\t--keep-empty)\n+\t\tkeep_empty=t ;;\n \t-d|--dotest)\n \t\tdie \"$(gettext \"-d option is no longer supported.  Do not use.\")\"\n \t\t;;\n@@ -669,6 +673,10 @@ do\n \t\t\techo \"$commit\" >\"$dotest/original-commit\"\n \t\t\tget_author_ident_from_commit \"$commit\" >\"$dotest/author-script\"\n \t\t\tgit diff-tree --root --binary \"$commit\" >\"$dotest/patch\"\n+\t\t\ttest -s \"$dotest/patch\" || test -n \"$keep_empty\" || {\n+\t\t\t\tgo_next\n+\t\t\t\tcontinue\n+\t\t\t}\n \t\telse\n \t\t\tgit mailinfo $keep $no_inbody_headers $scissors $utf8 \"$dotest/msg\" \"$dotest/patch\" \\\n \t\t\t\t<\"$dotest/$msgnum\" >\"$dotest/info\" ||\ndiff --git a/git-rebase--am.sh b/git-rebase--am.sh\nindex 392ebc9..37c1b23 100644\n--- a/git-rebase--am.sh\n+++ b/git-rebase--am.sh\n@@ -17,20 +17,12 @@ skip)\n esac\n \n test -n \"$rebase_root\" && root_flag=--root\n-\n-if test -n \"$keep_empty\"\n-then\n-\t# we have to do this the hard way.  git format-patch completely squashes\n-\t# empty commits and even if it didn't the format doesn't really lend\n-\t# itself well to recording empty patches.  fortunately, cherry-pick\n-\t# makes this easy\n-\tgit cherry-pick --allow-empty \"$revisions\"\n-else\n-\tgit format-patch -k --stdout --full-index --ignore-if-in-upstream \\\n-\t\t--src-prefix=a/ --dst-prefix=b/ \\\n-\t\t--no-renames $root_flag \"$revisions\" |\n-\tgit am $git_am_opt --rebasing --resolvemsg=\"$resolvemsg\"\n-fi && move_to_original_branch\n+test -n \"$keep_empty\" && git_am_opt=\"$git_am_opt --keep-empty\"\n+git format-patch -k --stdout --full-index --ignore-if-in-upstream \\\n+\t--src-prefix=a/ --dst-prefix=b/ \\\n+\t--no-renames $root_flag \"$revisions\" |\n+git am $git_am_opt --rebasing --resolvemsg=\"$resolvemsg\" &&\n+move_to_original_branch\n \n ret=$?\n test 0 != $ret -a -d \"$state_dir\" && write_basic_state\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195256","messageId":"1342596455-17046-3-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-2-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 2/7] git-rebase--interactive.sh: extract function for adding \"pick\" line","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:30Z","receivedAt":"2012-07-18T07:27:30Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"Extract the code that adds a possibly commented-out \"pick\" line to the\ntodo file. This lets us reuse it more easily later.\n---\n git-rebase--interactive.sh | 21 ++++++++++++---------\n 1 file changed, 12 insertions(+), 9 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex bef7bc0..fa722b6 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -828,23 +828,26 @@ else\n \trevisions=$onto...$orig_head\n \tshortrevisions=$shorthead\n fi\n-git rev-list $merges_option --pretty=oneline --abbrev-commit \\\n-\t--abbrev=7 --reverse --left-right --topo-order \\\n-\t$revisions | \\\n-\tsed -n \"s/^>//p\" |\n-while read -r shortsha1 rest\n-do\n \n-\tif test -z \"$keep_empty\" && is_empty_commit $shortsha1\n+add_pick_line () {\n+\tif test -z \"$keep_empty\" && is_empty_commit $1\n \tthen\n \t\tcomment_out=\"# \"\n \telse\n \t\tcomment_out=\n \tfi\n+\tprintf '%s\\n' \"${comment_out}pick $1 $2\" >>\"$todo\"\n+}\n \n+git rev-list $merges_option --pretty=oneline --abbrev-commit \\\n+\t--abbrev=7 --reverse --left-right --topo-order \\\n+\t$revisions | \\\n+\tsed -n \"s/^>//p\" |\n+while read -r shortsha1 rest\n+do\n \tif test t != \"$preserve_merges\"\n \tthen\n-\t\tprintf '%s\\n' \"${comment_out}pick $shortsha1 $rest\" >>\"$todo\"\n+\t\tadd_pick_line $shortsha1 \"$rest\"\n \telse\n \t\tsha1=$(git rev-parse $shortsha1)\n \t\tif test -z \"$rebase_root\"\n@@ -863,7 +866,7 @@ do\n \t\tif test f = \"$preserve\"\n \t\tthen\n \t\t\ttouch \"$rewritten\"/$sha1\n-\t\t\tprintf '%s\\n' \"${comment_out}pick $shortsha1 $rest\" >>\"$todo\"\n+\t\t\tadd_pick_line $shortsha1 \"$rest\"\n \t\tfi\n \tfi\n done\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195255","messageId":"1342596455-17046-4-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-3-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 3/7] git-rebase--interactive: group all $preserve_merges code","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:31Z","receivedAt":"2012-07-18T07:27:31Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"The code in git-rebase--interactive that creates the todo file\ncontains if-blocks that depend on whether $preserve_merges is\nactive. There is only a very small amount of code in between that is\nshared with non-merge-preserving code path, so remove the repeated\nconditions and duplicate the small amount of shared code instead.\n---\n git-rebase--interactive.sh | 69 ++++++++++++++++++++++------------------------\n 1 file changed, 33 insertions(+), 36 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex fa722b6..4bb8e3f 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -793,28 +793,6 @@ mkdir \"$state_dir\" || die \"Could not create temporary $state_dir\"\n \n : > \"$state_dir\"/interactive || die \"Could not mark as interactive\"\n write_basic_state\n-if test t = \"$preserve_merges\"\n-then\n-\tif test -z \"$rebase_root\"\n-\tthen\n-\t\tmkdir \"$rewritten\" &&\n-\t\tfor c in $(git merge-base --all $orig_head $upstream)\n-\t\tdo\n-\t\t\techo $onto > \"$rewritten\"/$c ||\n-\t\t\t\tdie \"Could not init rewritten commits\"\n-\t\tdone\n-\telse\n-\t\tmkdir \"$rewritten\" &&\n-\t\techo $onto > \"$rewritten\"/root ||\n-\t\t\tdie \"Could not init rewritten commits\"\n-\tfi\n-\t# No cherry-pick because our first pass is to determine\n-\t# parents to rewrite and skipping dropped commits would\n-\t# prematurely end our probe\n-\tmerges_option=\n-else\n-\tmerges_option=\"--no-merges --cherry-pick\"\n-fi\n \n shorthead=$(git rev-parse --short $orig_head)\n shortonto=$(git rev-parse --short $onto)\n@@ -839,16 +817,30 @@ add_pick_line () {\n \tprintf '%s\\n' \"${comment_out}pick $1 $2\" >>\"$todo\"\n }\n \n-git rev-list $merges_option --pretty=oneline --abbrev-commit \\\n-\t--abbrev=7 --reverse --left-right --topo-order \\\n-\t$revisions | \\\n-\tsed -n \"s/^>//p\" |\n-while read -r shortsha1 rest\n-do\n-\tif test t != \"$preserve_merges\"\n+if test t = \"$preserve_merges\"\n+then\n+\tif test -z \"$rebase_root\"\n \tthen\n-\t\tadd_pick_line $shortsha1 \"$rest\"\n+\t\tmkdir \"$rewritten\" &&\n+\t\tfor c in $(git merge-base --all $orig_head $upstream)\n+\t\tdo\n+\t\t\techo $onto > \"$rewritten\"/$c ||\n+\t\t\t\tdie \"Could not init rewritten commits\"\n+\t\tdone\n \telse\n+\t\tmkdir \"$rewritten\" &&\n+\t\techo $onto > \"$rewritten\"/root ||\n+\t\t\tdie \"Could not init rewritten commits\"\n+\tfi\n+\t# No cherry-pick because our first pass is to determine\n+\t# parents to rewrite and skipping dropped commits would\n+\t# prematurely end our probe\n+\tgit rev-list --pretty=oneline --abbrev-commit \\\n+\t\t--abbrev=7 --reverse --left-right --topo-order \\\n+\t\t$revisions |\n+\tsed -n \"s/^>//p\" |\n+\twhile read -r shortsha1 rest\n+\tdo\n \t\tsha1=$(git rev-parse $shortsha1)\n \t\tif test -z \"$rebase_root\"\n \t\tthen\n@@ -868,12 +860,8 @@ do\n \t\t\ttouch \"$rewritten\"/$sha1\n \t\t\tadd_pick_line $shortsha1 \"$rest\"\n \t\tfi\n-\tfi\n-done\n-\n-# Watch for commits that been dropped by --cherry-pick\n-if test t = \"$preserve_merges\"\n-then\n+\tdone\n+\t# Watch for commits that been dropped by --cherry-pick\n \tmkdir \"$dropped\"\n \t# Save all non-cherry-picked changes\n \tgit rev-list $revisions --left-right --cherry-pick | \\\n@@ -895,6 +883,15 @@ then\n \t\t\trm \"$rewritten\"/$rev\n \t\tfi\n \tdone\n+else\n+\tgit rev-list --no-merges --cherry-pick --pretty=oneline --abbrev-commit \\\n+\t\t--abbrev=7 --reverse --left-right --topo-order \\\n+\t\t$revisions |\n+\tsed -n \"s/^>//p\" |\n+\twhile read -r shortsha1 rest\n+\tdo\n+\t\tadd_pick_line $shortsha1 \"$rest\"\n+\tdone\n fi\n \n test -s \"$todo\" || echo noop >> \"$todo\"\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195259","messageId":"1342596455-17046-5-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-4-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:32Z","receivedAt":"2012-07-18T07:27:32Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"The todo file is generated using (more-or-less) 'git rev-list\n$revisions --pretty=oneline --abbrev-commit --abbrev=7', i.e. by\nletting 'git rev-list' output both the abbreviated sha1 and the\nsubject line. To allow us to more easily generate the list of commits\nto rebase by using commands that don't support outputting the subject\nline, move this logic into add_pick_line.\n---\n git-rebase--interactive.sh | 21 +++++++++------------\n 1 file changed, 9 insertions(+), 12 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 4bb8e3f..9715830 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -814,7 +814,8 @@ add_pick_line () {\n \telse\n \t\tcomment_out=\n \tfi\n-\tprintf '%s\\n' \"${comment_out}pick $1 $2\" >>\"$todo\"\n+\tline=$(git rev-list -1 --pretty=oneline --abbrev-commit --abbrev=7 $1)\n+\tprintf '%s\\n' \"${comment_out}pick $line\" >>\"$todo\"\n }\n \n if test t = \"$preserve_merges\"\n@@ -835,13 +836,10 @@ then\n \t# No cherry-pick because our first pass is to determine\n \t# parents to rewrite and skipping dropped commits would\n \t# prematurely end our probe\n-\tgit rev-list --pretty=oneline --abbrev-commit \\\n-\t\t--abbrev=7 --reverse --left-right --topo-order \\\n-\t\t$revisions |\n+\tgit rev-list $revisions --reverse --left-right --topo-order |\n \tsed -n \"s/^>//p\" |\n-\twhile read -r shortsha1 rest\n+\twhile read -r sha1\n \tdo\n-\t\tsha1=$(git rev-parse $shortsha1)\n \t\tif test -z \"$rebase_root\"\n \t\tthen\n \t\t\tpreserve=t\n@@ -858,7 +856,7 @@ then\n \t\tif test f = \"$preserve\"\n \t\tthen\n \t\t\ttouch \"$rewritten\"/$sha1\n-\t\t\tadd_pick_line $shortsha1 \"$rest\"\n+\t\t\tadd_pick_line $sha1\n \t\tfi\n \tdone\n \t# Watch for commits that been dropped by --cherry-pick\n@@ -884,13 +882,12 @@ then\n \t\tfi\n \tdone\n else\n-\tgit rev-list --no-merges --cherry-pick --pretty=oneline --abbrev-commit \\\n-\t\t--abbrev=7 --reverse --left-right --topo-order \\\n-\t\t$revisions |\n+\tgit rev-list $revisions --reverse --left-right --topo-order \\\n+\t\t--no-merges --cherry-pick |\n \tsed -n \"s/^>//p\" |\n-\twhile read -r shortsha1 rest\n+\twhile read -r sha1\n \tdo\n-\t\tadd_pick_line $shortsha1 \"$rest\"\n+\t\tadd_pick_line $sha1\n \tdone\n fi\n \n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195257","messageId":"1342596455-17046-6-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-5-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 5/7] rebase -p: use --cherry-mark for todo file","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:33Z","receivedAt":"2012-07-18T07:27:33Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"While building the todo file, 'rebase -p' needs to find the\ncherry-picked commits in the branch that is about to be rebased. For\nthis, it calculates the set difference between the full set of commits\nand the non-cherry-picked ones (as reported by 'git rev-list\n--left-right --cherry-pick'). Now that have the 'git rev-list\n--cherry-mark' option (since adbbb31 (revision.c: introduce\n--cherry-mark, 2011-03-07)), we can instead use that option to get the\nset of cherry-picked commits.\n---\n git-rebase--interactive.sh | 11 +++--------\n 1 file changed, 3 insertions(+), 8 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 9715830..47beb58 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -859,17 +859,12 @@ then\n \t\t\tadd_pick_line $sha1\n \t\tfi\n \tdone\n-\t# Watch for commits that been dropped by --cherry-pick\n+\t# Now drop cherry-picked commits\n \tmkdir \"$dropped\"\n-\t# Save all non-cherry-picked changes\n-\tgit rev-list $revisions --left-right --cherry-pick | \\\n-\t\tsed -n \"s/^>//p\" > \"$state_dir\"/not-cherry-picks\n-\t# Now all commits and note which ones are missing in\n-\t# not-cherry-picks and hence being dropped\n-\tgit rev-list $revisions |\n+\tgit rev-list $revisions --cherry-mark --right-only | sed -ne \"s/^=//p\" |\n \twhile read rev\n \tdo\n-\t\tif test -f \"$rewritten\"/$rev -a \"$(sane_grep \"$rev\" \"$state_dir\"/not-cherry-picks)\" = \"\"\n+\t\tif test -f \"$rewritten\"/$rev\n \t\tthen\n \t\t\t# Use -f2 because if rev-list is telling us this commit is\n \t\t\t# not worthwhile, we don't want to track its multiple heads,\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195258","messageId":"1342596455-17046-7-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-6-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 6/7] rebase -p: don't request --left-right only to ignore left side","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:34Z","receivedAt":"2012-07-18T07:27:34Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"While generating the todo file, rebase -p calls 'git rev-list\n--left-right a...b' (with 'a' equal to $upstream or $onto and 'b'\nequal to $orig_head) and its output is piped through 'sed -n\n\"s/^>//p\"', making it equivalent to 'git rev-list --right-only\na...b'. Change the invocation to exactly that.\n\n(One could alternatively change it to 'git rev-list a..b', which would\nbe even simpler, if it wasn't for the fact that we already have the\nrevision range expression in a variable.)\n---\n git-rebase--interactive.sh | 3 +--\n 1 file changed, 1 insertion(+), 2 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 47beb58..cd5a2cc 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -836,8 +836,7 @@ then\n \t# No cherry-pick because our first pass is to determine\n \t# parents to rewrite and skipping dropped commits would\n \t# prematurely end our probe\n-\tgit rev-list $revisions --reverse --left-right --topo-order |\n-\tsed -n \"s/^>//p\" |\n+\tgit rev-list $revisions --reverse --right-only --topo-order |\n \twhile read -r sha1\n \tdo\n \t\tif test -z \"$rebase_root\"\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195261","messageId":"1342596455-17046-8-git-send-email-martin.von.zweigbergk@gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-7-git-send-email-martin.von.zweigbergk@gmail.com","subject":"[PATCH 7/7] rebase (without -p): correctly calculate patches to rebase","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:27:35Z","receivedAt":"2012-07-18T07:27:35Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"The different types of rebase use different ways of calculating the\npatches to rebase.\n\n'git rebase' (without -m/-i/-p) uses\n\n  git format-patch --ignore-if-in-upstream $upstream..$orig_head\n\n'git rebase -m' uses\n\n  git rev-list $upstream..$orig_head\n\n'git rebase -i' (without -p) uses\n\n  git rev-list $upstream...$orig_head --left-right --no-merges \\\n          --cherry-pick | sed -n \"s/^>//p\"\n\n, which could also have been written\n\n  git rev-list $upstream...$orig_head --right-only --no-merges \\\n          --cherry-pick\n\n'git rebase -p' uses\n\n  git rev-list $upstream...$orig_head --right-only\n\nfollowed by cherry-picked commits found by\n\n  git rev-list $upstream...$orig_head --cherry-mark --right-only |\n  | sed -ne \"s/^=//p\"\n\nAs Knut Franke reported in [1], the fact that there is no\n--ignore-if-in-upstream or equivalent when using merge-based rebase\nmeans that unnecessary conflicts can arise due to commits\ncherry-picked between $orig_head and $upstream.\n\nWith all the other types, there is a different problem with the method\nof calculating the commits to rebase. Copying the example history from\n[1]:\n\n      .-c\n     /\na---b---d---e---f\n         \\\n          .-g---E\n\nCommit E is here a cherry-pick of e. If we now run 'git rebase [-i|-p]\n--onto c f E', the commits to rebase will be those on E that are not\nequivalent to any of those in f, which in this case would be only\n'g'. Commit 'E' would thus be lost.\n\nTo solve both of the above problems, we want to find the commits in\n$upstream..$orig_head that are not cherry-picked in\n$orig_head..$onto. There is unfortunately no direct way of finding\nthese commits using 'git rev-list', so we will have to resort to using\n'git cherry' and filter for lines starting with '+'. This works for\nall but 'rebase -p', since 'git cherry' ignores merges.\n\nAs a side-effect, we also avoid the cost of formatting patches.\n\nTest case updates for 'rebase -m' by Knut, the rest by Martin.\n\n [1] http://thread.gmane.org/gmane.comp.version-control.git/161917\n\nHelped-by: Knut Franke <Knut.Franke@gmx.de>\nSigned-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com>\n---\n git-rebase--am.sh          |  6 ++----\n git-rebase--interactive.sh |  8 +++-----\n git-rebase--merge.sh       |  2 +-\n git-rebase.sh              | 11 ++++-------\n t/t3401-rebase-partial.sh  | 17 +++++++++++++++++\n t/t3406-rebase-message.sh  | 14 +++++++-------\n 6 files changed, 34 insertions(+), 24 deletions(-)\n\ndiff --git a/git-rebase--am.sh b/git-rebase--am.sh\nindex 37c1b23..fe3fdd1 100644\n--- a/git-rebase--am.sh\n+++ b/git-rebase--am.sh\n@@ -16,11 +16,9 @@ skip)\n \t;;\n esac\n \n-test -n \"$rebase_root\" && root_flag=--root\n test -n \"$keep_empty\" && git_am_opt=\"$git_am_opt --keep-empty\"\n-git format-patch -k --stdout --full-index --ignore-if-in-upstream \\\n-\t--src-prefix=a/ --dst-prefix=b/ \\\n-\t--no-renames $root_flag \"$revisions\" |\n+generate_revisions |\n+sed -e 's/\\([0-9a-f]\\{40\\}\\)/From \\1 Mon Sep 17 00:00:00 2001/' |\n git am $git_am_opt --rebasing --resolvemsg=\"$resolvemsg\" &&\n move_to_original_branch\n \ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex cd5a2cc..da32ca7 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -800,10 +800,8 @@ if test -z \"$rebase_root\"\n \t# this is now equivalent to ! -z \"$upstream\"\n then\n \tshortupstream=$(git rev-parse --short $upstream)\n-\trevisions=$upstream...$orig_head\n \tshortrevisions=$shortupstream..$shorthead\n else\n-\trevisions=$onto...$orig_head\n \tshortrevisions=$shorthead\n fi\n \n@@ -822,6 +820,7 @@ if test t = \"$preserve_merges\"\n then\n \tif test -z \"$rebase_root\"\n \tthen\n+\t\trevisions=$upstream...$orig_head\n \t\tmkdir \"$rewritten\" &&\n \t\tfor c in $(git merge-base --all $orig_head $upstream)\n \t\tdo\n@@ -829,6 +828,7 @@ then\n \t\t\t\tdie \"Could not init rewritten commits\"\n \t\tdone\n \telse\n+\t\trevisions=$onto...$orig_head\n \t\tmkdir \"$rewritten\" &&\n \t\techo $onto > \"$rewritten\"/root ||\n \t\t\tdie \"Could not init rewritten commits\"\n@@ -876,9 +876,7 @@ then\n \t\tfi\n \tdone\n else\n-\tgit rev-list $revisions --reverse --left-right --topo-order \\\n-\t\t--no-merges --cherry-pick |\n-\tsed -n \"s/^>//p\" |\n+\tgenerate_revisions |\n \twhile read -r sha1\n \tdo\n \t\tadd_pick_line $sha1\ndiff --git a/git-rebase--merge.sh b/git-rebase--merge.sh\nindex b10f2cf..bf4ec4b 100644\n--- a/git-rebase--merge.sh\n+++ b/git-rebase--merge.sh\n@@ -131,7 +131,7 @@ echo \"$onto_name\" > \"$state_dir/onto_name\"\n write_basic_state\n \n msgnum=0\n-for cmt in `git rev-list --reverse --no-merges \"$revisions\"`\n+for cmt in $(generate_revisions)\n do\n \tmsgnum=$(($msgnum + 1))\n \techo \"$cmt\" > \"$state_dir/cmt.$msgnum\"\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 1cd0633..0fdff87 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -530,6 +530,10 @@ then\n \tGIT_PAGER='' git diff --stat --summary \"$mb\" \"$onto\"\n fi\n \n+generate_revisions () {\n+\tgit cherry $onto $orig_head $upstream | sed -ne 's/^+ //p'\n+}\n+\n test \"$type\" = interactive && run_specific_rebase\n \n # Detach HEAD and reset the tree\n@@ -546,11 +550,4 @@ then\n \texit 0\n fi\n \n-if test -n \"$rebase_root\"\n-then\n-\trevisions=\"$onto..$orig_head\"\n-else\n-\trevisions=\"$upstream..$orig_head\"\n-fi\n-\n run_specific_rebase\ndiff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh\nindex 7f8693b..9c5d815 100755\n--- a/t/t3401-rebase-partial.sh\n+++ b/t/t3401-rebase-partial.sh\n@@ -50,4 +50,21 @@ test_expect_success 'rebase ignores empty commit' '\n \ttest $(git log --format=%s C..) = \"D\"\n '\n \n+test_expect_success 'rebase --onto does not re-apply patches in $onto' '\n+\tgit checkout C &&\n+\ttest_commit C2 C.t &&\n+\tgit checkout -B my-topic-branch master &&\n+\ttest_commit E &&\n+\tgit rebase --onto C2 A2 &&\n+\ttest \"$(git log --format=%s C2..)\" = E\n+'\n+\n+test_expect_success 'rebase --onto does not lose patches in $upstream' '\n+\tgit rebase --onto A2 E &&\n+\ttest \"$(git log --format=%s A2..)\" = \"E\n+C2\n+C\n+B\"\n+'\n+\n test_done\ndiff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh\nindex 6898377..3eecc66 100755\n--- a/t/t3406-rebase-message.sh\n+++ b/t/t3406-rebase-message.sh\n@@ -5,8 +5,10 @@ test_description='messages from rebase operation'\n . ./test-lib.sh\n \n quick_one () {\n-\techo \"$1\" >\"file$1\" &&\n-\tgit add \"file$1\" &&\n+\tfileno=$2\n+\ttest -z \"$fileno\" && fileno=$1\n+\techo \"$1\" >\"file$fileno\" &&\n+\tgit add \"file$fileno\" &&\n \ttest_tick &&\n \tgit commit -m \"$1\"\n }\n@@ -16,21 +18,19 @@ test_expect_success setup '\n \tgit branch topic &&\n \tquick_one X &&\n \tquick_one A &&\n-\tquick_one B &&\n+\tquick_one B A &&\n \tquick_one Y &&\n \n \tgit checkout topic &&\n \tquick_one A &&\n-\tquick_one B &&\n+\tquick_one B A &&\n \tquick_one Z &&\n \tgit tag start\n \n '\n \n cat >expect <<\\EOF\n-Already applied: 0001 A\n-Already applied: 0002 B\n-Committed: 0003 Z\n+Committed: 0001 Z\n EOF\n \n test_expect_success 'rebase -m' '\n-- \n1.7.11.1.104.ge7b44f1\n"},{"id":"195263","messageId":"CAOeW2eEeOZwcmqVy3pqLdkRRpmdGWdHwvv2cX4YGDxz1Xg-Gaw@mail.gmail.com","threadId":"31048","inReplyTo":"1342596455-17046-1-git-send-email-martin.von.zweigbergk@gmail.com","subject":"Re: [PATCH 0/7] correctly calculate patches to rebase","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-18T07:32:05Z","receivedAt":"2012-07-18T07:32:05Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"Argh! Sorry about the sendemail.chainreplyto=true. I must have read\nthat warning message incorrectly :-(.\n"},{"id":"195284","messageId":"20120718124827.GD25563@hmsreliant.think-freely.org","threadId":"31048","inReplyTo":"1342596455-17046-3-git-send-email-martin.von.zweigbergk@gmail.com","subject":"Re: [PATCH 2/7] git-rebase--interactive.sh: extract function for adding \"pick\" line","fromName":"Neil Horman","fromEmail":"nhorman@tuxdriver.com","sentAt":"2012-07-18T12:48:27Z","receivedAt":"2012-07-18T12:48:27Z","isPatch":true,"sender":{"key":"nhorman@tuxdriver.com","avatar":"https://avatars.githubusercontent.com/u/1032926?v=4"},"body":"On Wed, Jul 18, 2012 at 12:27:30AM -0700, Martin von Zweigbergk wrote:\n> Extract the code that adds a possibly commented-out \"pick\" line to the\n> todo file. This lets us reuse it more easily later.\n> ---\n>  git-rebase--interactive.sh | 21 ++++++++++++---------\n>  1 file changed, 12 insertions(+), 9 deletions(-)\n> \n> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\n> index bef7bc0..fa722b6 100644\n> --- a/git-rebase--interactive.sh\n> +++ b/git-rebase--interactive.sh\n> @@ -828,23 +828,26 @@ else\n>  \trevisions=$onto...$orig_head\n>  \tshortrevisions=$shorthead\n>  fi\n> -git rev-list $merges_option --pretty=oneline --abbrev-commit \\\n> -\t--abbrev=7 --reverse --left-right --topo-order \\\n> -\t$revisions | \\\n> -\tsed -n \"s/^>//p\" |\n> -while read -r shortsha1 rest\n> -do\n>  \n> -\tif test -z \"$keep_empty\" && is_empty_commit $shortsha1\n> +add_pick_line () {\n> +\tif test -z \"$keep_empty\" && is_empty_commit $1\n>  \tthen\n>  \t\tcomment_out=\"# \"\n>  \telse\n>  \t\tcomment_out=\n>  \tfi\n> +\tprintf '%s\\n' \"${comment_out}pick $1 $2\" >>\"$todo\"\n> +}\n>  \n> +git rev-list $merges_option --pretty=oneline --abbrev-commit \\\n> +\t--abbrev=7 --reverse --left-right --topo-order \\\n> +\t$revisions | \\\n> +\tsed -n \"s/^>//p\" |\n> +while read -r shortsha1 rest\n> +do\n>  \tif test t != \"$preserve_merges\"\n>  \tthen\n> -\t\tprintf '%s\\n' \"${comment_out}pick $shortsha1 $rest\" >>\"$todo\"\n> +\t\tadd_pick_line $shortsha1 \"$rest\"\n>  \telse\n>  \t\tsha1=$(git rev-parse $shortsha1)\n>  \t\tif test -z \"$rebase_root\"\n> @@ -863,7 +866,7 @@ do\n>  \t\tif test f = \"$preserve\"\n>  \t\tthen\n>  \t\t\ttouch \"$rewritten\"/$sha1\n> -\t\t\tprintf '%s\\n' \"${comment_out}pick $shortsha1 $rest\" >>\"$todo\"\n> +\t\t\tadd_pick_line $shortsha1 \"$rest\"\n>  \t\tfi\n>  \tfi\n>  done\n> -- \n> 1.7.11.1.104.ge7b44f1\n> \n> \n\nThanks!\nAcked-by: Neil Horman <nhorman@tuxdriver.com>\n"},{"id":"195356","messageId":"5009135C.208@viscovery.net","threadId":"31048","inReplyTo":"1342596455-17046-5-git-send-email-martin.von.zweigbergk@gmail.com","subject":"Re: [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2012-07-20T08:14:20Z","receivedAt":"2012-07-20T08:14:20Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:\n> @@ -814,7 +814,8 @@ add_pick_line () {\n>  \telse\n>  \t\tcomment_out=\n>  \tfi\n> -\tprintf '%s\\n' \"${comment_out}pick $1 $2\" >>\"$todo\"\n> +\tline=$(git rev-list -1 --pretty=oneline --abbrev-commit --abbrev=7 $1)\n> +\tprintf '%s\\n' \"${comment_out}pick $line\" >>\"$todo\"\n\nI don't like this. On Windows, rebase -i is already slow, and these extra\nprocesses will make it even slower.\n\n> +\tgit rev-list $revisions --reverse --left-right --topo-order |\n>  \tsed -n \"s/^>//p\" |\n> -\twhile read -r shortsha1 rest\n> +\twhile read -r sha1\n>  \tdo\n> -\t\tsha1=$(git rev-parse $shortsha1)\n>  \t\tif test -z \"$rebase_root\"\n...\n> -\t\t\tadd_pick_line $shortsha1 \"$rest\"\n> +\t\t\tadd_pick_line $sha1\n>  \t\tfi\n\nThis is 'rebase -p' case, and you trade the new processes for some old ones.\n\n> +\tgit rev-list $revisions --reverse --left-right --topo-order \\\n> +\t\t--no-merges --cherry-pick |\n>  \tsed -n \"s/^>//p\" |\n> -\twhile read -r shortsha1 rest\n> +\twhile read -r sha1\n>  \tdo\n> -\t\tadd_pick_line $shortsha1 \"$rest\"\n> +\t\tadd_pick_line $sha1\n>  \tdone\n\nBut in the regulare case, you don't; the processes are really new.\n\nAnything that can be done about this? Perhaps the rev-list call can\ngenerate all of the full SHA1, the short SHA1, and the subject with a\n--pretty format?\n\n-- Hannes\n"},{"id":"195357","messageId":"50091469.5030307@viscovery.net","threadId":"31048","inReplyTo":"1342596455-17046-8-git-send-email-martin.von.zweigbergk@gmail.com","subject":"Re: [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2012-07-20T08:18:49Z","receivedAt":"2012-07-20T08:18:49Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:\n> diff --git a/git-rebase--am.sh b/git-rebase--am.sh\n> index 37c1b23..fe3fdd1 100644\n> --- a/git-rebase--am.sh\n> +++ b/git-rebase--am.sh\n> @@ -16,11 +16,9 @@ skip)\n>  \t;;\n>  esac\n>  \n> -test -n \"$rebase_root\" && root_flag=--root\n>  test -n \"$keep_empty\" && git_am_opt=\"$git_am_opt --keep-empty\"\n> -git format-patch -k --stdout --full-index --ignore-if-in-upstream \\\n> -\t--src-prefix=a/ --dst-prefix=b/ \\\n> -\t--no-renames $root_flag \"$revisions\" |\n> +generate_revisions |\n> +sed -e 's/\\([0-9a-f]\\{40\\}\\)/From \\1 Mon Sep 17 00:00:00 2001/' |\n>  git am $git_am_opt --rebasing --resolvemsg=\"$resolvemsg\" &&\n>  move_to_original_branch\n\nJust curious (as all tests pass): What does this do? It looks like\nformat-patch is not called anymore and git-am sees only SHA1s. Does it\nforce git-am to cherry-pick the patches?\n\n-- Hannes\n"},{"id":"195373","messageId":"CAOeW2eHeySzEzj_8BByuz4jrc_CreLtZpTshcYsTxqBrtxyg0g@mail.gmail.com","threadId":"31048","inReplyTo":"5009135C.208@viscovery.net","subject":"Re: [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-20T15:47:58Z","receivedAt":"2012-07-20T15:47:58Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"Thanks for reviewing.\n\nOn Fri, Jul 20, 2012 at 1:14 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:\n> Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:\n>> @@ -814,7 +814,8 @@ add_pick_line () {\n>>       else\n>>               comment_out=\n>>       fi\n>> -     printf '%s\\n' \"${comment_out}pick $1 $2\" >>\"$todo\"\n>> +     line=$(git rev-list -1 --pretty=oneline --abbrev-commit --abbrev=7 $1)\n>> +     printf '%s\\n' \"${comment_out}pick $line\" >>\"$todo\"\n>\n> I don't like this. On Windows, rebase -i is already slow, and these extra\n> processes will make it even slower.\n\nI don't like it either :-(.\n\n> Anything that can be done about this? Perhaps the rev-list call can\n> generate all of the full SHA1, the short SHA1, and the subject with a\n> --pretty format?\n\nAfter patch 7/7, cherry is used instead of rev-list. Ideally, I would\nhave liked to teach \"git rev-list --cherry-pick\" to somehow use a\n<limit> just like cherry does, but I couldn't think of a generic way\nof doing that (in this case, we want to say something like \"range\na..b, but drop commits that are equivalent to any in b..c\"). I\nactually don't remember if I gave up because I couldn't think of a\nsensible way of specifying ranges like that, or if I just ran out of\ntime (not familiar with the revision-walking code). Now it seems to me\nthat something like \"git rev-list a..b --not-cherry-picks b..c\" makes\nsense, but maybe it's just too specific and we should just support the\nlimited (no pun intended) case we need to emulate \"git cherry\", i.e.\nsomething like \"git rev-list --cherry-with-limit=a c...b\". Feedback\nappreciated.\n\nMartin\n"},{"id":"195379","messageId":"CAOeW2eEMQrmSwS4ziTWetrWxkS-CTCPrJrzchCb1ZnqmaFhW7g@mail.gmail.com","threadId":"31048","inReplyTo":"50091469.5030307@viscovery.net","subject":"Re: [PATCH 7/7] rebase (without -p): correctly calculate patches to rebase","fromName":"Martin von Zweigbergk","fromEmail":"martin.von.zweigbergk@gmail.com","sentAt":"2012-07-20T15:58:15Z","receivedAt":"2012-07-20T15:58:15Z","isPatch":true,"sender":{"key":"martinvonz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/891642?v=4"},"body":"On Fri, Jul 20, 2012 at 1:18 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:\n> Am 7/18/2012 9:27, schrieb Martin von Zweigbergk:\n>> diff --git a/git-rebase--am.sh b/git-rebase--am.sh\n>> index 37c1b23..fe3fdd1 100644\n>> --- a/git-rebase--am.sh\n>> +++ b/git-rebase--am.sh\n>> @@ -16,11 +16,9 @@ skip)\n>>       ;;\n>>  esac\n>>\n>> -test -n \"$rebase_root\" && root_flag=--root\n>>  test -n \"$keep_empty\" && git_am_opt=\"$git_am_opt --keep-empty\"\n>> -git format-patch -k --stdout --full-index --ignore-if-in-upstream \\\n>> -     --src-prefix=a/ --dst-prefix=b/ \\\n>> -     --no-renames $root_flag \"$revisions\" |\n>> +generate_revisions |\n>> +sed -e 's/\\([0-9a-f]\\{40\\}\\)/From \\1 Mon Sep 17 00:00:00 2001/' |\n>>  git am $git_am_opt --rebasing --resolvemsg=\"$resolvemsg\" &&\n>>  move_to_original_branch\n>\n> Just curious (as all tests pass): What does this do? It looks like\n> format-patch is not called anymore and git-am sees only SHA1s. Does it\n> force git-am to cherry-pick the patches?\n\nThat probably deserves to be mentioned in the commit message. Or maybe\nin as a comment in the code. Either way, since 0fbb95d (am: don't call\nmailinfo if $rebasing, 2012-06-26), 'git am --rebasing' never looks at\nanything but the sha1, so most of the output from 'git format-patch'\nis currently ignored. It doesn't do cherry-pick, though, but runs 'git\ndiff-tree' and other commands and then feeds the result to 'git\napply', just like a regular 'git am' invocation would.\n\nMartin\n"},{"id":"195454","messageId":"7v4nozr030.fsf@alter.siamese.dyndns.org","threadId":"31048","inReplyTo":"CAOeW2eHeySzEzj_8BByuz4jrc_CreLtZpTshcYsTxqBrtxyg0g@mail.gmail.com","subject":"Re: [PATCH 4/7] git-rebase--interactive.sh: look up subject in add_pick_line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-07-22T20:51:31Z","receivedAt":"2012-07-22T20:51:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Martin von Zweigbergk <martin.von.zweigbergk@gmail.com> writes:\n\n> After patch 7/7, cherry is used instead of rev-list. Ideally, I would\n> have liked to teach \"git rev-list --cherry-pick\" to somehow use a\n> <limit> just like cherry does, but I couldn't think of a generic way\n> of doing that (in this case, we want to say something like \"range\n> a..b, but drop commits that are equivalent to any in b..c\"). I\n> actually don't remember if I gave up because I couldn't think of a\n> sensible way of specifying ranges like that, or if I just ran out of\n> time (not familiar with the revision-walking code).\n\nWhy not use patch-id output instead, then?  Grab patch-id for\ncommits b..c to make a mapping from patch-id to commits, do the same\nfor a..b and use the mapping to filter?\n"}]}