{"thread":{"id":"21797","subject":"equal-tree-merges as way to make rebases fast-forward-able","startedAt":"2009-11-30T14:43:33Z","lastAt":"2009-12-02T18:03:17Z","messageCount":29,"participants":["Bernhard R. Link","Sverre Rabbelier","Paolo Bonzini","Michael J Gruber","Johannes Schindelin","Junio C Hamano","Johannes Sixt","Nanako Shiraishi","Nicolas Pitre","Michael Haggerty"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"128771","messageId":"cover.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":null,"subject":"equal-tree-merges as way to make rebases fast-forward-able","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:43:33Z","receivedAt":"2009-11-30T14:43:33Z","isPatch":false,"sender":{"key":"brlink@debian.org","avatar":null},"body":"The itch this idea is supposed to scratch is the problem that a rebase\nor a amended commit is no longer a fast-forward, so cannot be easily\npulled.\nWhile this is not a problem in most workflows, as one can either merge\nor keep everything private and rebase until published, it would be nice\nto have a way for cases in between, where both a clean presentable\ncommit order is to be maintained and people (or yourself from different\nrepositories) should be able to easily upgrade to newer versions without\nan error-prone not-fast-forward.\n\nMy idea to solve this is combining both histories, the rebased/revised\nhistory and the actualy history, marking with some \"equal-tree-merge\"\nthe point where they have the same result.\nThe following mails show some patches to implement this by means of\na merge where all parents have the same tree and some special casing\nwhen encountering such a thing. This has the advantage that older git\nversion will just see strange merges and may present both histories,\nbut otherwise just work.\n\nExample 1:\n\nLet's assume you maintain such a regularily-rebased branch that you\nwant to be able to publish (or pull from other repositories for example\non your laptop):\n\no=m=o=o=master\n   \\\n    a=b=c=d=e=feature\n\nwith this patch you can do \"git rebase -eqt master\" and get:\n\n              a'=b'=c'=d'=e'=feature'=eqt\n             /                       /\no=m=o=o=master--------              /\n   \\                  \\            /\n    a=b=c=d=e=feature--merge-------\n\ni.e: the new feature branch has both histories:\n  - \"feature'\" where everything is cleanly rebased and in a form where\n               format-patch is suitable to send it upstream\n  - \"merge\" which is both a descendant from feature (so one can see what\n    changed since that time and can just pull when one had had cloned feature)\n\nExample 2:\n\nLet's assume you have a feature branch like\n\no=master\n   \\\n    a=b=c=d=e=f\n\nAssume you just commited \"f\" which fixes a bug introduced by \"b\".\nNow you of course do not want to send it that way upstream (as it will\nmake reviewing harder, may force people bisecting to skip some versions\nevery time they hit this region and so on), so you want to\nbisect -i and squash \"f\" into \"b\".\n\no=master\n   \\\n    a=b+f=c'=d'=e'\n\nBut if you had already cloned at state \"d\" to your laptop (or made a backup\nof that branch at some server, or published it for use of some collegues)\nit will not be a fast-forward, so you have to be very carefull to not\naccidentially lose a commit that is already there.\n\nSo with this patches you can do \"git rebase -i --eqt\" and squash f into b\nand get:\n\no=master\n   \\\n    a=b=c=d=e=f---\n     \\            \\\n      b+f=c'=d'=e'=eqt\n\nwhich means that you can just pull from your laptop and get the new head\nas fast-forward, but still have a proper history ready for submitting.\n\nThe only downsize of this approach is that an unpatched/old git of course\ndoes not know about that it can just choose one of both histories but think\nit has to look at both, so git-format-patch will return patches multiple times\nand git-rebase will also try to apply both branches, which the patched version\nno longer does, only showing the 'presentable' in this case.\n\nThose patches are a bit rough and mostly intended to show how it could work\nand to allow experimenting with it. I think the biggest thing still missing\n(apart from documentation, error handling, better commit messages) is making\ngit bisect take advantage of this and only looking at the nice branch.\n\nBernhard R. Link (7):\n  add new command git equal-tree-marker\n  add option to only visit the first parent of a equal tree merge\n  format-patch defaults to --first-equal-tree-only\n  support equal tree merges in interactive rebase\n  make rebase -m equal tree marker aware\n  add support for creating equal tree markers after rebase\n  add support for creating equal tree markers to rebase -i\n\n .gitignore                 |    1 +\n Makefile                   |    1 +\n builtin-log.c              |    1 +\n git-equal-tree-marker.sh   |   50 ++++++++++++++++++++++++++++++++++++++\n git-rebase--interactive.sh |   33 +++++++++++++++++++++++++\n git-rebase.sh              |   35 ++++++++++++++++++++++++--\n revision.c                 |   57 +++++++++++++++++++++++++++++++++++++-------\n revision.h                 |    1 +\n 8 files changed, 167 insertions(+), 12 deletions(-)\n create mode 100644 git-equal-tree-marker.sh\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":"128772","messageId":"9e6833ef7188f41d6ea46ddcf92929af284b4adb.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 1/7] add new command git equal-tree-marker","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:43:58Z","receivedAt":"2009-11-30T14:43:58Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"This adds a new commit denoting tha current branch has the same\ntree as another branch, thus allowing fast-forward from the named\ncommits to this one.\n\nTODO: manpage, rewrite as builtin once the semantics are accepted?\n---\n .gitignore               |    1 +\n Makefile                 |    1 +\n git-equal-tree-marker.sh |   50 ++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 52 insertions(+), 0 deletions(-)\n create mode 100644 git-equal-tree-marker.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex ac02a58..248d146 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -39,6 +39,7 @@\n /git-difftool\n /git-difftool--helper\n /git-describe\n+/git-equal-tree-marker\n /git-fast-export\n /git-fast-import\n /git-fetch\ndiff --git a/Makefile b/Makefile\nindex 4dba10e..913d4c4 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -336,6 +336,7 @@ TEST_PROGRAMS =\n SCRIPT_SH += git-am.sh\n SCRIPT_SH += git-bisect.sh\n SCRIPT_SH += git-difftool--helper.sh\n+SCRIPT_SH += git-equal-tree-marker.sh\n SCRIPT_SH += git-filter-branch.sh\n SCRIPT_SH += git-lost-found.sh\n SCRIPT_SH += git-merge-octopus.sh\ndiff --git a/git-equal-tree-marker.sh b/git-equal-tree-marker.sh\nnew file mode 100644\nindex 0000000..403cc56\n--- /dev/null\n+++ b/git-equal-tree-marker.sh\n@@ -0,0 +1,50 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2009 Bernhard R. Link\n+#\n+# Create a new commit making HEAD parent of the arguments,\n+# which must be commits with the same tree.\n+\n+set -e\n+\n+USAGE='<head>...'\n+LONG_USAGE='Make current HEAD parent of the given heads (which need to have the same tree).'\n+SUBDIRECTORY_OK=Yes\n+OPTIONS_SPEC=\n+. git-sh-setup\n+cd_to_toplevel\n+\n+# is there really no function for this?\n+tree_of_commit() {\n+\tgit cat-file commit \"$1\" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'\n+}\n+\n+head=\"$(git rev-parse --verify HEAD)\"\n+htree=\"$(tree_of_commit $head)\"\n+parents=\"\"\n+while test $# -gt 0\n+do\n+\tcase \"$1\" in\n+\t-h|--h|--he|--hel|--help)\n+\t\tusage\n+\t\t;;\n+\t*)\n+\t\th=\"$(git rev-parse --verify $1)\"\n+\t\ttree=\"$(tree_of_commit \"$h\")\"\n+\t\tif test \"x${htree}\" != \"x${tree}\" ; then\n+\t\t\techo \"Tree of $h is not the same as tree of $head\" >&2\n+\t\t\texit 1\n+\t\tfi\n+\t\tparents=\"$parents -p $h\"\n+\t\t;;\n+\tesac\n+\tshift\n+done\n+\n+if test \"x$parents\" = \"x\" ; then\n+\techo \"Not enough arguments!\" >&2\n+\texit 1\n+fi\n+\n+new_commit=\"$(echo \"Equal tree marker\" | git commit-tree \"$tree\" -p \"$head\" $parents)\"\n+git-update-ref HEAD \"$new_commit\"\n-- \n1.6.6.rc0.82.g60a15.dirty\n"},{"id":"128773","messageId":"590501c88c7a7b4a7c0c29543775060d4b0e2316.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 2/7] add option to only visit the first parent of a equal tree merge","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:44:18Z","receivedAt":"2009-11-30T14:44:18Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"rev_info gets a new flag first_equal_tree_only that causes\nrevision walks to ignore all but the first parent of equal tree\nmerges.\nThe default is off and there are options --first-equal-tree-only\nand --all-equal-trees to switch it on/off respectively.\n\nTODO:\n - manpage updates\n - check interaction with some of the other options\n---\n revision.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++---------\n revision.h |    1 +\n 2 files changed, 49 insertions(+), 9 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex a8a3c3a..fb019d6 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -452,6 +452,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,\n \tstruct commit_list *parent = commit->parents;\n \tunsigned left_flag;\n \tstruct commit_list *cached_base = cache_ptr ? *cache_ptr : NULL;\n+\tint first_parent_only;\n \n \tif (commit->object.flags & ADDED)\n \t\treturn 0;\n@@ -499,6 +500,21 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,\n \n \tleft_flag = (commit->object.flags & SYMMETRIC_LEFT);\n \n+\tif (revs->first_parent_only)\n+\t\tfirst_parent_only = 1;\n+\telse if (revs->first_equal_tree_only && commit->parents) {\n+\t\tfor (parent = commit->parents; parent; parent = parent->next) {\n+\t\t\tstruct commit *p = parent->item;\n+\n+\t\t\tif (parse_commit(p) < 0)\n+\t\t\t\treturn -1;\n+\t\t\tif (p->tree != commit->tree)\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tfirst_parent_only = !parent;\n+\t} else\n+\t\tfirst_parent_only = 0;\n+\n \tfor (parent = commit->parents; parent; parent = parent->next) {\n \t\tstruct commit *p = parent->item;\n \n@@ -511,7 +527,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,\n \t\t\tp->object.flags |= SEEN;\n \t\t\tinsert_by_date_cached(p, list, cached_base, cache_ptr);\n \t\t}\n-\t\tif (revs->first_parent_only)\n+\t\tif (first_parent_only)\n \t\t\tbreak;\n \t}\n \treturn 0;\n@@ -1067,6 +1083,10 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->min_age = approxidate(arg + 8);\n \t} else if (!strcmp(arg, \"--first-parent\")) {\n \t\trevs->first_parent_only = 1;\n+\t} else if (!strcmp(arg, \"--first-equal-tree-only\")) {\n+\t\trevs->first_equal_tree_only = 1;\n+\t} else if (!strcmp(arg, \"--all-equal-trees\")) {\n+\t\trevs->first_equal_tree_only = 0;\n \t} else if (!strcmp(arg, \"-g\") || !strcmp(arg, \"--walk-reflogs\")) {\n \t\tinit_reflog_walk(&revs->reflog_info);\n \t} else if (!strcmp(arg, \"--default\")) {\n@@ -1912,6 +1932,16 @@ static void create_boundary_commit_list(struct rev_info *revs)\n \tsort_in_topological_order(&revs->commits, revs->lifo);\n }\n \n+static inline void add_boundary_commit(struct rev_info *revs, struct commit *c) {\n+\tstruct object *p = &c->object;\n+\n+\tif (p->flags & (CHILD_SHOWN | SHOWN))\n+\t\treturn;\n+\tp->flags |= CHILD_SHOWN;\n+\tgc_boundary(&revs->boundary_commits);\n+\tadd_object_array(p, NULL, &revs->boundary_commits);\n+}\n+\n static struct commit *get_revision_internal(struct rev_info *revs)\n {\n \tstruct commit *c = NULL;\n@@ -1987,16 +2017,25 @@ static struct commit *get_revision_internal(struct rev_info *revs)\n \t * 'c', we need to mark its parents that they could be boundaries.\n \t */\n \n-\tfor (l = c->parents; l; l = l->next) {\n-\t\tstruct object *p;\n-\t\tp = &(l->item->object);\n-\t\tif (p->flags & (CHILD_SHOWN | SHOWN))\n-\t\t\tcontinue;\n-\t\tp->flags |= CHILD_SHOWN;\n-\t\tgc_boundary(&revs->boundary_commits);\n-\t\tadd_object_array(p, NULL, &revs->boundary_commits);\n+\tif (revs->first_equal_tree_only && c->parents) {\n+\t\tfor (l = c->parents; l; l = l->next) {\n+\t\t\tstruct commit *p = l->item;\n+\t\t\tparse_commit(p);\n+\t\t\tif (c->tree != p->tree)\n+\t\t\t\tbreak;\n+\t\t}\n+\t\t/* if all parents have the same tree as this node,\n+\t\t * it's an equal tree merge, so ignore all but the\n+\t\t * first parent */\n+\t\tif (!l) {\n+\t\t\tadd_boundary_commit(revs, c->parents->item);\n+\t\t\treturn c;\n+\t\t}\n \t}\n \n+\tfor (l = c->parents; l; l = l->next) {\n+\t\tadd_boundary_commit(revs, l->item);\n+\t}\n \treturn c;\n }\n \ndiff --git a/revision.h b/revision.h\nindex d368003..7ac263c 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -64,6 +64,7 @@ struct rev_info {\n \t\t\treverse_output_stage:1,\n \t\t\tcherry_pick:1,\n \t\t\tbisect:1,\n+\t\t\tfirst_equal_tree_only:1,\n \t\t\tfirst_parent_only:1;\n \n \t/* Diff flags */\n"},{"id":"128774","messageId":"42502278366cca0d87980e538fa2e1a587d7e525.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 3/7] format-patch defaults to --first-equal-tree-only","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:44:34Z","receivedAt":"2009-11-30T14:44:34Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"TODO: manpage update to hint to --all-equal-trees?\n---\n builtin-log.c |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 33fa6ea..a3a2d3f 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.first_equal_tree_only = 1;\n \tDIFF_OPT_SET(&rev.diffopt, RECURSIVE);\n \n \trev.subject_prefix = fmt_patch_subject_prefix;\n"},{"id":"128775","messageId":"84bec3d6f3482d3cd6ef0a8734471deb69f3ff5a.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 4/7] support equal tree merges in interactive rebase","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:44:53Z","receivedAt":"2009-11-30T14:44:53Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"---\n git-rebase--interactive.sh |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 0bd3bf7..3da9f3e 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--first-equal-tree-only \\\n \t\t\t$REVISIONS | \\\n \t\t\tsed -n \"s/^>//p\" | while read shortsha1 rest\n \t\tdo\n"},{"id":"128776","messageId":"f2a9ac5906a9fa963f8d843230a1f419469c8b8e.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 5/7] make rebase -m equal tree marker aware","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:45:13Z","receivedAt":"2009-11-30T14:45:13Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"---\n git-rebase.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex b121f45..391f6d6 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 --first-equal-tree-only --no-merges \"$revisions\"`\n do\n \tmsgnum=$(($msgnum + 1))\n \techo \"$cmt\" > \"$dotest/cmt.$msgnum\"\n"},{"id":"128777","messageId":"07307f70f21343d69765c783dc82215ce52a3432.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 6/7] add support for creating equal tree markers after rebase","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:45:32Z","receivedAt":"2009-11-30T14:45:32Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"With the new --eqt option, git rebase adds an equal tree marker,\nso that the old branch can be fast-forwarded to the new one.\nIf the trees are not equal, a fake merge of the new base and the\nold branch is created first.\n\nTODO:\n - manpage update,\n - should --eqt have a better (longer more descriptive) name?\n - the commit message of the merge should have a better default\n   and presented to the user for editing\n---\n git-rebase.sh |   33 +++++++++++++++++++++++++++++++--\n 1 files changed, 31 insertions(+), 2 deletions(-)\n\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 391f6d6..681c97b 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -50,6 +50,7 @@ diffstat=$(git config --bool rebase.stat)\n git_am_opt=\n rebase_root=\n force_rebase=\n+equal_tree_marker=\n \n continue_merge () {\n \ttest -n \"$prev_head\" || die \"prev_head must be defined\"\n@@ -132,11 +133,30 @@ call_merge () {\n \tesac\n }\n \n+# is there really no already existing function for this?\n+tree_of_commit() {\n+        git cat-file commit \"$1\" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'\n+}\n+\n move_to_original_branch () {\n \ttest -z \"$head_name\" &&\n \t\thead_name=\"$(cat \"$dotest\"/head-name)\" &&\n \t\tonto=\"$(cat \"$dotest\"/onto)\" &&\n-\t\torig_head=\"$(cat \"$dotest\"/orig-head)\"\n+\t\torig_head=\"$(cat \"$dotest\"/orig-head)\" &&\n+\t\tequal_tree_marker=\"$(cat \"$dotest\"/eqt)\"\n+\tif test t = \"$equal_tree_marker\" ; then\n+\t\t# first apply all the changes to the old branch\n+\t\told_tree=$(tree_of_commit \"$orig_head\")\n+\t\tnew_tree=$(tree_of_commit HEAD)\n+\t\tif test \"$old_tree\" = \"$new_tree\" ; then\n+\t\t\told_branch=\"$orig_head\"\n+\t\telse\n+\t\t\t# TODO: better commit message\n+\t\t\told_branch=$(echo \"rebase $head_name onto $onto\" | git-commit-tree $new_tree -p \"$orig_head\" -p \"$onto\" )\n+\t\tfi\n+\t\t# then say the old branch can be upgraded to the new one:\n+\t\tgit equal-tree-marker \"$old_branch\"\n+\tfi\n \tcase \"$head_name\" in\n \trefs/*)\n \t\tmessage=\"rebase finished: $head_name onto $onto\"\n@@ -220,6 +240,7 @@ do\n \t\t\tend=$(cat \"$dotest/end\")\n \t\t\tmsgnum=$(cat \"$dotest/msgnum\")\n \t\t\tonto=$(cat \"$dotest/onto\")\n+\t\t\tequal_tree_marker=$(cat \"$dotest/eqt\")\n \t\t\tGIT_QUIET=$(cat \"$dotest/quiet\")\n \t\t\tcontinue_merge\n \t\t\twhile test \"$msgnum\" -le \"$end\"\n@@ -234,6 +255,7 @@ do\n \t\tonto=$(cat \"$GIT_DIR\"/rebase-apply/onto) &&\n \t\torig_head=$(cat \"$GIT_DIR\"/rebase-apply/orig-head) &&\n \t\tGIT_QUIET=$(cat \"$GIT_DIR\"/rebase-apply/quiet)\n+\t\tequal_tree_marker=$(cat \"$GIT_DIR\"/rebase-apply/eqt)\n \t\tgit am --resolved --3way --resolvemsg=\"$RESOLVEMSG\" &&\n \t\tmove_to_original_branch\n \t\texit\n@@ -251,6 +273,7 @@ do\n \t\t\tmsgnum=$(cat \"$dotest/msgnum\")\n \t\t\tmsgnum=$(($msgnum + 1))\n \t\t\tonto=$(cat \"$dotest/onto\")\n+\t\t\tequal_tree_marker=$(cat \"$dotest/eqt\")\n \t\t\tGIT_QUIET=$(cat \"$dotest/quiet\")\n \t\t\twhile test \"$msgnum\" -le \"$end\"\n \t\t\tdo\n@@ -264,6 +287,7 @@ do\n \t\tonto=$(cat \"$GIT_DIR\"/rebase-apply/onto) &&\n \t\torig_head=$(cat \"$GIT_DIR\"/rebase-apply/orig-head) &&\n \t\tGIT_QUIET=$(cat \"$GIT_DIR\"/rebase-apply/quiet)\n+\t\tequal_tree_marker=$(cat \"$GIT_DIR\"/rebase-apply/eqt)\n \t\tgit am -3 --skip --resolvemsg=\"$RESOLVEMSG\" &&\n \t\tmove_to_original_branch\n \t\texit\n@@ -340,6 +364,9 @@ do\n \t\tgit_am_opt=\"$git_am_opt $1\"\n \t\tforce_rebase=t\n \t\t;;\n+\t--eqt)\n+\t\tequal_tree_marker=t\n+\t\t;;\n \t-C*)\n \t\tgit_am_opt=\"$git_am_opt $1\"\n \t\t;;\n@@ -522,7 +549,8 @@ then\n \t\techo $head_name > \"$GIT_DIR\"/rebase-apply/head-name &&\n \t\techo $onto > \"$GIT_DIR\"/rebase-apply/onto &&\n \t\techo $orig_head > \"$GIT_DIR\"/rebase-apply/orig-head &&\n-\t\techo \"$GIT_QUIET\" > \"$GIT_DIR\"/rebase-apply/quiet\n+\t\techo \"$GIT_QUIET\" > \"$GIT_DIR\"/rebase-apply/quiet &&\n+\t\techo \"$equal_tree_marker\" > \"$GIT_DIR\"/rebase-apply/eqt\n \texit $ret\n fi\n \n@@ -537,6 +565,7 @@ echo \"$prev_head\" > \"$dotest/prev_head\"\n echo \"$orig_head\" > \"$dotest/orig-head\"\n echo \"$head_name\" > \"$dotest/head-name\"\n echo \"$GIT_QUIET\" > \"$dotest/quiet\"\n+echo \"$equal_tree_marker\" > \"$dotest/eqt\"\n \n msgnum=0\n for cmt in `git rev-list --reverse --first-equal-tree-only --no-merges \"$revisions\"`\n"},{"id":"128778","messageId":"9039548d987e1b9be8385c646b2e6e5abf697d09.1259524136.git.brlink@debian.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"[PATCH 7/7] add support for creating equal tree markers to rebase -i","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T14:45:55Z","receivedAt":"2009-11-30T14:45:55Z","isPatch":true,"sender":{"key":"brlink@debian.org","avatar":null},"body":"With the new --eqt option, git rebase -i adds an equal tree marker,\nso that the old branch can be fast-forwarded to the new one.\nIf the trees are not equal, a fake merge of the new base and\nthe old branch is created first.\n\nTODO:\n- manpage update,\n- should --eqt have a better (longer more descriptive) name?\n- the commit message of the merge should have a better default\n  and presented to the user for editing\n---\n git-rebase--interactive.sh |   32 ++++++++++++++++++++++++++++++++\n 1 files changed, 32 insertions(+), 0 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 3da9f3e..51cc5fa 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -20,6 +20,7 @@ v,verbose          display a diffstat of what changed upstream\n onto=              rebase onto given branch instead of upstream\n p,preserve-merges  try to recreate merges instead of ignoring them\n s,strategy=        use the given merge strategy\n+eqt                create an equal tree marker to allow f-f from old tree\n m,merge            always used (no-op)\n i,interactive      always used (no-op)\n  Actions:\n@@ -46,6 +47,7 @@ ONTO=\n VERBOSE=\n OK_TO_SKIP_PRE_REBASE=\n REBASE_ROOT=\n+EQUAL_TREE_MARKER=\n \n GIT_CHERRY_PICK_HELP=\"  After resolving the conflicts,\n mark the corrected paths with 'git add <paths>', and\n@@ -325,6 +327,11 @@ peek_next_command () {\n \tsed -n \"1s/ .*$//p\" < \"$TODO\"\n }\n \n+# is there really no already existing function for this?\n+tree_of_commit() {\n+\tgit cat-file commit \"$1\" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'\n+}\n+\n do_next () {\n \trm -f \"$DOTEST\"/message \"$DOTEST\"/author-script \\\n \t\t\"$DOTEST\"/amend || exit\n@@ -426,6 +433,25 @@ do_next () {\n \tesac\n \ttest -s \"$TODO\" && return\n \n+\tif test t = \"$(cat \"$DOTEST/eqt\")\" ; then\n+\t\tHEADNAME=$(cat \"$DOTEST\"/head-name)\n+\t\tOLDHEAD=$(cat \"$DOTEST\"/head)\n+\t\tONTO=$(cat \"$DOTEST\"/onto)\n+\t\tNEWHEAD=$(git rev-parse HEAD)\n+\t\tOLDTREE=$(tree_of_commit \"$OLDHEAD\")\n+\t\tNEWTREE=$(tree_of_commit HEAD)\n+\t\tif test \"$NEWTREE\" = \"$OLDTREE\" ; then\n+\t\t\tOLDBRANCH=\"$OLDHEAD\"\n+\t\telse\n+\t\t\techo \"Creating commit with differences of '$OLDHEAD' now that is applied to '$ONTO' (tree $NEWTREE)\"\n+\t\t\tOLDBRANCH=\"$( (grep '^# Rebase' \"$TODO\".full \\\n+\t\t\t\t; grep -v '^#' \"$TODO\".full ) \\\n+\t\t\t\t| git-commit-tree \"$NEWTREE\" \\\n+\t\t\t\t-p \"$OLDHEAD\" -p \"$ONTO\")\"\n+\t\tfi\n+\t\tgit equal-tree-marker \"$OLDBRANCH\"\n+\tfi\n+\n \tcomment_for_reflog finish &&\n \tHEADNAME=$(cat \"$DOTEST\"/head-name) &&\n \tOLDHEAD=$(cat \"$DOTEST\"/head) &&\n@@ -605,6 +631,9 @@ first and then run 'git rebase --continue' again.\"\n \t\tONTO=$(git rev-parse --verify \"$1\") ||\n \t\t\tdie \"Does not point to a valid commit: $1\"\n \t\t;;\n+\t--eqt)\n+\t\tEQUAL_TREE_MARKER=t\n+\t\t;;\n \t--)\n \t\tshift\n \t\ttest -z \"$REBASE_ROOT\" -a $# -ge 1 -a $# -le 2 ||\n@@ -656,6 +685,7 @@ first and then run 'git rebase --continue' again.\"\n \t\t\t: >\"$DOTEST\"/rebase-root ;;\n \t\tesac\n \t\techo $ONTO > \"$DOTEST\"/onto\n+\t\techo \"$EQUAL_TREE_MARKER\" > \"$DOTEST\"/eqt\n \t\ttest -z \"$STRATEGY\" || echo \"$STRATEGY\" > \"$DOTEST\"/strategy\n \t\ttest t = \"$VERBOSE\" && : > \"$DOTEST\"/verbose\n \t\tif test t = \"$PRESERVE_MERGES\"\n@@ -787,6 +817,8 @@ EOF\n \n \t\ttest -d \"$REWRITTEN\" || skip_unnecessary_picks\n \n+\t\tcp \"$TODO\" \"$TODO\".full\n+\n \t\tgit update-ref ORIG_HEAD $HEAD\n \t\toutput git checkout $ONTO && do_rest\n \t\t;;\n"},{"id":"128779","messageId":"fabb9a1e0911300710t33ddfb94wb2b8c1d23a8f5ac2@mail.gmail.com","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-11-30T15:10:19Z","receivedAt":"2009-11-30T15:10:19Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Mon, Nov 30, 2009 at 15:43, Bernhard R. Link <brlink@debian.org> wrote:\n> Those patches are a bit rough and mostly intended to show how it could work\n> and to allow experimenting with it.\n\nGiven the experimental nature of your patches it would probably have\nbeen appropriate to mark them \"RFC\" (request for comment). You can do\nso by running: `git format-patch --subject-prefix=\"RFC PATCH\"` instead\nof \"git format-patch\".\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"128780","messageId":"hf0oh0$elj$1@ger.gmane.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2009-11-30T15:31:44Z","receivedAt":"2009-11-30T15:31:44Z","isPatch":false,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"On 11/30/2009 03:43 PM, Bernhard R. Link wrote:\n> The itch this idea is supposed to scratch is the problem that a rebase\n> or a amended commit is no longer a fast-forward, so cannot be easily\n> pulled.\n\nHow does this compare with topgit?\n\nPaolo\n"},{"id":"128781","messageId":"4B13E65D.3050504@drmicha.warpmail.net","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-11-30T15:35:57Z","receivedAt":"2009-11-30T15:35:57Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:\n> The itch this idea is supposed to scratch is the problem that a rebase\n> or a amended commit is no longer a fast-forward, so cannot be easily\n> pulled.\n\nDo you mean pushed?\nFor pull, the state of the branch on the receiving side play a role, of\ncourse.\n\n> While this is not a problem in most workflows, as one can either merge\n> or keep everything private and rebase until published, it would be nice\n> to have a way for cases in between, where both a clean presentable\n> commit order is to be maintained and people (or yourself from different\n> repositories) should be able to easily upgrade to newer versions without\n> an error-prone not-fast-forward.\n> \n> My idea to solve this is combining both histories, the rebased/revised\n> history and the actualy history, marking with some \"equal-tree-merge\"\n> the point where they have the same result.\n> The following mails show some patches to implement this by means of\n> a merge where all parents have the same tree and some special casing\n> when encountering such a thing. This has the advantage that older git\n> version will just see strange merges and may present both histories,\n> but otherwise just work.\n\nWithout having the time to go through the detailed setup you described\nbelow (sorry), I'm wondering how this differs from what Git calls a\ntrivial merge? Is it merely about asserting that you merge coinciding\n(heads with) trees?\n\nMichael\n"},{"id":"128782","messageId":"4B13E67C.4050005@drmicha.warpmail.net","threadId":"21797","inReplyTo":"9e6833ef7188f41d6ea46ddcf92929af284b4adb.1259524136.git.brlink@debian.org","subject":"Re: [PATCH 1/7] add new command git equal-tree-marker","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-11-30T15:36:28Z","receivedAt":"2009-11-30T15:36:28Z","isPatch":true,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:\n> This adds a new commit denoting tha current branch has the same\n> tree as another branch, thus allowing fast-forward from the named\n> commits to this one.\n> \n> TODO: manpage, rewrite as builtin once the semantics are accepted?\n> ---\n>  .gitignore               |    1 +\n>  Makefile                 |    1 +\n>  git-equal-tree-marker.sh |   50 ++++++++++++++++++++++++++++++++++++++++++++++\n>  3 files changed, 52 insertions(+), 0 deletions(-)\n>  create mode 100644 git-equal-tree-marker.sh\n> \n> diff --git a/.gitignore b/.gitignore\n> index ac02a58..248d146 100644\n> --- a/.gitignore\n> +++ b/.gitignore\n> @@ -39,6 +39,7 @@\n>  /git-difftool\n>  /git-difftool--helper\n>  /git-describe\n> +/git-equal-tree-marker\n>  /git-fast-export\n>  /git-fast-import\n>  /git-fetch\n> diff --git a/Makefile b/Makefile\n> index 4dba10e..913d4c4 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -336,6 +336,7 @@ TEST_PROGRAMS =\n>  SCRIPT_SH += git-am.sh\n>  SCRIPT_SH += git-bisect.sh\n>  SCRIPT_SH += git-difftool--helper.sh\n> +SCRIPT_SH += git-equal-tree-marker.sh\n>  SCRIPT_SH += git-filter-branch.sh\n>  SCRIPT_SH += git-lost-found.sh\n>  SCRIPT_SH += git-merge-octopus.sh\n> diff --git a/git-equal-tree-marker.sh b/git-equal-tree-marker.sh\n> new file mode 100644\n> index 0000000..403cc56\n> --- /dev/null\n> +++ b/git-equal-tree-marker.sh\n> @@ -0,0 +1,50 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2009 Bernhard R. Link\n> +#\n> +# Create a new commit making HEAD parent of the arguments,\n> +# which must be commits with the same tree.\n> +\n> +set -e\n> +\n> +USAGE='<head>...'\n> +LONG_USAGE='Make current HEAD parent of the given heads (which need to have the same tree).'\n> +SUBDIRECTORY_OK=Yes\n> +OPTIONS_SPEC=\n> +. git-sh-setup\n> +cd_to_toplevel\n> +\n> +# is there really no function for this?\n> +tree_of_commit() {\n> +\tgit cat-file commit \"$1\" | grep '^tree ' | head -n 1 | sed -e 's/^tree //'\n> +}\n\nYou mean there should be something really simple, such as:\n\ngit rev-parse \"$1\"^{tree}\n\nMichael\n"},{"id":"128784","messageId":"4B13EBD6.5060608@drmicha.warpmail.net","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2009-11-30T15:59:18Z","receivedAt":"2009-11-30T15:59:18Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:\n[...]\n\nOk, I couldn't resist looking at your examples. Actually, before\nanything else: Thanking for describing *what* you want to achieve, not\nonly how.\n\n> Example 1:\n> \n> Let's assume you maintain such a regularily-rebased branch that you\n> want to be able to publish (or pull from other repositories for example\n> on your laptop):\n> \n> o=m=o=o=master\n>    \\\n>     a=b=c=d=e=feature\n> \n> with this patch you can do \"git rebase -eqt master\" and get:\n> \n>               a'=b'=c'=d'=e'=feature'=eqt\n>              /                       /\n> o=m=o=o=master--------              /\n>    \\                  \\            /\n>     a=b=c=d=e=feature--merge-------\n> \n\ngit checkout -b featureprime feature\ngit rebase master\ngit merge feature # should be trivial\ngit branch -M featureprime feature\n\n> i.e: the new feature branch has both histories:\n>   - \"feature'\" where everything is cleanly rebased and in a form where\n>                format-patch is suitable to send it upstream\n>   - \"merge\" which is both a descendant from feature (so one can see what\n>     changed since that time and can just pull when one had had cloned feature)\n> \n> Example 2:\n> \n> Let's assume you have a feature branch like\n> \n> o=master\n>    \\\n>     a=b=c=d=e=f\n> \n> Assume you just commited \"f\" which fixes a bug introduced by \"b\".\n> Now you of course do not want to send it that way upstream (as it will\n> make reviewing harder, may force people bisecting to skip some versions\n> every time they hit this region and so on), so you want to\n> bisect -i and squash \"f\" into \"b\".\n> \n> o=master\n>    \\\n>     a=b+f=c'=d'=e'\n> \n> But if you had already cloned at state \"d\" to your laptop (or made a backup\n> of that branch at some server, or published it for use of some collegues)\n> it will not be a fast-forward, so you have to be very carefull to not\n> accidentially lose a commit that is already there.\n> \n> So with this patches you can do \"git rebase -i --eqt\" and squash f into b\n> and get:\n> \n> o=master\n>    \\\n>     a=b=c=d=e=f---\n>      \\            \\\n>       b+f=c'=d'=e'=eqt\n> \n> which means that you can just pull from your laptop and get the new head\n> as fast-forward, but still have a proper history ready for submitting.\n\nIf that side branch is named \"feature\":\ngit checkout -b fixup feature\ngit rebase -i a # squash f into b; creates b+f c# d' e'\ngit merge feature # should be trivial\ngit branch -M fixup feature\n\nYou can also go crazy with rebase --onto here, or use cherry-pick\nrepeatedly.\n\nNote that I always use a temporary branch for rewriting, before renaming\nit to the proper branch name. I haven't checked, but I assume the\n\"first-parents\" are the way you want them (you want log --first-parent\n--no-merges to show the rewritten commits, right?); otherwise you would\nhave to do the merges the other way round.\n\nCheers,\nMichael\n"},{"id":"128785","messageId":"20091130162229.GA3792@pcpool00.mathematik.uni-freiburg.de","threadId":"21797","inReplyTo":"hf0oh0$elj$1@ger.gmane.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T16:22:29Z","receivedAt":"2009-11-30T16:22:29Z","isPatch":false,"sender":{"key":"brlink@debian.org","avatar":null},"body":"* Paolo Bonzini <bonzini@gnu.org> [091130 16:32]:\n> On 11/30/2009 03:43 PM, Bernhard R. Link wrote:\n>> The itch this idea is supposed to scratch is the problem that a rebase\n>> or a amended commit is no longer a fast-forward, so cannot be easily\n>> pulled.\n>\n> How does this compare with topgit?\n\nIt's not easily compareable as having different aims, but I think there\nare some use-cases where this allows native usage of git where\npreviously the best bet was topgit.\n\nAssume for example you want to maintain a set of patches of some\nupstream, which you want to have in some form relative to upstream\nand in patches easily reviewable and pickable by other people.\n\nYou could do that with topgit by making each change a topgit branch.\nBut to clone that repository then you would need topgit to get all\nthe information and cherry picking one of your changes (that perhaps\ngrow with the time, was adapted to new upstreams and had bugs fixed)\nneeds telling topgit to combine the changes of that branch and use that\ninstead of a simple cherry pick.\n\nWith this equal-tree-marker you can just do a git rebase --eqt or git\nrebase -i --eqt and both have a history with your changes as single\ncommits which are easy to look at (and you can just pushing head^1\nsomewhere for upstream to pull from) while still having all the history\nin your git archive so someone else can look what actually happened or\njust clone your current head and repeatenly pull from it.\n\nHochachtungsvoll,\n\tBernhard R. Link\n"},{"id":"128787","messageId":"20091130165437.GB3792@pcpool00.mathematik.uni-freiburg.de","threadId":"21797","inReplyTo":"4B13EBD6.5060608@drmicha.warpmail.net","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T16:54:37Z","receivedAt":"2009-11-30T16:54:37Z","isPatch":false,"sender":{"key":"brlink@debian.org","avatar":null},"body":"* Michael J Gruber <git@drmicha.warpmail.net> [091130 17:00]:\n> Bernhard R. Link venit, vidit, dixit 30.11.2009 15:43:\n> > o=m=o=o=master\n> >    \\\n> >     a=b=c=d=e=feature\n> >\n> > with this patch you can do \"git rebase -eqt master\" and get:\n> >\n>\n> git checkout -b featureprime feature\n> git rebase master\n> git merge feature # should be trivial\n> git branch -M featureprime feature\n\n> [...]\n\n> Note that I always use a temporary branch for rewriting, before renaming\n> it to the proper branch name. I haven't checked, but I assume the\n> \"first-parents\" are the way you want them (you want log --first-parent\n> --no-merges to show the rewritten commits, right?); otherwise you would\n> have to do the merges the other way round.\n\nMy problem with that is that --first-parent-only makes no difference\nbetween this and other merges.\n\nAssume the example2\n\no=master\n   \\\n    a=b=c=d=e=f---\n     \\            \\\n      b+f=c'=d'=e'=eqt\n\nwould continue with some paralel commits and a merge:\n\no=master\n   \\\n    a=b=c=d=e=f---       y\n     \\            \\     / \\\n      b+f=c'=d'=e'=eqt-x   m\n                        \\ /\n                         z\n\nnow if you rebase that tree (or want to send it with format-patch),\nyou either get the old commits multiple times in format-patch\n(and possibly causing already resolved conflicts when doing the am\nstep in rebase), or you use --first-parent-only and might miss z.\n\nThus the idea to have some way to destinguish this merge from a normal\nmerge and thus the extra pseudo-merge in example 1 to get the following\nmerge to merge things with equal tree.\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":"128788","messageId":"alpine.DEB.1.00.0911301815390.4985@pacific.mpi-cbg.de","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-11-30T17:19:31Z","receivedAt":"2009-11-30T17:19:31Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 30 Nov 2009, Bernhard R. Link wrote:\n\n> The itch this idea is supposed to scratch is the problem that a rebase \n> or a amended commit is no longer a fast-forward, so cannot be easily \n> pulled.\n\nActually, I did something like this without any new tool:\n\n\tgit rebase origin/master\n\tgit merge -s ours master@{1}\n\nThe effect is that there is a merge commit which really merges the old \nstate.\n\nOTOH I can see that there is merit in trying to avoid to _require_ the \nwhole history of the rebased branch.  But then, would it not be more in \nline with Git's ideas if there was a tool trying to identify, say, \nfrom the commit message which commits in HEAD...MERGE_HEAD are \nsupposed to be identical?\n\nCiao,\nDscho\n"},{"id":"128795","messageId":"7v8wdnooza.fsf@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-11-30T18:18:49Z","receivedAt":"2009-11-30T18:18:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Bernhard R. Link\" <brlink@debian.org> writes:\n\n> My idea to solve this is combining both histories, the rebased/revised\n> history and the actualy history, marking with some \"equal-tree-merge\"\n> the point where they have the same result.\n\nIf you rewrite a series twice, your RFC will work like this, IIUC:\n\n * You have commit 1 and rewrite it to 2.  You record the difference\n   between 1 and 2 on top of 1 as commit X and record a same-tree merge as\n   A.  Here, A^1 == 2, A^2 == X, and 2^{tree} == A^{tree}.\n\n       2-------A\n      /       /\n     0---1---X\n\n * You then rewrite it to 3.  You record the difference between A and 3\n   (which is the same as between 2 and 3, because 2^{tree} == A^{tree})\n   as commit Y, and record a same-tree merge as B.  B^1 == 3, B^2 == Y and\n   3^{tree} == B^{tree}.\n\n         Y---------------B\n        /               /\n       2-------A-------3\n      /       /\n     0---1---X\n\nIt however might be easier to review what happened if you create a history\nthis way upon the second rewrite (forget the second picture above):\n\n       3-------.\n      /         \\\n     0---2---W---B\n      \\         /\n       1-------Z\n\nThat is, Z and W records the interdifff between 1 to 3 and 2 to 3\nrespectively, and B is a same-tree merge of 3, W and Z.\n\nAs you are giving some specific meaning to the order of merge parents of a\nmarker commit, namely, the first parent is the latest version of this\nseries (i.e. B^1 == 3), you can extend it to declare that the second\nparent is the next to the latest incarnation (i.e. B^2 == W) and the third\none is one version older than the second one (i.e. B^3 == Z).\n\nDoing it this way allows you to publish the final result \"3\" without any\ncruft in the history.\n\nIn your code you have comment wondering if there is a better wording for\nthe fix-up commit you create during rebase when the trees do not match.  I\nwould suggest calling it \"interdiff\".  That is exactly what \"git show W\"\nwould show.\n\nWhile I find the primary idea (i.e. keeping the old and new equivalents by\nrecording a merge of it, and using the first-parent to traverse when you\nfind such a special merge) reasonable (and as Dscho has pointed out, this\ntechnique is widely used, I suspect---it is an obvious thing to do), I\nthink we need something stronger than just \"this commit merges commits\nthat happen to have the same trees\" as the marker.\n\nGit is designed to work well in an environment where multiple people\nproduces identical result.  A 3-way merge resolves cleanly when both\nbranches modified a path to the same result (at contents level as well at\npath level).  If you take this principle to the extreme, you should be\nable to merge two branches that were developed independently but still\nreached the same conclusion at the end, without marking such a merge as\nanything funny.  With your RFC code, one branch will be mistakenly treated\nas \"old cruft that was improved by the other branch by rewriting\".\n\nTo avoid that, I think (1) the marker has to be more reliable than just\n\"happens to have the same tree\", and (2) the traversal done by Porcelains\n(your patches 3 thru 5) by default should be unaware of eqt.\n\nI don't know what a suitable marker should look like, though.  The marker\nmust be easily identifiable by the lowest level rev-list machinery, so it\nneeds to be a sign left somewhere in the commit object.  Perhaps making it\nrequire to have the same tree as all its parents _and_ a well-known marker\nstring in the log message (and nothing else) would be a good start.\n\nIn the longer term, if the line of this direction turns out to be a good\none, I do not mind adding a special header to the commit object separate\nfrom the log message, but we should start without one until this proves to\nbe a useful ingredient in people's workflows.  With a reliable marker, we\ncan obviously drop the \"same-tree\" ness from the definition of the marker\ncommit, which in turn means that you do not need \"interdiff\" commits while\nrebasing.\n\nThe command to build such a merge could be an option to \"git merge -s ours\"\n(perhaps something like \"git merge -s ours -Xeqt\").\n"},{"id":"128797","messageId":"20091130185540.GA5764@pcpool00.mathematik.uni-freiburg.de","threadId":"21797","inReplyTo":"7v8wdnooza.fsf@alter.siamese.dyndns.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Bernhard R. Link","fromEmail":"brlink@debian.org","sentAt":"2009-11-30T18:55:40Z","receivedAt":"2009-11-30T18:55:40Z","isPatch":false,"sender":{"key":"brlink@debian.org","avatar":null},"body":"* Junio C Hamano <gitster@pobox.com> [091130 19:19]:\n> \"Bernhard R. Link\" <brlink@debian.org> writes:\n> \n> > My idea to solve this is combining both histories, the rebased/revised\n> > history and the actualy history, marking with some \"equal-tree-merge\"\n> > the point where they have the same result.\n> \n> If you rewrite a series twice, your RFC will work like this, IIUC:\n> \n>  * You have commit 1 and rewrite it to 2.  You record the difference\n>    between 1 and 2 on top of 1 as commit X and record a same-tree merge as\n>    A.  Here, A^1 == 2, A^2 == X, and 2^{tree} == A^{tree}.\n> \n>        2-------A\n>       /       /\n>      0---1---X\n> \n>  * You then rewrite it to 3.  You record the difference between A and 3\n>    (which is the same as between 2 and 3, because 2^{tree} == A^{tree})\n>    as commit Y, and record a same-tree merge as B.  B^1 == 3, B^2 == Y and\n>    3^{tree} == B^{tree}.\n> \n>          Y---------------B\n>         /               /\n>        2-------A-------3\n>       /       /\n>      0---1---X\n\nI think it rather looks like this:\n\n     3---------------B\n     |              /\n     | 2-------A---Y\n     |/       /\n     0---1---X\n\n>\n>        3-------.\n>       /         \\\n>      0---2---W---B\n>       \\         /\n>        1-------Z\n>\n> That is, Z and W records the interdifff between 1 to 3 and 2 to 3\n> respectively, and B is a same-tree merge of 3, W and Z.\n\nI think changing it to get this would be easy (though only in the case\nwhere the very last commit was such an equal tree merge), but I do not\nthink it would be actually better:\n\n- it is no longer possible to see the history of changes by just walking\n  right on every equal-tree-merge.\n- commit a no longer exists. If some downstream already has\n  cloned/pulled, no fast-forward is possible any more.\n\n> While I find the primary idea (i.e. keeping the old and new equivalents by\n> recording a merge of it, and using the first-parent to traverse when you\n> find such a special merge) reasonable (and as Dscho has pointed out, this\n> technique is widely used, I suspect---it is an obvious thing to do), I\n> think we need something stronger than just \"this commit merges commits\n> that happen to have the same trees\" as the marker.\n\nI've considered adding a new header or only a magic description text for those\ncommits, but I think it is not necessary.\nBecause the actual programs making it useful to treat this special\n(format-patch producing too many patches, rebases possibly showing conflicts\nalready resolved and bisect walking too many branches) will be the same when\ntwo branches only resulting in the same tree by pure chance show up.\n\n> To avoid that, I think (1) the marker has to be more reliable than just\n> \"happens to have the same tree\", and (2) the traversal done by Porcelains\n> (your patches 3 thru 5) by default should be unaware of eqt.\n\nI think for patch 3 (format-patch) and 4 (rebase -i) it is always better to\nhave the new behaviour even when only hitting equal trees by chance.\nI'm unsure about 5 (rebase -m), but guess it still is.\n\n> I don't know what a suitable marker should look like, though.  The marker\n> must be easily identifiable by the lowest level rev-list machinery, so it\n> needs to be a sign left somewhere in the commit object.  Perhaps making it\n> require to have the same tree as all its parents _and_ a well-known marker\n> string in the log message (and nothing else) would be a good start.\n\nIt already does always create a unique log message. So one could also\nhave one more strict and one less strict mode (and some option to decide\non the default).\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":"128800","messageId":"200911302026.53933.j6t@kdbg.org","threadId":"21797","inReplyTo":"7v8wdnooza.fsf@alter.siamese.dyndns.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2009-11-30T19:26:53Z","receivedAt":"2009-11-30T19:26:53Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Montag, 30. November 2009, Junio C Hamano wrote:\n> To avoid that, I think (1) the marker has to be more reliable than just\n> \"happens to have the same tree\", and (2) the traversal done by Porcelains\n> (your patches 3 thru 5) by default should be unaware of eqt.\n>\n> I don't know what a suitable marker should look like, though.  The marker\n> must be easily identifiable by the lowest level rev-list machinery, so it\n> needs to be a sign left somewhere in the commit object.\n\nWouldn't the pathspec . be the marker:\n\n    git rev-list HEAD -- .\n\nfollows only one of the branches that have identical trees.\n\n-- Hannes\n"},{"id":"128805","messageId":"7viqcrkb3e.fsf@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"200911302026.53933.j6t@kdbg.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-11-30T20:32:21Z","receivedAt":"2009-11-30T20:32:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j6t@kdbg.org> writes:\n\n> On Montag, 30. November 2009, Junio C Hamano wrote:\n>> To avoid that, I think (1) the marker has to be more reliable than just\n>> \"happens to have the same tree\", and (2) the traversal done by Porcelains\n>> (your patches 3 thru 5) by default should be unaware of eqt.\n>>\n>> I don't know what a suitable marker should look like, though.  The marker\n>> must be easily identifiable by the lowest level rev-list machinery, so it\n>> needs to be a sign left somewhere in the commit object.\n>\n> Wouldn't the pathspec . be the marker:\n>\n>     git rev-list HEAD -- .\n>\n> follows only one of the branches that have identical trees.\n\nBecause I am saying that \"this commit has two parents and they record the\nidentical trees\" is a condition that is too weak to mark a special-purpose\nmerge to bind the latest and an earlier version of a series, your rev-list\nexample command line should not be the way to identify such a mark commit\nand act differently upon seeing one.\n\nActually your command line is even weaker, I think, although it would not\nmake much difference in real-life.  The marker as currently Bernhard\nimplements not only has parents with identical trees, but the tree it has\nalso matches those of its parents.\n\nYou can make a commit that merges two branches that independently reached\nthe same conclusion (which git is designed to handle as an ordinary event\nin real life), and amend that commit into an evil merge that has different\ncontents from its parents (which, I suspect, does not have much use in\npractice), and your rev-list will drop one of the branches for even such a\ncommit, mistaking it as a marker when it is clearly not one.\n\nMy \"it would not make much difference in real-life\" in the two paragraphs\nabove comes purely from \"such an evil merge would not have much use in\npractice\".  We should make sure that \"two branches that reached the same\nconclusion\" is not mistaken with a marker this series introduces.\n"},{"id":"128813","messageId":"20091201071234.6117@nanako3.lavabit.com","threadId":"21797","inReplyTo":"7v8wdnooza.fsf@alter.siamese.dyndns.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2009-11-30T22:12:34Z","receivedAt":"2009-11-30T22:12:34Z","isPatch":false,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting Junio C Hamano <gitster@pobox.com>\n\n> To avoid that, I think (1) the marker has to be more reliable than just\n> \"happens to have the same tree\", and (2) the traversal done by Porcelains\n> (your patches 3 thru 5) by default should be unaware of eqt.\n>\n> I don't know what a suitable marker should look like, though.  The marker\n> must be easily identifiable by the lowest level rev-list machinery, so it\n> needs to be a sign left somewhere in the commit object.  Perhaps making it\n> require to have the same tree as all its parents _and_ a well-known marker\n> string in the log message (and nothing else) would be a good start.\n\nI think you can record a merge commit that has an unusual \nlist of parents for this. For example, you can record the \nlatest version twice, as the first and the second parents, \nand make the previous version the third parent. Because \nsuch a merge can't be created with git-merge command, you \ncan reliably tell that it is an unusual 'marker' merge.\n\nNo matter what techinique is used to mark the special \n'marker', if it happens in real life for two or more people \nwho worked independantly to arrive at the same conclusion, \nI don't think dismissing it as 'by chance' and discarding \nthe contribution from the second branch is a good solution. \nIf git is meant to work smoothly in projects where more than \none person see and accept patches from the same origin, the \ncondition is not met 'by chance'; the tool is by design \nsupposed to handle it as a regular situation.\n\nOn the other hand, if you made the marker reliable, I think \nyou don't have to disable this feature by default like you \nsaid in your (2).\n\nAs a side note, I have a bug to report. I tried this sequence \nof commands to make sure git-merge doesn't record the same \nparent twice (the last git-merge is made on the slave branch \nand tries to have slave, master and slave as its three \nparents).\n\n % git init\n % echo hello >world\n % git add . ; git commit -m first\n % echo again >world\n % git commit -a -m master\n % git checkout -b slave master^\n % echo again >world\n % git commit -a -m slave\n % git merge master slave\n\nBut I got the \"usage: ...\" error message from git-merge.\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"128822","messageId":"7vmy23bl4o.fsf@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"20091201071234.6117@nanako3.lavabit.com","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-01T00:20:23Z","receivedAt":"2009-12-01T00:20:23Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nanako Shiraishi <nanako3@lavabit.com> writes:\n\n> I think you can record a merge commit that has an unusual \n> list of parents for this. For example, you can record the \n> latest version twice, as the first and the second parents, \n> and make the previous version the third parent. Because \n> such a merge can't be created with git-merge command, you \n> can reliably tell that it is an unusual 'marker' merge.\n\nThat's too ugly a hack, and hints an undesirable attitude that this will\nbe the last feature that needs such cleverness, without leaving the door\nopen for others who need similar \"magic marker\" capability added to commit\nobjects.  The approach will not scale, unless you consider \"first and\nsecond parents being the same means it is 'rebased branches magic', and\nfirst, second and third parents being the same means some other matic, \netc.\" as scalable.\n\nAs I said, if the approach this series takes turns out to be useful, it is\nOk to implement it as a new header in the commit object if necessary.\n\nWe try very hard to avoid adding random headers to commits because a\ncommit that records the same history should be named the same way in the\nobject store namespace and adding random headers will make it easier to\ncreate the same commit with different names, but what we are discussing\nis a special purpose pseudo commit and it _is_ a feature that the object\nname of a commit, after SHA-1 hashing, is different with and without the\nspecial header in this case.\n\n> No matter what techinique is used to mark the special \n> 'marker', if it happens in real life for two or more people \n> who worked independantly to arrive at the same conclusion, \n> I don't think dismissing it as 'by chance' and discarding \n> the contribution from the second branch is a good solution. \n> If git is meant to work smoothly in projects where more than \n> one person see and accept patches from the same origin, the \n> condition is not met 'by chance'; the tool is by design \n> supposed to handle it as a regular situation.\n\nI said the same thing, and I agree that two (or more) people creating the\nsame state should be treated as a normal event.  But I am not so sure\nabout a merge that binds two such histories together.  The person who\nmakes such a merge can go on without making one as far as tree-state is\nconcerned (i.e. such a merge will result in the same tree with both\nparents), and the _only_ reason a merge between the two branches is\ncreated is to cauterize one (or both) of the branches, declare that\neverything that happened in the branch is now part of this branch.\nIn other words, such a merge is an operation to purely affect the history\nand not contents.\n\nAs J6t pointed out, when we tell the revision walking machinery to limit\nby path, we already simplify the history we show to the user, and if path\nhappens to name the whole tree, such a history is already simplified to\nshow only one side of the story.  So perhaps it is not as grave an offence\nto ignore contribution from one side when both of the parents of a merge\nrecord the same tree as I originally thought.  It also justifies not\nintroducing a new header in commits.  The implementation of Bernhard's\nseries might become simpler if it used the trick to use \".\" pathspec\ninternally instead of introducing a new traversal option to the revision\nmachinery.\n\n> On the other hand, if you made the marker reliable, I think \n> you don't have to disable this feature by default like you \n> said in your (2).\n\nThat is true, but as you may be able to tell, I am undecided if the marker\nshould be _that_ explicit, or should be implicit and the fact that a merge\nthat whose all parents have the same tree should make it automatically a\nmarker (iow, I earlier said \"misidentify\" but now I am wondering if it\nmakes sense to define any merge with the property an \"alternative history\nbinding marker\", no matter how it was created).\n\n> As a side note, I have a bug to report. I tried this sequence \n> of commands to make sure git-merge doesn't record the same \n> parent twice (the last git-merge is made on the slave branch \n> and tries to have slave, master and slave as its three \n> parents).\n>\n>  % git init\n>  % echo hello >world\n>  % git add . ; git commit -m first\n>  % echo again >world\n>  % git commit -a -m master\n>  % git checkout -b slave master^\n>  % echo again >world\n>  % git commit -a -m slave\n>  % git merge master slave\n>\n> But I got the \"usage: ...\" error message from git-merge.\n\nWell, you did not quote the usage string you got, but it should have began\nlike this:\n\n    usage: git merge [options] <remote>...\n       or: git merge [options] <msg> HEAD <remote>\n\nThe parser misinterpreted your request as the latter form (which is\nancient and probably predates your involvement with the git project),\nnoticed that you did not give any <remote> commit, and then gave the\nusage message.\n\nI think we really should start deprecating the ancient form, but the\noriginal sample script using this syntax from Linus was copied by many\npeople and are still found everywhere, I think, and people may still\nuse their scripts that were written with the ancient syntax.\n\nIn any case, at least this patch will make it start behaving a bit\nmore sanely.\n\n-- >8 --\nSubject: Do not misidentify \"git merge foo HEAD\" as an old-style invocation\n\nThis was misinterpreted as an ancient style \"git merge <message> HEAD\n<commit> <commit>...\" that merges one (or more) <commit> into the current\nbranch and record the resulting commit with the given message.  Then a\nlater sanity check found that there is no <commit> specified and gave\na usage message.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex e95c5dc..e5cf795 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -792,7 +792,7 @@ static int suggest_conflicts(void)\n static struct commit *is_old_style_invocation(int argc, const char **argv)\n {\n \tstruct commit *second_token = NULL;\n-\tif (argc > 1) {\n+\tif (argc > 2) {\n \t\tunsigned char second_sha1[20];\n \n \t\tif (get_sha1(argv[1], second_sha1))\n"},{"id":"128824","messageId":"7vaay3bkyx.fsf_-_@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"7vmy23bl4o.fsf@alter.siamese.dyndns.org","subject":"[PATCH] git-merge: a deprecation notice of the ancient command line syntax","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-01T00:23:50Z","receivedAt":"2009-12-01T00:23:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The ancient form of git merge command used in the original sample script\nhas been copied from Linus and are still found everywhere, I think, and\npeople may still have it in their scripts, but on the other hand, it is so\nunintuitive that even people reasonably familiar with git is surprised by\naccidentally triggering the support to parse this ancient form.\n\nGently nudge people to upgrade their script to more recent and readable\nstyle for eventual removal of the original syntax.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n    And this is the first step of such a deprecation.  Perhaps we start\n    warning in 1.7.0 and remove it in 1.8.0, or something like that.\n\n builtin-merge.c |    5 +++++\n 1 files changed, 5 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex e5cf795..4cb695e 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -789,6 +789,11 @@ static int suggest_conflicts(void)\n \treturn 1;\n }\n \n+static const char deprecation_warning[] =\n+\t\"'git merge <msg> HEAD <commit>' is deprecated. Please update\\n\"\n+\t\"your script to use 'git merge -m <msg> <commit>' instead.\\n\"\n+\t\"In future versions of git, this syntax will be removed.\";\n+\n static struct commit *is_old_style_invocation(int argc, const char **argv)\n {\n \tstruct commit *second_token = NULL;\n@@ -802,6 +806,7 @@ static struct commit *is_old_style_invocation(int argc, const char **argv)\n \t\t\tdie(\"'%s' is not a commit\", argv[1]);\n \t\tif (hashcmp(second_token->object.sha1, head))\n \t\t\treturn NULL;\n+\t\twarning(deprecation_warning);\n \t}\n \treturn second_token;\n }\n"},{"id":"128826","messageId":"7vtywba6bj.fsf@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"20091130185540.GA5764@pcpool00.mathematik.uni-freiburg.de","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-01T00:25:36Z","receivedAt":"2009-12-01T00:25:36Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Bernhard R. Link\" <brlink@debian.org> writes:\n\n>>        3-------.\n>>       /         \\\n>>      0---2---W---B\n>>       \\         /\n>>        1-------Z\n>>\n>> That is, Z and W records the interdifff between 1 to 3 and 2 to 3\n>> respectively, and B is a same-tree merge of 3, W and Z.\n>\n> I think changing it to get this would be easy (though only in the case\n> where the very last commit was such an equal tree merge), but I do not\n> think it would be actually better:\n>\n> - it is no longer possible to see the history of changes by just walking\n>   right on every equal-tree-merge.\n> - commit a no longer exists. If some downstream already has\n>   cloned/pulled, no fast-forward is possible any more.\n\nOh, I wasn't suggesting you to change it to use an octopus.  I however did\nwant to know if you considered pros-and-cons with such an alternative\n(there perhaps are other approaches as well), and I agree recording one\niteration at a time like you do is better.\n"},{"id":"128830","messageId":"alpine.LFD.2.00.0911302251270.5820@xanadu.home","threadId":"21797","inReplyTo":"7vaay3bkyx.fsf_-_@alter.siamese.dyndns.org","subject":"Re: [PATCH] git-merge: a deprecation notice of the ancient command line syntax","fromName":"Nicolas Pitre","fromEmail":"nico@fluxnic.net","sentAt":"2009-12-01T03:55:58Z","receivedAt":"2009-12-01T03:55:58Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Mon, 30 Nov 2009, Junio C Hamano wrote:\n\n> The ancient form of git merge command used in the original sample script\n> has been copied from Linus and are still found everywhere, I think, and\n> people may still have it in their scripts, but on the other hand, it is so\n> unintuitive that even people reasonably familiar with git is surprised by\n> accidentally triggering the support to parse this ancient form.\n> \n> Gently nudge people to upgrade their script to more recent and readable\n> style for eventual removal of the original syntax.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> \n>     And this is the first step of such a deprecation.  Perhaps we start\n>     warning in 1.7.0 and remove it in 1.8.0, or something like that.\n\nIf this is going to be removed in the future, then it is already \ndeprecated.  Therefore it is much better to start warning now and not \nwait for 1.7.0.  There is just no point delaying the advice.\n\n\nNicolas\n"},{"id":"128831","messageId":"7viqcr72wz.fsf@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"alpine.LFD.2.00.0911302251270.5820@xanadu.home","subject":"Re: [PATCH] git-merge: a deprecation notice of the ancient command line syntax","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-01T04:07:24Z","receivedAt":"2009-12-01T04:07:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nicolas Pitre <nico@fluxnic.net> writes:\n\n> On Mon, 30 Nov 2009, Junio C Hamano wrote:\n>\n>> The ancient form of git merge command used in the original sample script\n>> has been copied from Linus and are still found everywhere, I think, and\n>> people may still have it in their scripts, but on the other hand, it is so\n>> unintuitive that even people reasonably familiar with git is surprised by\n>> accidentally triggering the support to parse this ancient form.\n>> \n>> Gently nudge people to upgrade their script to more recent and readable\n>> style for eventual removal of the original syntax.\n>> \n>> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n>> ---\n>> \n>>     And this is the first step of such a deprecation.  Perhaps we start\n>>     warning in 1.7.0 and remove it in 1.8.0, or something like that.\n>\n> If this is going to be removed in the future, then it is already \n> deprecated.  Therefore it is much better to start warning now and not \n> wait for 1.7.0.  There is just no point delaying the advice.\n\nVery true.\n\nWhat I am not absolutely sure about is if the presense of the support for\nancient usage hurts people in real life so much that it is better to\nremove it than keep it.  At least we saw one example of a user (who is not\na novice) getting puzzled by it, but that may not be enough datapoint to\ndecide with.\n"},{"id":"128866","messageId":"4B1502F5.1060100@alum.mit.edu","threadId":"21797","inReplyTo":"cover.1259524136.git.brlink@debian.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2009-12-01T11:50:13Z","receivedAt":"2009-12-01T11:50:13Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"Bernhard R. Link wrote:\n> Example 1:\n> \n> Let's assume you maintain such a regularily-rebased branch that you\n> want to be able to publish (or pull from other repositories for example\n> on your laptop):\n> \n> o=m=o=o=master\n>    \\\n>     a=b=c=d=e=feature\n> \n> with this patch you can do \"git rebase -eqt master\" and get:\n> \n>               a'=b'=c'=d'=e'=feature'=eqt\n>              /                       /\n> o=m=o=o=master--------              /\n>    \\                  \\            /\n>     a=b=c=d=e=feature--merge-------\n\nActually, there is more information that can be retained about this\nrebase operation.  Your scheme records the fact that (a+b+c+d+e+merge)\n== (o+o+a'+b'+c'+d'+e'), which is certainly true.  But in the process of\nrebasing, the user has (implicitly or explicitly) resolved conflicts in\ntransforming each of the patches a -> a', b -> b', etc.  In fact, the\npatch a' is itself a merge between a and master; b' is a merge between b\nand a'; etc.  If you record each of these merges individually, the\nresult looks like this:\n\no=m=o=o=master\n   \\      \\\n    \\      a'=b'=c'=d'=e'=feature'\n     \\    /  /  /  /  /\n      ---a==b==c==d==e==feature\n\nThere are advantages to retaining all of this history:\n\n* It faithfully represents intermediate steps of the rebase.\n\n* There is no need for special \"merge\" and \"eqt\" merge commits affecting\nan arbitrary group of feature patches; each of the rebased patches is\ntreated identically.\n\n* There is a direct ancestry connection from the \"new version\" to the\n\"old version\" of each patch; for example, it is easy to see that c' is a\nnew version of c and to compute the corresponding interdiffs.\n\n* There are situations where the additional info can help git choose\nbetter merge bases in the case of merge/rebases across three or more\nrepositories.  For example, somebody who is developing a subfeature\nbased on the feature branch can merge/rebase changes from both feature\nand master without causing utter chaos.\n\nThe \"historical\" version of the feature branch should be omitted from\nmost git output as you have suggested, but this would be best\nimplemented by marking the \"historical\" ancestor with some extra flag in\neach merge commit.\n\n> Example 2:\n> \n> Let's assume you have a feature branch like\n> \n> o=master\n>    \\\n>     a=b=c=d=e=f\n> \n> Assume you just commited \"f\" which fixes a bug introduced by \"b\". [...]\n> \n> So with this patches you can do \"git rebase -i --eqt\" and squash f into b\n> and get:\n> \n> o=master\n>    \\\n>     a=b=c=d=e=f---\n>      \\            \\\n>       b+f=c'=d'=e'=eqt\n\nThis case can also record additional information:\n\no=master\n   \\\n    a=b===c==d=e=f\n       \\   \\  \\   \\\n        b+f=c'=d'==e'\n\nHere the new DAG cannot represent *all* ancestry information (namely,\nthat b+f, c', and d' also include the original patch f), but it does\naccurately reflect useful information such as that c' includes c and\nthat e' includes e and f.\n\nI wrote some blog entries about rebasing-with-history that might be\ninteresting [1-3].\n\nMichael\n\n[1]\nhttp://softwareswirl.blogspot.com/2009/04/truce-in-merge-vs-rebase-war.html\n[2]\nhttp://softwareswirl.blogspot.com/2009/08/upstream-rebase-just-works-if-history.html\n[3]\nhttp://softwareswirl.blogspot.com/2009/08/rebase-with-history-implementation.html\n"},{"id":"128992","messageId":"20091202192026.6117@nanako3.lavabit.com","threadId":"21797","inReplyTo":"7vmy23bl4o.fsf@alter.siamese.dyndns.org","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2009-12-02T10:20:26Z","receivedAt":"2009-12-02T10:20:26Z","isPatch":false,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting Junio C Hamano <gitster@pobox.com> writes:\n\n> I think we really should start deprecating the ancient form, but the\n> original sample script using this syntax from Linus was copied by many\n> people and are still found everywhere, I think, and people may still\n> use their scripts that were written with the ancient syntax.\n>\n> In any case, at least this patch will make it start behaving a bit\n> more sanely.\n\nThank you; it fixes the bug for me. Do I have to say \n\n    Tested-by: Nanako Shiraishi <nanako3@lavabit.com>\n\nto ask you to include it in the new release?\n\n> -- >8 --\n> Subject: Do not misidentify \"git merge foo HEAD\" as an old-style invocation\n>\n> This was misinterpreted as an ancient style \"git merge <message> HEAD\n> <commit> <commit>...\" that merges one (or more) <commit> into the current\n> branch and record the resulting commit with the given message.  Then a\n> later sanity check found that there is no <commit> specified and gave\n> a usage message.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>\n> diff --git a/builtin-merge.c b/builtin-merge.c\n> index e95c5dc..e5cf795 100644\n> --- a/builtin-merge.c\n> +++ b/builtin-merge.c\n> @@ -792,7 +792,7 @@ static int suggest_conflicts(void)\n>  static struct commit *is_old_style_invocation(int argc, const char **argv)\n>  {\n>  \tstruct commit *second_token = NULL;\n> -\tif (argc > 1) {\n> +\tif (argc > 2) {\n>  \t\tunsigned char second_sha1[20];\n>  \n>  \t\tif (get_sha1(argv[1], second_sha1))\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"129031","messageId":"7v638pgsnu.fsf@alter.siamese.dyndns.org","threadId":"21797","inReplyTo":"20091202192026.6117@nanako3.lavabit.com","subject":"Re: equal-tree-merges as way to make rebases fast-forward-able","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-02T18:03:17Z","receivedAt":"2009-12-02T18:03:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nanako Shiraishi <nanako3@lavabit.com> writes:\n\n>> In any case, at least this patch will make it start behaving a bit\n>> more sanely.\n>\n> Thank you; it fixes the bug for me. Do I have to say \n>\n>     Tested-by: Nanako Shiraishi <nanako3@lavabit.com>\n>\n> to ask you to include it in the new release?\n>\n>> -- >8 --\n>> Subject: Do not misidentify \"git merge foo HEAD\" as an old-style invocation\n\nThanks for reminding me.  I almost forgot that I did that patch.\n"}]}