{"thread":{"id":"13829","subject":"[PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","startedAt":"2008-06-06T10:59:30Z","lastAt":"2008-06-08T23:06:33Z","messageCount":10,"participants":["Paolo Bonzini","Peter Karlsson","Miklos Vajna","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"78888","messageId":"E1K4a1Q-0002hq-QE@fencepost.gnu.org","threadId":"13829","inReplyTo":null,"subject":"[PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-06-06T10:59:30Z","receivedAt":"2008-06-06T10:59:30Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"The new strategy resolves only two heads, and the result of the merge\nis always the second head.  It can be useful with `rebase --onto`,\nbecause it always resolves conflicts in favor of the commits\nbeing applied.\n\nThe patch includes an update to git-rebase's documentation, showing\nhow to use the new patch to convert an \"--amend\"ing commit into a\nseparate one, as if --amend had not been used.\n---\n .gitignore                         |    1 +\n Documentation/git-rebase.txt       |   39 +++++++++++++++++++++++++\n Documentation/merge-strategies.txt |    6 ++++\n Makefile                           |    3 +-\n builtin-merge-theirs.c             |   56 ++++++++++++++++++++++++++++++++++++\n builtin.h                          |    1 +\n git-merge.sh                       |    6 ++--\n git.c                              |    1 +\n t/t3409-rebase-merge-theirs.sh     |   43 +++++++++++++++++++++++++++\n 9 files changed, 152 insertions(+), 4 deletions(-)\n create mode 100644 builtin-merge-theirs.c\n create mode 100755 t/t3409-rebase-merge-theirs.sh\n\n\tThis is equivalent to this script that I suggested in\n\thttp://permalink.gmane.org/gmane.comp.version-control.git/83528\n\n\t\t#! /bin/sh\n\t\teval git reset \\$$# -- .\n\t\tgit-checkout-index -q -f -a \n\n\tThe use-case in the manual is also based on that thread.\n\ndiff --git a/.gitignore b/.gitignore\nindex 4ff2fec..6d000e5 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -77,6 +77,7 @@ git-merge-recursive\n git-merge-resolve\n git-merge-stupid\n git-merge-subtree\n+git-merge-theirs\n git-mergetool\n git-mktag\n git-mktree\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex cc4e94f..577ae83 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -168,6 +168,45 @@ This is useful if F and G were flawed in some way, or should not be\n part of topicA.  Note that the argument to --onto and the <upstream>\n parameter can be any valid commit-ish.\n \n+`git rebase` rewrites history, and this is in general something that\n+you do not want to do when somebody else is pulling from your\n+repository.  For this reason, history rewrites (\"forced updates\")\n+are often forbidden when pushing to a remote repository.  However,\n+there are other commands that rewrite history, and indeed rebasing\n+can help fixing mistakes and reverting to the published history.\n+\n+For example, `git commit --amend` also has this effect, and it can\n+happen that you use it even though you had already pushed to the\n+remote repository before amending your commit.  You can then\n+use `git rebase` (with the --onto option) to transform the `--amend`\n+commit into a separate commit (as if you had not used the `--amend`\n+option).  The situation is like this:\n+\n+------------\n+    o---D---E  origin/master\n+         \\\n+          E'---F---G---H---I  master\n+------------\n+\n+because the parent of the amended commit E' is D, that is\n+origin/master^.  To avoid a forced update from master to\n+origin/master, you need the history to look like this:\n+\n+------------\n+    o---D---E  origin/master\n+             \\\n+              E''---F'---G'---H'---I'  master\n+------------\n+\n+You can achieve this with:\n+\n+    git-rebase -s theirs --onto origin/master origin/master^ master\n+\n+The merge strategy `-s theirs` resolves conflicts in favor of the commits\n+being rebased---in this case, you know that the only conflicts will occur\n+when replaying E', and you definitely E'' to have those changes.\n+\n+\n In case of conflict, git-rebase will stop at the first problematic commit\n and leave conflict markers in the tree.  You can use git diff to locate\n the markers (<<<<<<) and make edits to resolve the conflict.  For each\ndiff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt\nindex 1276f85..384c34a 100644\n--- a/Documentation/merge-strategies.txt\n+++ b/Documentation/merge-strategies.txt\n@@ -34,6 +34,12 @@ ours::\n \tbe used to supersede old development history of side\n \tbranches.\n \n+theirs::\n+\tThis resolves only two heads, and the result of the merge is\n+\talways the second head.  It can be useful with `rebase --onto`,\n+\tbecause it always resolves conflicts in favor of the commits\n+\tbeing applied.\n+\n subtree::\n \tThis is a modified recursive strategy. When merging trees A and\n \tB, if B corresponds to a subtree of A, B is first adjusted to\ndiff --git a/Makefile b/Makefile\nindex cce5a6e..6241e5d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -515,6 +515,7 @@ BUILTIN_OBJS += builtin-merge-base.o\n BUILTIN_OBJS += builtin-merge-file.o\n BUILTIN_OBJS += builtin-merge-ours.o\n BUILTIN_OBJS += builtin-merge-recursive.o\n+BUILTIN_OBJS += builtin-merge-theirs.o\n BUILTIN_OBJS += builtin-mv.o\n BUILTIN_OBJS += builtin-name-rev.o\n BUILTIN_OBJS += builtin-pack-objects.o\n@@ -1343,7 +1344,7 @@ check-docs::\n \t\tcase \"$$v\" in \\\n \t\tgit-merge-octopus | git-merge-ours | git-merge-recursive | \\\n \t\tgit-merge-resolve | git-merge-stupid | git-merge-subtree | \\\n-\t\tgit-fsck-objects | git-init-db | \\\n+\t\tgit-merge-theirs | git-fsck-objects | git-init-db | \\\n \t\tgit-?*--?* ) continue ;; \\\n \t\tesac ; \\\n \t\ttest -f \"Documentation/$$v.txt\" || \\\ndiff --git a/builtin-merge-theirs.c b/builtin-merge-theirs.c\nnew file mode 100644\nindex 0000000..6f3e66a\n--- /dev/null\n+++ b/builtin-merge-theirs.c\n@@ -0,0 +1,56 @@\n+/*\n+ * Implementation the `theirs' merge strategy.\n+ *\n+ * Copyright (c) 2008 Paolo Bonzini\n+ *\n+ * A one-way merge, declaring that the merged-from tree trumps everybody else.\n+ */\n+\n+#include \"cache.h\"\n+#include \"run-command.h\"\n+#include \"tree.h\"\n+#include \"tree-walk.h\"\n+#include \"unpack-trees.h\"\n+\n+int cmd_merge_theirs(int argc, const char **argv, const char *prefix)\n+{\n+\tint i, fd;\n+\tstruct tree *tree;\n+\tstruct tree_desc desc;\n+\tstruct unpack_trees_options opts;\n+\tstruct lock_file lock_file;\n+\tunsigned char sha1[20];\n+\n+\tif (argc < 4)\n+\t\tdie(\"Usage: %s <base>... -- <head> <remote> ...\\n\", argv[0]);\n+\n+\tfor (i = 1; i < argc; ++i)\n+\t\tif (!strcmp(argv[i], \"--\"))\n+\t\t\tbreak;\n+\tif (argc - i != 3) /* \"--\" \"<head>\" \"<remote>\" */\n+\t\tdie(\"Not handling anything other than two heads merge.\");\n+\tif (get_sha1(argv[i + 2], sha1))\n+\t\tdie(\"%s: not a valid SHA1\", argv[i + 2]);\n+\tif (unmerged_cache())\n+\t\tdie(\"you need to resolve your current index first\");\n+\n+\tfd = hold_locked_index(&lock_file, 1);\n+\n+\tmemset(&opts, 0, sizeof(opts));\n+\topts.update = 1;\n+\topts.reset = 1;\n+\topts.merge = 1;\n+\topts.fn = oneway_merge;\n+\topts.src_index = &the_index;\n+\topts.dst_index = &the_index;\n+\n+\ttree = parse_tree_indirect(sha1);\n+\tinit_tree_desc(&desc, tree->buffer, tree->size);\n+\tif (unpack_trees(1, &desc, &opts))\n+\t\treturn 128;\n+\n+\tif (write_cache(fd, active_cache, active_nr) ||\n+\t    commit_locked_index(&lock_file))\n+\t\tdie(\"unable to write new index file\");\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 8bda111..933ba84 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -60,6 +60,7 @@ extern int cmd_merge_base(int argc, const char **argv, const char *prefix);\n extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);\n extern int cmd_merge_file(int argc, const char **argv, const char *prefix);\n extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);\n+extern int cmd_merge_theirs(int argc, const char **argv, const char *prefix);\n extern int cmd_mv(int argc, const char **argv, const char *prefix);\n extern int cmd_name_rev(int argc, const char **argv, const char *prefix);\n extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 2d177c1..24ba651 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -30,11 +30,11 @@ test -z \"$(git ls-files -u)\" ||\n LF='\n '\n \n-all_strategies='recur recursive octopus resolve stupid ours subtree'\n+all_strategies='recur recursive octopus resolve stupid ours theirs subtree'\n default_twohead_strategies='recursive'\n default_octopus_strategies='octopus'\n-no_fast_forward_strategies='subtree ours'\n-no_trivial_strategies='recursive recur subtree ours'\n+no_fast_forward_strategies='subtree ours theirs'\n+no_trivial_strategies='recursive recur subtree ours theirs'\n use_strategies=\n \n allow_fast_forward=t\ndiff --git a/git.c b/git.c\nindex 272bf03..4ee0822 100644\n--- a/git.c\n+++ b/git.c\n@@ -326,6 +326,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n \t\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n+\t\t{ \"merge-theirs\", cmd_merge_theirs, RUN_SETUP },\n \t\t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n \t\t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\ndiff --git a/t/t3409-rebase-merge-theirs.sh b/t/t3409-rebase-merge-theirs.sh\nnew file mode 100755\nindex 0000000..01a0434\n--- /dev/null\n+++ b/t/t3409-rebase-merge-theirs.sh\n@@ -0,0 +1,43 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2008 Paolo Bonzini\n+#\n+\n+test_description='git rebase -s theirs test'\n+\n+. ./test-lib.sh\n+\n+test_expect_success setup  '\n+\tT=\"A quick brown fox jumps over the lazy dog.\"\n+\techo \"$T\" >file &&\n+\techo \"$T\" >untouched\n+\tgit add file untouched &&\n+\tgit commit -m\"initial\" &&\n+\tfor i in 1 2 3 4 5\n+\tdo\n+\t\techo \"$i $T\"\n+\tdone >file &&\n+\tgit commit -a -m\"more work\" &&\n+\tgit branch origin &&\n+\tsed \"s/5/AMEND/\" file >file.tmp &&\n+\tmv file.tmp file &&\n+\tgit commit --amend -a -m\"master amended.\" &&\n+\tfor i in 6 7 8 9 10\n+\tdo\n+\t\techo \"$i $T\" >> file &&\n+\t\tgit commit -a -m\"$i\" || exit 1\n+\tdone &&\n+\tgit branch amended\n+'\n+\n+test_expect_success 'grafting amended history using rebase -s theirs...' '\n+\tgit rebase -s theirs --onto origin origin^ master &&\n+\tgit diff amended HEAD'\n+\n+test_expect_success '... should allow a subsequent fast forward merge' '\n+\tgit checkout origin &&\n+\tgit merge master &&\n+\ttest $(git rev-parse origin) = $(git rev-parse master)\n+'\n+\n+test_done\n-- \n1.5.5\n"},{"id":"78889","messageId":"Pine.LNX.4.64.0806061226510.12829@ds9.cixit.se","threadId":"13829","inReplyTo":"E1K4a1Q-0002hq-QE@fencepost.gnu.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Peter Karlsson","fromEmail":"peter@softwolves.pp.se","sentAt":"2008-06-06T11:27:47Z","receivedAt":"2008-06-06T11:27:47Z","isPatch":true,"sender":{"key":"peter@softwolves.pp.se","avatar":"https://avatars.githubusercontent.com/u/990764?v=4"},"body":"Paolo Bonzini:\n\nI found a typo in the documentation:\n\n> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\n[...]\n> +The merge strategy `-s theirs` resolves conflicts in favor of the commits\n> +being rebased---in this case, you know that the only conflicts will occur\n> +when replaying E', and you definitely E'' to have those changes.\n\nIt should say \"...you definitely *want* E'' to have...\"\n\n-- \n\\\\// Peter - http://www.softwolves.pp.se/\n"},{"id":"78890","messageId":"48491F45.3070100@gnu.org","threadId":"13829","inReplyTo":"E1K4a1Q-0002hq-QE@fencepost.gnu.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-06-06T11:28:05Z","receivedAt":"2008-06-06T11:28:05Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"Paolo Bonzini wrote:\n> The new strategy resolves only two heads, and the result of the merge\n> is always the second head.  It can be useful with `rebase --onto`,\n> because it always resolves conflicts in favor of the commits\n> being applied.\n> \n> The patch includes an update to git-rebase's documentation, showing\n> how to use the new patch to convert an \"--amend\"ing commit into a\n> separate one, as if --amend had not been used.\n\nSigned-Off-By: Paolo Bonzini  <bonzini@gnu.org>\n\n(i.e. forge it in my original commit message if the patch is accepted).\n\nPaolo\n"},{"id":"78913","messageId":"20080606141458.GQ29404@genesis.frugalware.org","threadId":"13829","inReplyTo":"E1K4a1Q-0002hq-QE@fencepost.gnu.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-06-06T14:14:58Z","receivedAt":"2008-06-06T14:14:58Z","isPatch":true,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Fri, Jun 06, 2008 at 12:59:30PM +0200, Paolo Bonzini <bonzini@gnu.org> wrote:\n> The new strategy resolves only two heads, and the result of the merge\n> is always the second head.  It can be useful with `rebase --onto`,\n> because it always resolves conflicts in favor of the commits\n> being applied.\n\nJust wanted to say I like the idea. :-)\n"},{"id":"78974","messageId":"7vfxrqrwjm.fsf@gitster.siamese.dyndns.org","threadId":"13829","inReplyTo":"E1K4a1Q-0002hq-QE@fencepost.gnu.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-06-06T23:08:45Z","receivedAt":"2008-06-06T23:08:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Paolo Bonzini <bonzini@gnu.org> writes:\n\n> +For example, `git commit --amend` also has this effect, and it can\n> +happen that you use it even though you had already pushed to the\n> +remote repository before amending your commit.  You can then\n> +use `git rebase` (with the --onto option) to transform the `--amend`\n> +commit into a separate commit (as if you had not used the `--amend`\n> +option).  The situation is like this:\n> +\n> +------------\n> +    o---D---E  origin/master\n> +         \\\n> +          E'---F---G---H---I  master\n> +------------\n> +\n> +because the parent of the amended commit E' is D, that is\n> +origin/master^.  To avoid a forced update from master to\n> +origin/master, you need the history to look like this:\n> +\n> +------------\n> +    o---D---E  origin/master\n> +             \\\n> +              E''---F'---G'---H'---I'  master\n> +------------\n> +\n> +You can achieve this with:\n> +\n> +    git-rebase -s theirs --onto origin/master origin/master^ master\n> +\n> +The merge strategy `-s theirs` resolves conflicts in favor of the commits\n> +being rebased---in this case, you know that the only conflicts will occur\n> +when replaying E', and you definitely E'' to have those changes.\n\nIsn't this a very risky thing to suggest as if it is a generally\napplicable solution?  What happens if others have already worked on top of\nE and your history looked like this?\n\n    o---D---E---X---Y  origin/master\n         \\\n          E'---F---G---H---I  master\n\nThe reader would want this history:\n\n\n    o---D---E---X---Y  origin/master\n                     \\\n                      E''--F'--G'--H'--I'  master\n\nwhere difference between Y and E'' contains the change between E and E'.\n\nHowever, neither \"rebase -s theirs --onto Y D master\" (use of D is more in\nthe spirit of your original example than literal origin/master^) nor\n\"rebase -s theirs --onto Y origin/master^ master\" (which is nonsense but\ncareless readers would be tempted to \"adjust\" your example to their\nsituation) would give such a tree.  E'' should not have the same tree as\nE' in this case.\n\nI think I know why you wanted to do it in the original context without X\nand Y.  Use of \"-s theirs\" would allow you to record the tree of E'\nwithout conflicts.  But even that I do not agree is a good thing to do.\n\nBecause original E' was an amend of E, its log message explained\neverything E did and more.  You cannot leave that same commit message in\nE''.  What you did in E was already explained in the history, so now you\nwould want to talk about the incremental change on top of it when you\ndesribe E''.  For that, replaying of E' must stop to allow you to fix up\nthe log message.  It shouldn't silently go on.\n\nYes, you may want an easy way to say \"the result should have the same tree\nas E'\" while replaying of E' on top of E _when_ you have to resolve the\nconflict.  But that is a separate issue (\"git checkout $other_head --\n$conflicted_paths\", or somesuch).  Using this in rebase is a horrible\nexample inviting misuse and a broken history, I think.\n"},{"id":"79090","messageId":"484B49D5.8080708@gnu.org","threadId":"13829","inReplyTo":"7vfxrqrwjm.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-06-08T02:54:13Z","receivedAt":"2008-06-08T02:54:13Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n> Because original E' was an amend of E, its log message explained\n> everything E did and more.  You cannot leave that same commit message in\n> E''.  What you did in E was already explained in the history, so now you\n> would want to talk about the incremental change on top of it when you\n> desribe E''.  For that, replaying of E' must stop to allow you to fix up\n> the log message. \n\nYes, I had suggested in the original thread to follow up with a \"git \nrebase -i\" to fix the commit message, because \"git-rebase--interactive \n--help\" did not show a -s option.  However, I found out that it does \nsupport it, so it is probably better to use \"git rebase -i -s theirs \n--onto ...\" directly.\n\n> Yes, you may want an easy way to say \"the result should have the same tree\n> as E'\" while replaying of E' on top of E _when_ you have to resolve the\n> conflict.  But that is a separate issue (\"git checkout $other_head --\n> $conflicted_paths\", or somesuch).  Using this in rebase is a horrible\n> example inviting misuse and a broken history, I think.\n\nYou mean that I should a) drop the example from git-rebase.1, b) reword \nit to clarify it, c) drop the patch completely?\n\nPaolo\n"},{"id":"79099","messageId":"7vmylwl4t9.fsf@gitster.siamese.dyndns.org","threadId":"13829","inReplyTo":"484B49D5.8080708@gnu.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-06-08T08:16:34Z","receivedAt":"2008-06-08T08:16:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Paolo Bonzini <bonzini@gnu.org> writes:\n\n>> Because original E' was an amend of E, its log message explained\n>> everything E did and more.  You cannot leave that same commit message in\n>> E''.  What you did in E was already explained in the history, so now you\n>> would want to talk about the incremental change on top of it when you\n>> desribe E''.  For that, replaying of E' must stop to allow you to fix up\n>> the log message.\n>\n> Yes, I had suggested in the original thread to follow up with a \"git\n> rebase -i\" to fix the commit message, because \"git-rebase--interactive\n> --help\" did not show a -s option.  However, I found out that it does\n> support it, so it is probably better to use \"git rebase -i -s theirs\n> --onto ...\" directly.\n\nYeah, but that is only about the commit log message.  The issue of\nrecording a wrong tree when commits X and Y exist is not alleviated, is\nit?\n\n> You mean that I should a) drop the example from git-rebase.1, b)\n> reword it to clarify it, c) drop the patch completely?\n\nI have to say that the rebase example is too misleading --- unless it is\naccompanied by a lot of disclaimers, its risk to give broken result to\npeople probably is worse than the benefit. I am afraid that we would need\na lot better use case to justify the use of \"theirs\" than what you wrote.\n\nI have occasionally seen valid situations to use \"ours\", but I personally\nhaven't been in a situation that merge using \"theirs\" is a good solution.\nObviously if you start from a wrong branch, you should be in the situation\nthat you would want to merge using \"theirs\", just like when you started\nfrom the right branch and would use \"ours\", but in practice that never\nhappened to me as far as I can recall.  I am not sure where this asymmetry\ncomes from.\n\nOn the other hand, I've sometimes heard people say \"when I get a merge\nconflict, I'd want to discard what I did _only in the conflicted part_.\"\nI am not sure if such a conflict resolution makes much sense in practice,\nbut perhaps people know that their changes are worthless crap anyway, and\ndo not even care about their work themselves, to the point that they would\nrather discard what they did than spend more time to fix them up properly.\nWhether that makes sense or not, what they want is different from \"theirs\"\n(which is opposite of \"ours\"); they want to keep their own changes for\nparts that did not conflict, and give up what they did only in the\nconflicted part.  Perhaps such a kind of mixed conflict resolution should\nbe supported under the name of \"theirs\", even though that would make\n\"ours\" and \"theirs\" _not_ the opposite of each other.  I dunno...\n"},{"id":"79106","messageId":"484BE0BE.1050102@gnu.org","threadId":"13829","inReplyTo":"7vmylwl4t9.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-06-08T13:38:06Z","receivedAt":"2008-06-08T13:38:06Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n> Yeah, but that is only about the commit log message.  The issue of\n> recording a wrong tree when commits X and Y exist is not alleviated, is\n> it?\n\nNo, it's not.\n\n> On the other hand, I've sometimes heard people say \"when I get a merge\n> conflict, I'd want to discard what I did _only in the conflicted part_.\"\n> I am not sure if such a conflict resolution makes much sense in practice,\n> but perhaps people know that their changes are worthless crap anyway, and\n> do not even care about their work themselves, to the point that they would\n> rather discard what they did than spend more time to fix them up properly.\n> Whether that makes sense or not, what they want is different from \"theirs\"\n> (which is opposite of \"ours\"); they want to keep their own changes for\n> parts that did not conflict, and give up what they did only in the\n> conflicted part.  Perhaps such a kind of mixed conflict resolution should\n> be supported under the name of \"theirs\", even though that would make\n> \"ours\" and \"theirs\" _not_ the opposite of each other.  I dunno...\n\nHmm, anyway you do want to test what this strategy would do --- before \nmerging.  The point of \"ours\"/\"theirs\" is AFAICS that they *cannot* \nproduce broken trees (they can cause you to lose committed stuff if used \ncarelessly, but the resulting tree is already in some branch and \nsupposedly has already been tested).  So breaking the symmetry would not \nbe good probably.\n\nI guess I see the reason why \"ours\" is more useful than \"theirs\".  The \nreason is that rebase (and \"rebase -i\" in particular is in some sense \ndifferent from most other git operations.  Git workflows are \nmerge-based, so your checked-out branch is the one where the interesting \nstuff is happening; if you wanted a \"theirs\" merge, you would probably \ndo it as a \"ours\" merge in the other branch.  Rebase instead is \ncherrypicking basically, so \"ours\" makes no sense (it would just *not* \ncherrypick).\n\n(It also explains why I saw a use case for \"theirs\" -- as a former arch \nuser, I still tend to think in terms of cherrypicks more than merges).\n\nThe correct way to proceed would be something like \"git rebase -i --onto \norigin/master $(git merge-base origin/master master) master\", and then \nif you have\n\n    A--B--C--X--Y     origin/master\n        \\\n         --C'--D--E      master\n\nchange\n\n    pick C'\n    pick D\n    pick E\n\ninto\n\n    reset C'^\n    pick --strategy=theirs C'\n    mark :1\n    reset origin/master\n    pick :1\n    pick D\n    pick E\n\nThen I guess the correct way to go is to write a custom script that uses \nthe sequencer to make the rebase scenario less dangerous.  You can do\n\n    #! /bin/sh\n    # git-merge-after-amend <branch>\n    #\n    # Makes it possible to do a fast-forward merge of <branch>\n    # into HEAD, assuming that the first diverging commit of <branch>\n    # is an --amend'ed version of the first diverging commit of HEAD.\n    us=$(git rev-parse HEAD)\n    them=$(git rev-parse $1)\n    base=$(git merge-base $us $them)\n\n    (echo reset $base\n    first=t\n    git rev-list --reverse $us..$them | while read i do\n      if test \"$first\" = t; then\n        first=\n        echo pick --strategy=theirs $i\n        echo mark :1\n        echo reset $us\n        echo pick --edit :1\n      else\n        echo pick $i\n      fi\n    done) | git-sequencer\n\nThis script could actually become a merge strategy, so that you could do\n\n    git reset --hard origin/master\n    git merge -s split-first HEAD@{1}\n\nThis is maybe a little contrived (what if there are conflits, ecc.), but \nI like how it shows git's pluggability.\n\nSo, as a result of the discussion, I think that:\n\n1) it can be useful to put the \"theirs\" strategy into git, especially as \nthe sequencer (which is cherrypick-based) becomes an important component \nof some git porcelain; I would remove the rebase example from my patch \nand make it just a power-user option (same as \"-s ours\").\n\n2) user-defined merge strategies can be useful.  So it would make sense \nto modify \"git-merge\" so that it accepts arbitrary merge strategies \ninstead of just the predefined ones.  These would default to disallowing \nfast forward and trivial merges.  (Possibly, as a safety net, \"index\", \n\"base\", \"file\", \"one-file\", \"tree\" should be excluded... this in turn \nmeans adding an interface to the commands array in git.c... again, I can \ndo this -- if it is considered interesting; I'd like to know that in \nadvance -- after the built-in merge is committed).\n\n3) this scenario giveit would make sense to provide the strategy option \nto \"git cherry-pick\".  I can write a patch for \"git cherry-pick\" if you \nare interested, though I'd like to have a hint about what to do with the \nshort option \"-s\", which is already taken by \"--signoff\".  The same \nthing could be done to the sequencer's pick command, so I'm also CCing \nStephan Beyer about this.\n\n4) A useful option for the sequencer (and possibly for git-rebase) would \nbe \"--batch\", ensuring that a single execution of the sequencer does the \nentire job.  \"--edit\" would then be changed to mean \"ask user to edit \ncommit message\" instead of \"stop and let the user amend the commit\"; and \nif a conflict was found, the sequencer would simply abort and exit with \na non-zero exit status.\n\nThanks,\n\nPaolo\n"},{"id":"79160","messageId":"7vk5gziqxn.fsf@gitster.siamese.dyndns.org","threadId":"13829","inReplyTo":"484BE0BE.1050102@gnu.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-06-08T20:59:16Z","receivedAt":"2008-06-08T20:59:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Paolo Bonzini <bonzini@gnu.org> writes:\n\n>    #! /bin/sh\n>    # git-merge-after-amend <branch>\n>    #\n>    # Makes it possible to do a fast-forward merge of <branch>\n>    # into HEAD, assuming that the first diverging commit of <branch>\n>    # is an --amend'ed version of the first diverging commit of HEAD.\n\nCan this strong special case limitation \"only the first one can be the\namend\" somehow be loosened?  Otherwise I suspect it would not be useful as\na general solution.\n"},{"id":"79182","messageId":"484C65F9.10007@gnu.org","threadId":"13829","inReplyTo":"7vk5gziqxn.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] provide a new \"theirs\" strategy, useful for rebase --onto","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2008-06-08T23:06:33Z","receivedAt":"2008-06-08T23:06:33Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"Junio C Hamano wrote:\n> Paolo Bonzini <bonzini@gnu.org> writes:\n> \n>>    #! /bin/sh\n>>    # git-merge-after-amend <branch>\n>>    #\n>>    # Makes it possible to do a fast-forward merge of <branch>\n>>    # into HEAD, assuming that the first diverging commit of <branch>\n>>    # is an --amend'ed version of the first diverging commit of HEAD.\n> \n> Can this strong special case limitation \"only the first one can be the\n> amend\" somehow be loosened?\n\nWell, the point of the exercise is to split a *single* commit into a \n\"base\" commit (already available, possibly on another branch) and a \n\"delta\" (the amending, transformed into an independent commit whose \nparent is the \"base\").  Indeed you can do that for any commit.\n\nThe script uses the \"git-merge-base\" to compute the \"base\", and takes \nthe following commit (on the path to HEAD) as the \"delta\".  That's what \nadd the restriction.  You can definitely make a two-argument variation \nthat, given arguments \"B C\" and history\n\n     o--B     (it is irrelevant if B and C have common parents)\n\n     o--o--C--D--E    HEAD\n\nmakes\n\n     A--B--C'--D--E\n\nEven in that case, I would make the script (which anyway is obviously \nnot meant to be included in git, it's a commodity script) accept both \nvariations: one-argument to do the special case, and two-arguments to \ngenerically split a commit into a base provided by the user + a delta.\n\nPaolo\n"}]}