{"thread":{"id":"9949","subject":"[PATCH 1/2] git-merge: add option --no-ff","startedAt":"2007-09-20T12:53:07Z","lastAt":"2007-09-20T13:38:48Z","messageCount":8,"participants":["Lars Hjemli","Johannes Schindelin","Matthieu Moy"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"53643","messageId":"1190292789-16203-1-git-send-email-hjemli@gmail.com","threadId":"9949","inReplyTo":null,"subject":"[PATCH 0/2] add support for per branch merge policy","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-09-20T12:53:07Z","receivedAt":"2007-09-20T12:53:07Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"These two patches extends git-merge with the options --ff and --no-ff,\nand uses the configuration setting branch.<name>.integrationonly to\nselect the default policy per branch (it obviously defaults to --ff), as\nmentioned in http://article.gmane.org/gmane.comp.version-control.git/41980\n\nThis can also be used as a clean solution to the problem related to\nfast-forward merges between git-svn tracking branches, especially if\ngit-svn could be taught to set integrationonly=true on all relevant\nbranches whenever this setting is undefined.\n\nDiffstat:\n\n Documentation/config.txt        |    7 +++\n Documentation/git-svn.txt       |   17 ++++++\n Documentation/merge-options.txt |   13 +++++\n git-merge.sh                    |   30 ++++++++++-\n t/t6029-merge-integration.sh    |  108 +++++++++++++++++++++++++++++++++++++++\n 5 files changed, 172 insertions(+), 3 deletions(-)\n"},{"id":"53642","messageId":"1190292789-16203-2-git-send-email-hjemli@gmail.com","threadId":"9949","inReplyTo":"1190292789-16203-1-git-send-email-hjemli@gmail.com","subject":"[PATCH 1/2] git-merge: add option --no-ff","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-09-20T12:53:08Z","receivedAt":"2007-09-20T12:53:08Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"This option forces all merges to create a \"true\" merge commit, i.e. a commit\nwith multiple parents.\n\nA fast-forward merge will often be considered The Right Thing when working\nin a distributed environment, but it doesn't work well when the branches to\nbe merged originated in subversion and the merge commit will be pushed back\nwith 'git svn dcommit'. In this case, a fast-forward merge will make git-svn\nmistakenly think that the current branch is tracking the merged upstream\nbranch. But if the merge is created with --no-ff, 'git svn dcommit' will work\nas expected (and the history in subversion and git will be equal).\n\nThere are also a use-case for --no-ff in 'native git' when integrating topic\nbranches: if the merge of a topic-branch results in a fast-forward operation,\nthere will be no way to detect that the topic-branch ever existed. This might\nbe good or bad dependent on project policy, but both options (ff/no-ff) are\ntechnically sane.\n\nSigned-off-by: Lars Hjemli <hjemli@gmail.com>\n---\n Documentation/git-svn.txt       |   13 +++++++++++\n Documentation/merge-options.txt |    5 ++++\n git-merge.sh                    |   13 +++++++++-\n t/t6029-merge-integration.sh    |   46 +++++++++++++++++++++++++++++++++++++++\n 4 files changed, 75 insertions(+), 2 deletions(-)\n create mode 100755 t/t6029-merge-integration.sh\n\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex e157c6a..619023d 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -475,6 +475,19 @@ use 'git-svn rebase' to update your work branch instead of 'git pull' or\n when committing into SVN, which can lead to merge commits reversing\n previous commits in SVN.\n \n+If you use 'git-svn dcommit' to commit your local work to the upstream\n+subversion branch, merge commits are usually handled correctly, i.e.\n+git-svn will only follow the first parent of each merge commit and create\n+a single subversion revision for each of them. An exception is when two\n+subversion branches has been merged locally and the merge ended up as a\n+fast-forward operation. This will make git-svn believe that there are no\n+local changes to dcommit. To work around this issue, one can redo the\n+merge using the --no-ff option:\n+\n+       $ git reset --hard HEAD@{1}   ## undo the fast-forward merge\n+       $ git merge --no-ff <branch>\n+\n+\n DESIGN PHILOSOPHY\n -----------------\n Merge tracking in Subversion is lacking and doing branched development\ndiff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\nindex d64c259..b34b888 100644\n--- a/Documentation/merge-options.txt\n+++ b/Documentation/merge-options.txt\n@@ -25,3 +25,8 @@\n \tIf there is no `-s` option, a built-in list of strategies\n \tis used instead (`git-merge-recursive` when merging a single\n \thead, `git-merge-octopus` otherwise).\n+\n+--no-ff::\n+\tForce the creation of a merge commit even when the merge would\n+\thave resolved as a fast-forward operation. See gitlink:git-svn[1]\n+\tfor a use-case for this option.\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 3a01db0..70ca5ff 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -3,7 +3,7 @@\n # Copyright (c) 2005 Junio C Hamano\n #\n \n-USAGE='[-n] [--summary] [--no-commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'\n+USAGE='[-n] [--summary] [--no-commit] [--no-ff] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'\n \n SUBDIRECTORY_OK=Yes\n . git-sh-setup\n@@ -165,6 +165,9 @@ do\n \t\tmerge_msg=\"$1\"\n \t\thave_message=t\n \t\t;;\n+\t--no-ff)\n+\t\tallow_fast_forward=f\n+\t\t;;\n \t-*)\tusage ;;\n \t*)\tbreak ;;\n \tesac\n@@ -444,7 +447,13 @@ done\n # auto resolved the merge cleanly.\n if test '' != \"$result_tree\"\n then\n-    parents=$(git show-branch --independent \"$head\" \"$@\" | sed -e 's/^/-p /')\n+    if test \"$allow_fast_forward\" = \"f\"\n+    then\n+        parents=$(git rev-parse \"$head\" \"$@\")\n+    else\n+        parents=$(git show-branch --independent \"$head\" \"$@\")\n+    fi\n+    parents=$(echo \"$parents\" | sed -e 's/^/-p /')\n     result_commit=$(printf '%s\\n' \"$merge_msg\" | git commit-tree $result_tree $parents) || exit\n     finish \"$result_commit\" \"Merge made by $wt_strategy.\"\n     dropsave\ndiff --git a/t/t6029-merge-integration.sh b/t/t6029-merge-integration.sh\nnew file mode 100755\nindex 0000000..6ba7dd9\n--- /dev/null\n+++ b/t/t6029-merge-integration.sh\n@@ -0,0 +1,46 @@\n+#!/bin/sh\n+\n+test_description='merge --no-ff'\n+\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\t>file &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m initial &&\n+\tgit tag c0 &&\n+\tc0=$(git rev-parse c0)\n+\n+\techo second >file &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m second &&\n+\tgit tag c1 &&\n+\tc1=$(git rev-parse c1)\n+\tgit branch test\n+'\n+\n+test_expect_success 'merge c1' '\n+\n+\tgit reset --hard c0 &&\n+\ttest_tick &&\n+\tgit merge c1 &&\n+\ttest $c0 = $(git rev-parse HEAD^) &&\n+\ttest $c1 = $(git rev-parse HEAD)\n+\n+'\n+\n+test_expect_success 'merge --no-ff c1' '\n+\n+\tgit reset --hard c0 &&\n+\ttest_tick &&\n+\tgit merge --no-ff c1 &&\n+\ttest $c0 = $(git rev-parse HEAD^1) &&\n+\ttest $c1 = $(git rev-parse HEAD^2)\n+\n+'\n+\n+test_debug 'gitk &'\n+\n+test_done\n-- \n1.5.3.2.82.g75c8d\n"},{"id":"53644","messageId":"1190292789-16203-3-git-send-email-hjemli@gmail.com","threadId":"9949","inReplyTo":"1190292789-16203-2-git-send-email-hjemli@gmail.com","subject":"[PATCH 2/2] add support for branch.<name>.integrationonly","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-09-20T12:53:09Z","receivedAt":"2007-09-20T12:53:09Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"This setting can be used to set --no-ff as default merge policy for\nselected branches. There is also a new new merge-option, --ff, which can\nbe used to override the default.\n\nSigned-off-by: Lars Hjemli <hjemli@gmail.com>\n---\n Documentation/config.txt        |    7 ++++\n Documentation/git-svn.txt       |    4 ++\n Documentation/merge-options.txt |   14 +++++++--\n git-merge.sh                    |   19 ++++++++++-\n t/t6029-merge-integration.sh    |   64 ++++++++++++++++++++++++++++++++++++++-\n 5 files changed, 102 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 015910f..fa7c3c1 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -337,6 +337,13 @@ branch.<name>.merge::\n \tbranch.<name>.merge to the desired branch, and use the special setting\n \t`.` (a period) for branch.<name>.remote.\n \n+branch.<name>.integrationonly::\n+\tWhen merging into branch <name>, this setting specifies whether\n+\tfast-forward merges are disallowed. The setting can be overridden\n+\tby the --ff and --no-ff options of gitlink:git-merge[1]. See\n+\tgitlink:git-svn[1] for information about this setting when\n+\tworking with subversion branches. Defaults to false.\n+\n clean.requireForce::\n \tA boolean to make git-clean do nothing unless given -f or -n.  Defaults\n \tto false.\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex 619023d..55828a3 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -487,6 +487,10 @@ merge using the --no-ff option:\n        $ git reset --hard HEAD@{1}   ## undo the fast-forward merge\n        $ git merge --no-ff <branch>\n \n+Alternatively, one can configure the appropriate local branches to use\n+--no-ff as default by setting branch.<name>.integrationonly=true in\n+$GIT_DIR/config.\n+\n \n DESIGN PHILOSOPHY\n -----------------\ndiff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\nindex b34b888..f83bba9 100644\n--- a/Documentation/merge-options.txt\n+++ b/Documentation/merge-options.txt\n@@ -26,7 +26,15 @@\n \tis used instead (`git-merge-recursive` when merging a single\n \thead, `git-merge-octopus` otherwise).\n \n+--ff::\n+\tExplicitly allow fast-forward merges. This can be used to\n+\toverride the merge policy of the current branch, as specified\n+\tby the branch.<branch>.integrationonly configuration setting (see \n+\tgitlink:git-config[1] for further details).\n+\n --no-ff::\n-\tForce the creation of a merge commit even when the merge would\n-\thave resolved as a fast-forward operation. See gitlink:git-svn[1]\n-\tfor a use-case for this option.\n+\tExplicitly disallow fast-forward merges. This can be used to\n+\toverride the merge policy of the current branch, as specified\n+\tby the branch.<branch>.integrationonly configuration setting (see \n+\tgitlink:git-config[1] for further details, and gitlink:git-svn[1]\n+\tfor a use-case for this option).\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 70ca5ff..4775767 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -3,7 +3,7 @@\n # Copyright (c) 2005 Junio C Hamano\n #\n \n-USAGE='[-n] [--summary] [--no-commit] [--no-ff] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'\n+USAGE='[-n] [--summary] [--no-commit] [--ff] [--no-ff] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'\n \n SUBDIRECTORY_OK=Yes\n . git-sh-setup\n@@ -23,7 +23,7 @@ no_fast_forward_strategies='subtree ours'\n no_trivial_strategies='recursive recur subtree ours'\n use_strategies=\n \n-allow_fast_forward=t\n+allow_fast_forward=\n allow_trivial_merge=t\n \n dropsave() {\n@@ -165,6 +165,9 @@ do\n \t\tmerge_msg=\"$1\"\n \t\thave_message=t\n \t\t;;\n+\t--ff)\n+\t\tallow_fast_forward=t\n+\t\t;;\n \t--no-ff)\n \t\tallow_fast_forward=f\n \t\t;;\n@@ -245,6 +248,18 @@ do\n done\n set x $remoteheads ; shift\n \n+if test -z \"$allow_fast_forward\"\n+then\n+\tbranch=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||')\n+\tintegrate=$(git config --bool \"branch.$branch.integrationonly\")\n+\tif test -n \"$branch\" -a \"$integrate\" = \"true\"\n+\tthen\n+\t\tallow_fast_forward=f\n+\telse\n+\t\tallow_fast_forward=t\n+\tfi\n+fi\n+\n case \"$use_strategies\" in\n '')\n \tcase \"$#\" in\ndiff --git a/t/t6029-merge-integration.sh b/t/t6029-merge-integration.sh\nindex 6ba7dd9..c5ffa34 100755\n--- a/t/t6029-merge-integration.sh\n+++ b/t/t6029-merge-integration.sh\n@@ -31,6 +31,8 @@ test_expect_success 'merge c1' '\n \n '\n \n+test_debug 'gitk'\n+\n test_expect_success 'merge --no-ff c1' '\n \n \tgit reset --hard c0 &&\n@@ -41,6 +43,66 @@ test_expect_success 'merge --no-ff c1' '\n \n '\n \n-test_debug 'gitk &'\n+test_debug 'gitk'\n+\n+test_expect_success 'setup integrationonly' '\n+\n+\tgit config branch.master.integrationonly true\n+\n+'\t\n+\n+test_expect_success 'merge c1' '\n+\n+\tgit reset --hard c0 &&\n+\ttest_tick &&\n+\tgit merge c1 &&\n+\ttest $c0 = $(git rev-parse HEAD^1) &&\n+\ttest $c1 = $(git rev-parse HEAD^2)\n+\n+'\n+\n+test_debug 'gitk'\n+\n+test_expect_success 'merge c1 --ff' '\n+\n+\tgit reset --hard c0 &&\n+\ttest_tick &&\n+\tgit merge --ff c1 &&\n+\ttest $c0 = $(git rev-parse HEAD^) &&\n+\ttest $c1 = $(git rev-parse HEAD)\n+\n+'\n+\n+test_debug 'gitk'\n+\n+test_expect_success 'revert integrationonly' '\n+\n+\tgit config branch.master.integrationonly false\n+\n+'\t\n+\n+test_expect_success 'merge c1' '\n+\n+\tgit reset --hard c0 &&\n+\ttest_tick &&\n+\tgit merge c1 &&\n+\ttest $c0 = $(git rev-parse HEAD^) &&\n+\ttest $c1 = $(git rev-parse HEAD)\n+\n+'\n+\n+test_debug 'gitk'\n+\n+test_expect_success 'merge c1 --no-ff' '\n+\n+\tgit reset --hard c0 &&\n+\ttest_tick &&\n+\tgit merge --no-ff c1 &&\n+\ttest $c0 = $(git rev-parse HEAD^1) &&\n+\ttest $c1 = $(git rev-parse HEAD^2)\n+\n+'\n+\n+test_debug 'gitk'\n \n test_done\n-- \n1.5.3.2.82.g75c8d\n"},{"id":"53645","messageId":"8c5c35580709200607s428e898ay32fd4cdad30f096e@mail.gmail.com","threadId":"9949","inReplyTo":"1190292789-16203-1-git-send-email-hjemli@gmail.com","subject":"Re: [PATCH 0/2] add support for per branch merge policy","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-09-20T13:07:50Z","receivedAt":"2007-09-20T13:07:50Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On 9/20/07, Lars Hjemli <hjemli@gmail.com> wrote:\n> branch.<name>.integrationonly\n\nBtw: we might want to call this 'branch.<name>.mergepolicy' with the\npossible values 'synchronize' and 'integrate'.\n\n--\nlarsh\n"},{"id":"53647","messageId":"Pine.LNX.4.64.0709201413440.28395@racer.site","threadId":"9949","inReplyTo":"1190292789-16203-3-git-send-email-hjemli@gmail.com","subject":"Re: [PATCH 2/2] add support for branch.<name>.integrationonly","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-20T13:14:18Z","receivedAt":"2007-09-20T13:14:18Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 20 Sep 2007, Lars Hjemli wrote:\n\n> +branch.<name>.integrationonly::\n\nWhy not have something like branch.<name>.mergeOptions instead?\n\nCiao,\nDscho\n"},{"id":"53648","messageId":"Pine.LNX.4.64.0709201424270.28395@racer.site","threadId":"9949","inReplyTo":"8c5c35580709200607s428e898ay32fd4cdad30f096e@mail.gmail.com","subject":"Re: [PATCH 0/2] add support for per branch merge policy","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-09-20T13:24:38Z","receivedAt":"2007-09-20T13:24:38Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 20 Sep 2007, Lars Hjemli wrote:\n\n> On 9/20/07, Lars Hjemli <hjemli@gmail.com> wrote:\n> > branch.<name>.integrationonly\n> \n> Btw: we might want to call this 'branch.<name>.mergepolicy' with the\n> possible values 'synchronize' and 'integrate'.\n\nIMHO this is way too limiting.\n\nCiao,\nDscho\n"},{"id":"53649","messageId":"vpq1wctsblf.fsf@bauges.imag.fr","threadId":"9949","inReplyTo":"Pine.LNX.4.64.0709201413440.28395@racer.site","subject":"Re: [PATCH 2/2] add support for branch.<name>.integrationonly","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2007-09-20T13:36:12Z","receivedAt":"2007-09-20T13:36:12Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Thu, 20 Sep 2007, Lars Hjemli wrote:\n>\n>> +branch.<name>.integrationonly::\n>\n> Why not have something like branch.<name>.mergeOptions instead?\n\nWhy make it plural? I agree that it's better to have a multiple values\noption than having just \"true/false\", which makes it more extensible,\nbut I don't understand the kind of things you could put here that\nwouldn't be better located in a separate configuration option.\n\n-- \nMatthieu\n"},{"id":"53650","messageId":"8c5c35580709200638v75fcf611m7c6465d074c9244d@mail.gmail.com","threadId":"9949","inReplyTo":"Pine.LNX.4.64.0709201424270.28395@racer.site","subject":"Re: [PATCH 0/2] add support for per branch merge policy","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2007-09-20T13:38:48Z","receivedAt":"2007-09-20T13:38:48Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"[...joining two posts in one...]\n\nOn 9/20/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > On 9/20/07, Lars Hjemli <hjemli@gmail.com> wrote:\n> > > branch.<name>.integrationonly\n> >\n> > Btw: we might want to call this 'branch.<name>.mergepolicy' with the\n> > possible values 'synchronize' and 'integrate'.\n>\n> IMHO this is way too limiting.\n> Why not have something like branch.<name>.mergeOptions instead?\n\nYeah, that would be more powerful, I'll give it a try.\n\n--\nlarsh\n"}]}