{"thread":{"id":"21970","subject":"[PATCH] Let format-patch and rebase ignore trivial merges.","startedAt":"2009-12-16T16:45:53Z","lastAt":"2009-12-18T18:23:08Z","messageCount":11,"participants":["Bernhard R. Link","Johannes Sixt","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"129994","messageId":"20091216164553.GA22471@pcpool00.mathematik.uni-freiburg.de","threadId":"21970","inReplyTo":null,"subject":"[PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-12-16T16:45:53Z","receivedAt":"2009-12-16T16:45:53Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"As git rebase and git format-patch linearize commits,\nhaving the same change in different branches causes in the\nbest case duplicate patches in the produced series and in the\nworst case conflicts. If there are trivial merges involved\n(i.e. merges that do not change the tree), then this patch\nwill cause git to only look at one branch, thereby avoiding\nduplicates and reducing the chance of conflicts.\n\nThere are two new options --prune-tree and --no-prune-tree\nadded.\n\n--prune-tree makes rev-list without paths equivalent to\n\"git rev-list $options -- .\" (or .. or ../.. and so on,\nif you are in some subdirectory).\nThis is the new default for format-patch and rebase\n\n--no-prune-tree deactivates --prune-tree.\n\nSigned-off-by: Bernhard R. Link <brlink@debian.org>\n---\n Documentation/rev-list-options.txt |   11 +++++++++++\n builtin-log.c                      |    1 +\n git-rebase--interactive.sh         |    1 +\n git-rebase.sh                      |    2 +-\n revision.c                         |   11 ++++++++++-\n revision.h                         |    1 +\n 6 files changed, 25 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt\nindex 1f57aed..6c5e90c 100644\n--- a/Documentation/rev-list-options.txt\n+++ b/Documentation/rev-list-options.txt\n@@ -328,6 +328,17 @@ The following options select the commits to be shown:\n \n \tCommits modifying the given <paths> are selected.\n \n+--prune-tree::\n+\n+\tNo paths is equivalent to the whole tree as path.\n+\tThat means merges with the same tree follow only one parent.\n+\t(Default for format-patch and rebase).\n+\n+--no-prune-tree::\n+\n+\tNo paths means not doing history simplification based on paths.\n+\t(Default for everything but format-patch and rebase).\n+\n --simplify-by-decoration::\n \n \tCommits that are referred by some branch or tag are selected.\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 1766349..efc2f40 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -960,6 +960,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \trev.diff = 1;\n \trev.combine_merges = 0;\n \trev.ignore_merges = 1;\n+\trev.prune_tree = 1;\n \tDIFF_OPT_SET(&rev.diffopt, RECURSIVE);\n \n \trev.subject_prefix = fmt_patch_subject_prefix;\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 0bd3bf7..ea23d9b 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -703,6 +703,7 @@ first and then run 'git rebase --continue' again.\"\n \t\tfi\n \t\tgit rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \\\n \t\t\t--abbrev=7 --reverse --left-right --topo-order \\\n+\t\t\t--prune-tree \\\n \t\t\t$REVISIONS | \\\n \t\t\tsed -n \"s/^>//p\" | while read shortsha1 rest\n \t\tdo\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex b121f45..2186619 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -539,7 +539,7 @@ echo \"$head_name\" > \"$dotest/head-name\"\n echo \"$GIT_QUIET\" > \"$dotest/quiet\"\n \n msgnum=0\n-for cmt in `git rev-list --reverse --no-merges \"$revisions\"`\n+for cmt in `git rev-list --reverse --no-merges --prune-tree \"$revisions\"`\n do\n \tmsgnum=$(($msgnum + 1))\n \techo \"$cmt\" > \"$dotest/cmt.$msgnum\"\ndiff --git a/revision.c b/revision.c\nindex a8a3c3a..3350af6 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1112,6 +1112,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->dense = 1;\n \t} else if (!strcmp(arg, \"--sparse\")) {\n \t\trevs->dense = 0;\n+\t} else if (!strcmp(arg, \"--prune-tree\")) {\n+\t\trevs->prune_tree = 1;\n+\t} else if (!strcmp(arg, \"--no-prune-tree\")) {\n+\t\trevs->prune_tree = 0;\n \t} else if (!strcmp(arg, \"--show-all\")) {\n \t\trevs->show_all = 1;\n \t} else if (!strcmp(arg, \"--remove-empty\")) {\n@@ -1408,8 +1412,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \t\t}\n \t}\n \n-\tif (prune_data)\n+\tif (prune_data) {\n \t\trevs->prune_data = get_pathspec(revs->prefix, prune_data);\n+\t} else if (revs->prune_tree) {\n+\t\t/* limit whole tree (limits trivial merges to one side) */\n+\t\tstatic const char *whole_tree[2] = { \"\", NULL };\n+\t\trevs->prune_data = whole_tree;\n+\t}\n \n \tif (revs->def == NULL)\n \t\trevs->def = def;\ndiff --git a/revision.h b/revision.h\nindex d368003..d007aaa 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -38,6 +38,7 @@ struct rev_info {\n \t/* Traversal flags */\n \tunsigned int\tdense:1,\n \t\t\tprune:1,\n+\t\t\tprune_tree:1,\n \t\t\tno_merges:1,\n \t\t\tmerges_only:1,\n \t\t\tno_walk:1,\n"},{"id":"129995","messageId":"4B29106C.1040501@viscovery.net","threadId":"21970","inReplyTo":"20091216164553.GA22471@pcpool00.mathematik.uni-freiburg.de","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-12-16T16:53:00Z","receivedAt":"2009-12-16T16:53:00Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Please do not set Mail-Followup-To (and use reply-to-all to keep the Cc list).\n\nBernhard R. Link schrieb:\n> --prune-tree makes rev-list without paths equivalent to\n> \"git rev-list $options -- .\" (or .. or ../.. and so on,\n> if you are in some subdirectory).\n> This is the new default for format-patch and rebase\n\nWhy do you need a new option when you can just add \"-- .\" to the rev-list\ninvocation?\n\n-- Hannes\n"},{"id":"130022","messageId":"20091217093547.GA25451@pcpool00.mathematik.uni-freiburg.de","threadId":"21970","inReplyTo":"4B29106C.1040501@viscovery.net","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-12-17T09:35:47Z","receivedAt":"2009-12-17T09:35:47Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"* Johannes Sixt <j.sixt@viscovery.net> [091216 17:53]:\n> Bernhard R. Link schrieb:\n> > --prune-tree makes rev-list without paths equivalent to\n> > \"git rev-list $options -- .\" (or .. or ../.. and so on,\n> > if you are in some subdirectory).\n> > This is the new default for format-patch and rebase\n>\n> Why do you need a new option when you can just add \"-- .\" to the rev-list\n> invocation?\n\nI want the default for format-patch changed.\n\nFor this I think it is easiest to add a new rev_info flag, as otherwise\nformat-patch would need to duplicate parsing the rev_list options\nand either duplicate applying revs->prune_data or changing the argv for\nsetup_revisions with some special casing of bare repository and non-bare\nrepository cases.\n\nAnd if there is that rev_info flag I think it is most logical to make\nit accessible from the outside.\n\nThat also allows to revert to the old format-patch behaviour,\nin case someone uses format-patch not to get some appliable patches but\nsome differently formated log or for something else I cannot imagine.\n\nAnd when there is that option, I think it is more robust to use that\nin merge -m and merge -i, as \"-- .\" only does the right thing by chance\nbecause both only work with a non-bare repository and have\ncd_to_toplevel.\n\nHochachtungsvoll,\n\tBernhard R. Link\n-- \nPlease do not CC me if git@vger.kernel.org also gets a copy.\n"},{"id":"130027","messageId":"4B2A1895.2000803@viscovery.net","threadId":"21970","inReplyTo":"20091217093547.GA25451@pcpool00.mathematik.uni-freiburg.de","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-12-17T11:40:05Z","receivedAt":"2009-12-17T11:40:05Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Bernhard R. Link schrieb:\n> * Johannes Sixt <j.sixt@viscovery.net> [091216 17:53]:\n>> Bernhard R. Link schrieb:\n>>> --prune-tree makes rev-list without paths equivalent to\n>>> \"git rev-list $options -- .\" (or .. or ../.. and so on,\n>>> if you are in some subdirectory).\n>>> This is the new default for format-patch and rebase\n>> Why do you need a new option when you can just add \"-- .\" to the rev-list\n>> invocation?\n> \n> I want the default for format-patch changed.\n\nI do not see why format-patch would have to be changed. The case that you\noutline (a merge -s ours happened and you want to follow only one parent)\nis rare enough and even more rarly will somebody want to apply\nformat-patch to such a history.\n\nBut I guess that you are actually not interested in format-patch per se,\nbut rather in rebase (which uses format-patch).\n\n> For this I think it is easiest to add a new rev_info flag, as otherwise\n> format-patch would need to duplicate parsing the rev_list options\n> and either duplicate applying revs->prune_data or changing the argv for\n> setup_revisions with some special casing of bare repository and non-bare\n> repository cases.\n\nI haven't looked at the code, but wouldn't it be matter of \"if we do not\nhave any pathspec, add '.'\" *after* all options are parsed?\n\n> And when there is that option, I think it is more robust to use that\n> in merge -m and merge -i, as \"-- .\" only does the right thing by chance\n> because both only work with a non-bare repository and have\n> cd_to_toplevel.\n\ngit rev-list -- . works in a bare repository, too. If you hard-code \"-- .\"\nin the rev-list invocations in git-rebase[--interactive], then it cannot\nbe said that this works \"by chance\" due to cd_to_toplevel.\n\n-- Hannes\n"},{"id":"130044","messageId":"20091217214843.GA414@pcpool00.mathematik.uni-freiburg.de","threadId":"21970","inReplyTo":"4B2A1895.2000803@viscovery.net","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-12-17T21:48:43Z","receivedAt":"2009-12-17T21:48:43Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"* Johannes Sixt <j.sixt@viscovery.net> [091217 12:40]:\n> > I want the default for format-patch changed.\n>\n> I do not see why format-patch would have to be changed. The case that you\n> outline (a merge -s ours happened and you want to follow only one parent)\n> is rare enough\n\nWhile it is rare, the result format-patch currently produces is quite a\ndesaster without any need.\n\n> and even more rarly will somebody want to apply format-patch to such a history.\n> But I guess that you are actually not interested in format-patch per se,\n> but rather in rebase (which uses format-patch).\n\nI'm looking for a nice way to store the history of a patches in a Debian package.\nCurrently the best way is to use quilt and store the patches in git.\nTopgit is quite overkill, git directly preserving history means no way to\nexport sane patches. And git rebase -i means losing history of previous\nstates and pullability.\n\nAn way to combine those is doing many trivial merges, but that kills\nrebase and format-patch. (While the patch exporting for creating the\ndebian source packages could change to the right directory and give the\nproper arguments, needing to remember the extra argument and teaching\nanyone else involved how to call it to get what to sent to upstream\nis annoying).\n\n> I haven't looked at the code, but wouldn't it be matter of \"if we do not\n> have any pathspec, add '.'\" *after* all options are parsed?\n\nThat's what I would say my patch is doing.\n\n> git rev-list -- . works in a bare repository, too. If you hard-code \"-- .\"\n> in the rev-list invocations in git-rebase[--interactive], then it cannot\n> be said that this works \"by chance\" due to cd_to_toplevel.\n\nIt works in a bare repository. But it does not work when called from a\nsubdirectory of the working dir.\n\nThe easiest way I see to express generally\n\ngit rev-list --prune-tree $args\n\nis\n\ntopdir=$(git rev-parse --show-cdup)\nif test -z \"$topdir\" ; then\n        topdir=.\nfi\nset -- $args\nwhile test $# -gt 0 ; do\n        if test \"x$1\" = \"x--\" ; then\n                break\n        fi\n        shift\ndone\nif test $# -gt 1 ; then\n        git rev-list $args\nelif test $# -eq 1 ; then\n        git rev-list $args $topdir\nelse\n        git rev-list $args -- $topdir\nfi\n\nHochachtungsvoll,\n\tBernhard R. Link\n-- \n\"Never contain programs so few bugs, as when no debugging tools are available!\"\n\tNiklaus Wirth\n"},{"id":"130045","messageId":"7vaaxhfcfe.fsf@alter.siamese.dyndns.org","threadId":"21970","inReplyTo":"4B29106C.1040501@viscovery.net","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-17T22:44:37Z","receivedAt":"2009-12-17T22:44:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> Please do not set Mail-Followup-To (and use reply-to-all to keep the Cc list).\n>\n> Bernhard R. Link schrieb:\n>> --prune-tree makes rev-list without paths equivalent to\n>> \"git rev-list $options -- .\" (or .. or ../.. and so on,\n>> if you are in some subdirectory).\n>> This is the new default for format-patch and rebase\n>\n> Why do you need a new option when you can just add \"-- .\" to the rev-list\n> invocation?\n\nI agree that --[no-]prune-tree options are unnecessary.  The patch to\nbuiltin-log.c, the second hunk to revision.c, and revision.h would be\nsufficient and all others should be dropped.  Instead, the shell script\nPorcelains can simply add \"-- .\" at the end of their rev-list invocations.\n\nThat way, we don't have to add anything to the documentation either.\n\nBut I wonder if it is an indication of something screwy in the workflow,\nif a branch that merges others with \"-s ours\" is where the patches for\nupstream submission is taken from with format-patch, or what is rebased\nand internally gets its patches extracted with format-patch.\n\nA branch that merges with \"-s ours\" is typically done so that others can\npull and build against (and \"-s ours\" is used to cauterize the history of\na bad side branch), and good bits merged into it would also have come from\na different clean branch that is merged into that branch.  It might make\nmore sense to format-patch that clean branch when preparing for upstream\nsubmission, than the \"aggregated mesh of commits\" branch with \"-s ours\"\nfix-ups.\n\nOn the other hand, a branch that will be rebased to keep up with others is\nby definition private, and I don't see a reason to mark with \"-s ours\" to\ncauterize history of an unrelated side branch that tried to do something\nsimilar to what the branch is trying to achieve in that setting.  You can\ninstead ignore such a side branch and not merge with it.  So I don't know\nhow a sane history you are going to rebase ends up containing a \"-s ours\"\nmerge to begin with.\n"},{"id":"130068","messageId":"20091218130603.GA6193@pcpool00.mathematik.uni-freiburg.de","threadId":"21970","inReplyTo":"7vaaxhfcfe.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-12-18T13:06:03Z","receivedAt":"2009-12-18T13:06:03Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"* Junio C Hamano <gitster@pobox.com> [091217 23:44]:\n[order of replies changed for the sake of answers]\n> On the other hand, a branch that will be rebased to keep up with others is\n> by definition private, and I don't see a reason to mark with \"-s ours\" to\n> cauterize history of an unrelated side branch that tried to do something\n> similar to what the branch is trying to achieve in that setting.  You can\n> instead ignore such a side branch and not merge with it.  So I don't know\n> how a sane history you are going to rebase ends up containing a \"-s ours\"\n> merge to begin with.\n\nThink of a team working to prepare a complicated change that is to be\npresented as multiple easily reviewable patches.\n\nIf you do something like that alone on a single computer, you will\nusually have a branch, collect some commits and merge fixes for previous\ncommits together with rebase -i. If it takes a longer time you also\nrebase to upstream from time to time, fixing all the conflicts and so\non. (You can also just collect and hope to still separate them into\ndifferent patches at the end, but that usually gets messy in my\nexperience).\nThose rebases will make you lose some history, which you can work around\nby having some extra branches with older states. If you work on\ndifferent computers, pulling and pushing the current state of the branch\naround needs special care as the non-fast-forward needed all the time\nmight also easily overwrite and newer with an older state (and keeping\ntrack of the older branches is a big mess unless you have one central\nrepository).\nIf there are multiple people working on this, things will not get\neasier. In this case having the new clean branch containing a trivial merge\nwith second parent the old history will both allow easy push and pull\nand keep the history so one can look at older states.\n(see http://marc.info/?l=git&m=125959221911443&w=2)\n\nA special case for this are modifications in Debian packages. The\npatches have to be rebased to every new upstream, while at the same\ntime should always be in a state so they can be sent upstream and\nupstream can pick some of them. (And ideally the debian source package\ndoes include the patches as nice topic separated patch files, so other\ndistributions/users can easily pick those independent of what vcs they\nuse).\n\n> A branch that merges with \"-s ours\" is typically done so that others can\n> pull and build against (and \"-s ours\" is used to cauterize the history of\n> a bad side branch), and good bits merged into it would also have come from\n> a different clean branch that is merged into that branch.  It might make\n> more sense to format-patch that clean branch when preparing for upstream\n> submission, than the \"aggregated mesh of commits\" branch with \"-s ours\"\n> fix-ups.\n\nformat-patch has to choose a parent. Choosing the first one make the\nmost sense for me (as the first is the only real 'special' one).\nIn the workflows I envision the first parent would also be the one with\nthe clean history.\n\nHochachtungsvoll,\n\tBernhard R. Link\n-- \n\"Never contain programs so few bugs, as when no debugging tools are available!\"\n\tNiklaus Wirth\n"},{"id":"130069","messageId":"4B2B8213.1090104@viscovery.net","threadId":"21970","inReplyTo":"20091218130603.GA6193@pcpool00.mathematik.uni-freiburg.de","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-12-18T13:22:27Z","receivedAt":"2009-12-18T13:22:27Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Please do not cull Cc list.\n\nBernhard R. Link schrieb:\n> format-patch has to choose a parent. Choosing the first one make the\n> most sense for me (as the first is the only real 'special' one).\n> In the workflows I envision the first parent would also be the one with\n> the clean history.\n\nThen use\n\n   git format-patch --first-parent upstream..\n\n-- Hannes\n"},{"id":"130070","messageId":"20091218144756.GA7211@pcpool00.mathematik.uni-freiburg.de","threadId":"21970","inReplyTo":"4B2B8213.1090104@viscovery.net","subject":"Re: [PATCH] Let format-patch and rebase ignore trivial merges.","fromName":"Bernhard R. Link","fromEmail":"brl@pcpool00.mathematik.uni-freiburg.de","sentAt":"2009-12-18T14:47:57Z","receivedAt":"2009-12-18T14:47:57Z","isPatch":true,"sender":{"key":"brl@pcpool00.mathematik.uni-freiburg.de","avatar":null},"body":"* Johannes Sixt <j.sixt@viscovery.net> [091218 14:22]:\n> > format-patch has to choose a parent. Choosing the first one make the\n> > most sense for me (as the first is the only real 'special' one).\n> > In the workflows I envision the first parent would also be the one with\n> > the clean history.\n>\n> Then use\n>\n>    git format-patch --first-parent upstream..\n\nAs already described in the thread my mail contained a link to, this\nwill miss patches if there were also real merges (which there will).\n\nBut the point that there is only a --first-parent and no --last-parent\nshows that the first parent is special, so format-patch should choose\nthe first one.\n\nHochachtungsvoll,\n\tBernhard R. Link\n-- \nPlease do not CC me if also sending to git@vger.kernel.org.\n"},{"id":"130073","messageId":"20091218151102.GB7211@pcpool00.mathematik.uni-freiburg.de","threadId":"21970","inReplyTo":"7vaaxhfcfe.fsf@alter.siamese.dyndns.org","subject":"[PATCH v2] Let format-patch and rebase ignore trivial merges.","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-12-18T15:11:02Z","receivedAt":"2009-12-18T15:11:02Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"As git rebase and git format-patch linearize commits,\nhaving the same change in different branches causes in the\nbest case duplicate patches in the produced series and in the\nworst case conflicts. If there are trivial merges involved\n(i.e. merges that do not change the tree), then this patch\nwill cause git to only look at one branch, thereby avoiding\nduplicates and reducing the chance of conflicts.\n\nSigned-off-by: Bernhard R. Link <brlink@debian.org>\n---\n builtin-log.c              |    1 +\n git-rebase--interactive.sh |    2 +-\n git-rebase.sh              |    2 +-\n revision.c                 |    7 ++++++-\n revision.h                 |    1 +\n 5 files changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 1766349..efc2f40 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -960,6 +960,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \trev.diff = 1;\n \trev.combine_merges = 0;\n \trev.ignore_merges = 1;\n+\trev.prune_tree = 1;\n \tDIFF_OPT_SET(&rev.diffopt, RECURSIVE);\n \n \trev.subject_prefix = fmt_patch_subject_prefix;\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 0bd3bf7..e5c134b 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -703,7 +703,7 @@ first and then run 'git rebase --continue' again.\"\n \t\tfi\n \t\tgit rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \\\n \t\t\t--abbrev=7 --reverse --left-right --topo-order \\\n-\t\t\t$REVISIONS | \\\n+\t\t\t$REVISIONS -- . | \\\n \t\t\tsed -n \"s/^>//p\" | while read shortsha1 rest\n \t\tdo\n \t\t\tif test t != \"$PRESERVE_MERGES\"\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex b121f45..dab6949 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -539,7 +539,7 @@ echo \"$head_name\" > \"$dotest/head-name\"\n echo \"$GIT_QUIET\" > \"$dotest/quiet\"\n \n msgnum=0\n-for cmt in `git rev-list --reverse --no-merges \"$revisions\"`\n+for cmt in `git rev-list --reverse --no-merges \"$revisions\" -- .`\n do\n \tmsgnum=$(($msgnum + 1))\n \techo \"$cmt\" > \"$dotest/cmt.$msgnum\"\ndiff --git a/revision.c b/revision.c\nindex a8a3c3a..b27b682 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1408,8 +1408,13 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \t\t}\n \t}\n \n-\tif (prune_data)\n+\tif (prune_data) {\n \t\trevs->prune_data = get_pathspec(revs->prefix, prune_data);\n+\t} else if (revs->prune_tree) {\n+\t\t/* limit whole tree (limits trivial merges to one side) */\n+\t\tstatic const char *whole_tree[2] = { \"\", NULL };\n+\t\trevs->prune_data = whole_tree;\n+\t}\n \n \tif (revs->def == NULL)\n \t\trevs->def = def;\ndiff --git a/revision.h b/revision.h\nindex d368003..d007aaa 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -38,6 +38,7 @@ struct rev_info {\n \t/* Traversal flags */\n \tunsigned int\tdense:1,\n \t\t\tprune:1,\n+\t\t\tprune_tree:1,\n \t\t\tno_merges:1,\n \t\t\tmerges_only:1,\n \t\t\tno_walk:1,\n"},{"id":"130084","messageId":"7vy6l0xhtf.fsf@alter.siamese.dyndns.org","threadId":"21970","inReplyTo":"20091218151102.GB7211@pcpool00.mathematik.uni-freiburg.de","subject":"Re: [PATCH v2] Let format-patch and rebase ignore trivial merges.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-18T18:23:08Z","receivedAt":"2009-12-18T18:23:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Bernhard R. Link\" <brlink@debian.org> writes:\n\n[offtopic: weren't you already asked not to try redirecting away direct\nresponses to you by using M-F-T and wasting time of people who do want to\nrespond directly to you?  Please don't.]\n\n> As git rebase and git format-patch linearize commits,\n> having the same change in different branches causes in the\n> best case duplicate patches in the produced series and in the\n> worst case conflicts. If there are trivial merges involved\n> (i.e. merges that do not change the tree), then this patch\n> will cause git to only look at one branch, thereby avoiding\n> duplicates and reducing the chance of conflicts.\n\nThe patch text itself from the cursory review looks Ok (I haven't thought\nthings through yet, let alone applying it, though).\n\nOne issue in the proposed commit log message above is that \"trivial merge\"\nis an established technical term that means something very different from\n\"resulting tree of the merge matches exactly one of the parents' tree\",\nand it needs to be reworded.  In this case it is easy [*1*].  Drop\neverything after \"If there are ...\", and add something like this as a\nseparate paragraph:\n\n    Avoid outputting duplicate patches by ignoring all other parents when\n    the merge result matches exactly one of the parents.\n\nThe code comment also needs to be adjusted.\n\nThanks.\n\n[Footnote]\n\n*1* It is a good habit to acquire to question yourself if you can omit \"X\"\naltogether and just say \"Y\" after writing \"X (i.e. Y)\".\n"}]}