{"thread":{"id":"17415","subject":"[PATCH] Add --ff-only flag to git-merge","startedAt":"2009-01-28T12:53:58Z","lastAt":"2009-01-30T04:32:45Z","messageCount":9,"participants":["Yuval Kogman","Johannes Schindelin","Sverre Rabbelier","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"102305","messageId":"1233147238-30082-1-git-send-email-nothingmuch@woobling.org","threadId":"17415","inReplyTo":null,"subject":"[PATCH] Add --ff-only flag to git-merge","fromName":"Yuval Kogman","fromEmail":"nothingmuch@woobling.org","sentAt":"2009-01-28T12:53:58Z","receivedAt":"2009-01-28T12:53:58Z","isPatch":true,"sender":{"key":"nothingmuch@woobling.org","avatar":"https://gravatar.com/avatar/8aeee9ffc2fdaff6410edb92db8c0fe2031d2965faa1f8e48489953c06caefd8?d=mp&s=160"},"body":"This patch adds an --ff-only flag to git-merge. When specified git-merge\nwill exit with an error whenver a merge will not be a simple fast\nforward, similar to the default behavior of git push.\n---\n builtin-merge.c  |    6 ++++++\n t/t7600-merge.sh |   45 +++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 51 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex e4555b0..d37423b 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -44,6 +44,7 @@ static const char * const builtin_merge_usage[] = {\n static int show_diffstat = 1, option_log, squash;\n static int option_commit = 1, allow_fast_forward = 1;\n static int allow_trivial = 1, have_message;\n+static int only_fast_forward;\n static struct strbuf merge_msg;\n static struct commit_list *remoteheads;\n static unsigned char head[20], stash[20];\n@@ -167,6 +168,8 @@ static struct option builtin_merge_options[] = {\n \t\t\"perform a commit if the merge succeeds (default)\"),\n \tOPT_BOOLEAN(0, \"ff\", &allow_fast_forward,\n \t\t\"allow fast forward (default)\"),\n+\tOPT_BOOLEAN(0, \"ff-only\", &only_fast_forward,\n+\t\t\"allow only fast forward\"),\n \tOPT_CALLBACK('s', \"strategy\", &use_strategies, \"strategy\",\n \t\t\"merge strategy to use\", option_parse_strategy),\n \tOPT_CALLBACK('m', \"message\", &merge_msg, \"message\",\n@@ -1012,6 +1015,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tfinish(o->sha1, msg.buf);\n \t\tdrop_save();\n \t\treturn 0;\n+\t} else if ( only_fast_forward ) {\n+\t\tprintf(\"Merge is non fast forward, aborting.\\n\");\n+\t\treturn 1;\n \t} else if (!remoteheads->next && common->next)\n \t\t;\n \t\t/*\ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex e5b210b..6c2febc 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -234,6 +234,8 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' '\n \ttest_must_fail git merge -s index c1\n '\n \n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c0 with c1' '\n \tgit reset --hard c0 &&\n \tgit merge c1 &&\n@@ -243,6 +245,15 @@ test_expect_success 'merge c0 with c1' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge c0 with c1 (fast forward only)' '\n+\tgit reset --hard c0 &&\n+\tgit merge --ff-only c1 &&\n+\tverify_merge file result.1 &&\n+\tverify_head \"$c1\"\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c2' '\n \tgit reset --hard c1 &&\n \ttest_tick &&\n@@ -253,6 +264,14 @@ test_expect_success 'merge c1 with c2' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge c1 with c2' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\ttest_must_fail git merge --ff-only c2\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c2 and c3' '\n \tgit reset --hard c1 &&\n \ttest_tick &&\n@@ -263,6 +282,14 @@ test_expect_success 'merge c1 with c2 and c3' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge c1 with c2 and c3 (fast forward only' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\ttest_must_fail git merge --ff-only c2 c3\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c0 with c1 (no-commit)' '\n \tgit reset --hard c0 &&\n \tgit merge --no-commit c1 &&\n@@ -470,6 +497,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge fast forward only' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge --ff-only c0 c2 c0 c1\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c0, c2, c0, and c1' '\n        git reset --hard c1 &&\n        git config branch.master.mergeoptions \"\" &&\n@@ -481,6 +517,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge fast forward only' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge --ff-only c1 c2\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c1 and c2' '\n        git reset --hard c1 &&\n        git config branch.master.mergeoptions \"\" &&\n-- \n1.6.1\n"},{"id":"102307","messageId":"alpine.DEB.1.00.0901281425180.3586@pacific.mpi-cbg.de","threadId":"17415","inReplyTo":"1233147238-30082-1-git-send-email-nothingmuch@woobling.org","subject":"Re: [PATCH] Add --ff-only flag to git-merge","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-01-28T13:26:07Z","receivedAt":"2009-01-28T13:26:07Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 28 Jan 2009, Yuval Kogman wrote:\n\n> @@ -1012,6 +1015,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n>  \t\tfinish(o->sha1, msg.buf);\n>  \t\tdrop_save();\n>  \t\treturn 0;\n> +\t} else if ( only_fast_forward ) {\n> +\t\tprintf(\"Merge is non fast forward, aborting.\\n\");\n> +\t\treturn 1;\n>  \t} else if (!remoteheads->next && common->next)\n\nIf you compare the two if() lines, you will see that you mixed style.\n\nCiao,\nDscho\n"},{"id":"102308","messageId":"a891e1bd0901280529v296914bdod8f33a1db4846c47@mail.gmail.com","threadId":"17415","inReplyTo":"alpine.DEB.1.00.0901281425180.3586@pacific.mpi-cbg.de","subject":"Re: [PATCH] Add --ff-only flag to git-merge","fromName":"Yuval Kogman","fromEmail":"nothingmuch@woobling.org","sentAt":"2009-01-28T13:29:23Z","receivedAt":"2009-01-28T13:29:23Z","isPatch":true,"sender":{"key":"nothingmuch@woobling.org","avatar":"https://gravatar.com/avatar/8aeee9ffc2fdaff6410edb92db8c0fe2031d2965faa1f8e48489953c06caefd8?d=mp&s=160"},"body":"2009/1/28 Johannes Schindelin <Johannes.Schindelin@gmx.de>:\n> If you compare the two if() lines, you will see that you mixed style.\n\nThanks,\n\nI will be fixing it here:\n\nhttp://github.com/nothingmuch/git/tree/ff-only\n\nbefore I send a new version, as I likely screwed up many things, not\njust that =)\n"},{"id":"102311","messageId":"bd6139dc0901280635q6b6d538axede045de121f72b6@mail.gmail.com","threadId":"17415","inReplyTo":"1233147238-30082-1-git-send-email-nothingmuch@woobling.org","subject":"Re: [PATCH] Add --ff-only flag to git-merge","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-01-28T14:35:48Z","receivedAt":"2009-01-28T14:35:48Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"On Wed, Jan 28, 2009 at 13:53, Yuval Kogman <nothingmuch@woobling.org> wrote:\n> This patch adds an --ff-only flag to git-merge. When specified git-merge\n> will exit with an error whenver a merge will not be a simple fast\n> forward, similar to the default behavior of git push.\n\nI like! This calls for a new alias 'git config alias.integrate \"merge\n--no-ff\"', thanks!\n*hopes this hits next soon*\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"102350","messageId":"7vk58fm8x2.fsf@gitster.siamese.dyndns.org","threadId":"17415","inReplyTo":"1233147238-30082-1-git-send-email-nothingmuch@woobling.org","subject":"Re: [PATCH] Add --ff-only flag to git-merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-28T21:12:57Z","receivedAt":"2009-01-28T21:12:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yuval Kogman <nothingmuch@woobling.org> writes:\n\n> This patch adds an --ff-only flag to git-merge. When specified git-merge\n> will exit with an error whenver a merge will not be a simple fast\n> forward, similar to the default behavior of git push.\n> ---\n\nLacks a sign-off.\n\n> @@ -167,6 +168,8 @@ static struct option builtin_merge_options[] = {\n>  \t\t\"perform a commit if the merge succeeds (default)\"),\n>  \tOPT_BOOLEAN(0, \"ff\", &allow_fast_forward,\n>  \t\t\"allow fast forward (default)\"),\n> +\tOPT_BOOLEAN(0, \"ff-only\", &only_fast_forward,\n> +\t\t\"allow only fast forward\"),\n>  \tOPT_CALLBACK('s', \"strategy\", &use_strategies, \"strategy\",\n>  \t\t\"merge strategy to use\", option_parse_strategy),\n>  \tOPT_CALLBACK('m', \"message\", &merge_msg, \"message\",\n\nAfter parse_options() returns, there are a few existing tests to reject\nnonsensical combination of options.  I think there are some combinations\nyou would want to reject (for example, \"--no-ff --ff-only\" is an obvious\nsuch nonsensical combination, but there may be others, such as giving a\nstrategy explicitly).\n\n> @@ -1012,6 +1015,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n>  \t\tfinish(o->sha1, msg.buf);\n>  \t\tdrop_save();\n>  \t\treturn 0;\n> +\t} else if ( only_fast_forward ) {\n> +\t\tprintf(\"Merge is non fast forward, aborting.\\n\");\n> +\t\treturn 1;\n>  \t} else if (!remoteheads->next && common->next)\n>  \t\t;\n\nThis is wrong for at least three reasons:\n\n * Style of \"if (expression) {\", somebody else already pointed out.\n\n * Only this case exits with 1, while others die() that exits with 128.\n\n * The placement of this misses the case where a merge of two unrelated\n   histories is attempted.  You would need to also have a check at \"No\n   common ancestors found. We need a real merge.\" part.  The octopus\n   codepath could also end up with a fast forward or up-to-date.\n"},{"id":"102502","messageId":"a891e1bd0901291257t774af061s84497cde8f4bf61c@mail.gmail.com","threadId":"17415","inReplyTo":"7vk58fm8x2.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Add --ff-only flag to git-merge","fromName":"Yuval Kogman","fromEmail":"nothingmuch@woobling.org","sentAt":"2009-01-29T20:57:43Z","receivedAt":"2009-01-29T20:57:43Z","isPatch":true,"sender":{"key":"nothingmuch@woobling.org","avatar":"https://gravatar.com/avatar/8aeee9ffc2fdaff6410edb92db8c0fe2031d2965faa1f8e48489953c06caefd8?d=mp&s=160"},"body":"Hi,\n\nI started incorperating your feedback but before I send a new patch I\nhave several questions about the trickier bits:\n\n2009/1/28 Junio C Hamano <gitster@pobox.com>:\n\n>  * The placement of this misses the case where a merge of two unrelated\n>   histories is attempted.  You would need to also have a check at \"No\n>   common ancestors found. We need a real merge.\" part.\n\nWon't that fall through? The if (!common) is above, and this is\neventually an else if for it (see line 978)\n\n> The octopus\n>   codepath could also end up with a fast forward or up-to-date.\n\nSo this case is obviously more convoluted... If an octopus merge is\nchosen should it just pass --ff-only to git-merge-octopus? Or maybe it\nshould always pass --ff-only and the various different strategies\nwould just die unconditionally?\n"},{"id":"102511","messageId":"7vbptpeoge.fsf@gitster.siamese.dyndns.org","threadId":"17415","inReplyTo":"a891e1bd0901291257t774af061s84497cde8f4bf61c@mail.gmail.com","subject":"Re: [PATCH] Add --ff-only flag to git-merge","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-29T22:29:05Z","receivedAt":"2009-01-29T22:29:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yuval Kogman <nothingmuch@woobling.org> writes:\n\n> I started incorperating your feedback but before I send a new patch I\n> have several questions about the trickier bits:\n>\n> 2009/1/28 Junio C Hamano <gitster@pobox.com>:\n>\n>>  * The placement of this misses the case where a merge of two unrelated\n>>   histories is attempted.  You would need to also have a check at \"No\n>>   common ancestors found. We need a real merge.\" part.\n>\n> Won't that fall through? The if (!common) is above, and this is\n> eventually an else if for it (see line 978)\n\nWhen \"if (!common)\" is true, the empty statement \";\" is executed, and all\nits \"else if\" conditional arms will be skipped.  Is that what you want to\nhappen?\n\n>> The octopus\n>>   codepath could also end up with a fast forward or up-to-date.\n>\n> So this case is obviously more convoluted... If an octopus merge is\n> chosen should it just pass --ff-only to git-merge-octopus? Or maybe it\n> should always pass --ff-only and the various different strategies\n> would just die unconditionally?\n\nI was referring to this part:\n\n\t} else {\n\t\t/*\n\t\t * An octopus.  If we can reach all the remote we are up\n\t\t * to date.\n\t\t */\n\t\tint up_to_date = 1;\n\t\t...\n\t\tif (up_to_date) {\n\t\t\tfinish_up_to_date(\"Already up-to-date. Yeeah!\");\n\t\t\treturn 0;\n\t\t}\n\t}\n\nYou do not want to fail this case, where you tried to merge others that\nhave already been merged, when --ff-only is given, do you?  After all, all\nthat you are interested in is \"do not create a new merge commit\".\n\nIf you scroll down a bit from there, you will see:\n\n\n\t/* We are going to make a new commit. */\n\tgit_committer_info(IDENT_ERROR_ON_NO_NAME);\n\n\t/*\n\t * At this point, we need a real merge.  No matter what strategy\n\t * we use, it would operate on the index, possibly affecting the\n\nThis is where \"if (!common) ;\" will fall through to.\n\nIf your goal is to prevent the user from creating a new merge commit,\nthe logical place to do so would be immediately before that comment,\nindependent from all the if..elseif..fi conditional arms that come before\nit, I think.\n\nYou also need to disable allow_trivial when ff-only is given, but I think\nthat goes without saying.  If you do not want to allow creating a new\nmerge commit, you do not want even a trivial merge to happen.\n"},{"id":"102540","messageId":"1233289965-19538-1-git-send-email-nothingmuch@woobling.org","threadId":"17415","inReplyTo":"7vbptpeoge.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] Add --ff-only flag to git-merge (take 2)","fromName":"Yuval Kogman","fromEmail":"nothingmuch@woobling.org","sentAt":"2009-01-30T04:32:44Z","receivedAt":"2009-01-30T04:32:44Z","isPatch":true,"sender":{"key":"nothingmuch@woobling.org","avatar":"https://gravatar.com/avatar/8aeee9ffc2fdaff6410edb92db8c0fe2031d2965faa1f8e48489953c06caefd8?d=mp&s=160"},"body":"Hi,\n\nThis attempt fixes the various issues raised, except for the case of octopus\nending in 1 or more fast forwards. I'm not sure what the best way to fix this\nis. I see three obvious options, none of which seem optimal:\n\n\t1. git-merge-octopus will take a --ff-only flag as well, adding a branch for that\n\n\t2. ff-only could be a merge strategy, and octopus is forbidden in\n\t   --ff-only, while this new strategy will behave just like octopus when\n\t   the merge can be fast forward only.\n\n\t3. the logic from git-merge-octopus could be duplicated into builtin-merge,\n\t   to handle only the fast forward case.\n\nPlease advise.\n\nRegards,\nYuval\n"},{"id":"102541","messageId":"1233289965-19538-2-git-send-email-nothingmuch@woobling.org","threadId":"17415","inReplyTo":"1233289965-19538-1-git-send-email-nothingmuch@woobling.org","subject":"[PATCH] Add --ff-only flag to git-merge","fromName":"Yuval Kogman","fromEmail":"nothingmuch@woobling.org","sentAt":"2009-01-30T04:32:45Z","receivedAt":"2009-01-30T04:32:45Z","isPatch":true,"sender":{"key":"nothingmuch@woobling.org","avatar":"https://gravatar.com/avatar/8aeee9ffc2fdaff6410edb92db8c0fe2031d2965faa1f8e48489953c06caefd8?d=mp&s=160"},"body":"When specified git-merge will exit with an error unless the merge is\nresolved as a fast-forward.\n\nThis is similar to the default behavior of git push.\n---\n Documentation/merge-options.txt |    4 +++\n builtin-merge.c                 |   18 +++++++++++++++\n git-pull.sh                     |    4 ++-\n t/t7600-merge.sh                |   45 +++++++++++++++++++++++++++++++++++++++\n 4 files changed, 70 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\nindex 637b53f..ac742f8 100644\n--- a/Documentation/merge-options.txt\n+++ b/Documentation/merge-options.txt\n@@ -59,6 +59,10 @@\n \ta fast-forward, only update the branch pointer. This is\n \tthe default behavior of git-merge.\n \n+--ff-only::\n+\tRefuse to merge unless the merge is resolved as a\n+\tfast-forward.\n+\n -s <strategy>::\n --strategy=<strategy>::\n \tUse the given merge strategy; can be supplied more than\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex e4555b0..dae53fe 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -44,6 +44,7 @@ static const char * const builtin_merge_usage[] = {\n static int show_diffstat = 1, option_log, squash;\n static int option_commit = 1, allow_fast_forward = 1;\n static int allow_trivial = 1, have_message;\n+static int only_fast_forward;\n static struct strbuf merge_msg;\n static struct commit_list *remoteheads;\n static unsigned char head[20], stash[20];\n@@ -167,6 +168,8 @@ static struct option builtin_merge_options[] = {\n \t\t\"perform a commit if the merge succeeds (default)\"),\n \tOPT_BOOLEAN(0, \"ff\", &allow_fast_forward,\n \t\t\"allow fast forward (default)\"),\n+\tOPT_BOOLEAN(0, \"ff-only\", &only_fast_forward,\n+\t\t\"allow only fast forward\"),\n \tOPT_CALLBACK('s', \"strategy\", &use_strategies, \"strategy\",\n \t\t\"merge strategy to use\", option_parse_strategy),\n \tOPT_CALLBACK('m', \"message\", &merge_msg, \"message\",\n@@ -858,6 +861,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\toption_commit = 0;\n \t}\n \n+\tif (only_fast_forward && !allow_fast_forward)\n+\t\tdie(\"You cannot combine --ff-only with --no-ff.\");\n+\n \tif (!argc)\n \t\tusage_with_options(builtin_merge_usage,\n \t\t\tbuiltin_merge_options);\n@@ -959,6 +965,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t\tallow_trivial = 0;\n \t}\n \n+\tif (only_fast_forward && !allow_fast_forward)\n+\t\tdie(\"You cannot combine --ff-only with the selected\"\n+\t\t    \" merge strategies.\");\n+\n+\n \tif (!remoteheads->next)\n \t\tcommon = get_merge_bases(lookup_commit(head),\n \t\t\t\tremoteheads->item, 1);\n@@ -1023,6 +1034,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t * We are not doing octopus, not fast forward, and have\n \t\t * only one common.\n \t\t */\n+\n+\t\tif (only_fast_forward)\n+\t\t\tdie(\"Merge is non fast forward, aborting.\");\n+\n \t\trefresh_cache(REFRESH_QUIET);\n \t\tif (allow_trivial) {\n \t\t\t/* See if it is really trivial. */\n@@ -1063,6 +1078,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \n+\tif (only_fast_forward)\n+\t\tdie(\"Merge is non fast forward, aborting.\");\n+\n \t/* We are going to make a new commit. */\n \tgit_committer_info(IDENT_ERROR_ON_NO_NAME);\n \ndiff --git a/git-pull.sh b/git-pull.sh\nindex 2c7f432..242d36f 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -45,6 +45,8 @@ do\n \t\tno_ff=--ff ;;\n \t--no-ff)\n \t\tno_ff=--no-ff ;;\n+\t--ff-only)\n+\t\tff-only=--ff-only ;;\n \t-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\\\n \t\t--strateg=*|--strategy=*|\\\n \t-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)\n@@ -185,5 +187,5 @@ merge_name=$(git fmt-merge-msg $log_arg <\"$GIT_DIR/FETCH_HEAD\") || exit\n test true = \"$rebase\" &&\n \texec git-rebase $strategy_args --onto $merge_head \\\n \t${oldremoteref:-$merge_head}\n-exec git-merge $no_stat $no_commit $squash $no_ff $log_arg $strategy_args \\\n+exec git-merge $no_stat $no_commit $squash $no_ff $ff_only $log_arg $strategy_args \\\n \t\"$merge_name\" HEAD $merge_head $verbosity\ndiff --git a/t/t7600-merge.sh b/t/t7600-merge.sh\nindex e5b210b..6c2febc 100755\n--- a/t/t7600-merge.sh\n+++ b/t/t7600-merge.sh\n@@ -234,6 +234,8 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' '\n \ttest_must_fail git merge -s index c1\n '\n \n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c0 with c1' '\n \tgit reset --hard c0 &&\n \tgit merge c1 &&\n@@ -243,6 +245,15 @@ test_expect_success 'merge c0 with c1' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge c0 with c1 (fast forward only)' '\n+\tgit reset --hard c0 &&\n+\tgit merge --ff-only c1 &&\n+\tverify_merge file result.1 &&\n+\tverify_head \"$c1\"\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c2' '\n \tgit reset --hard c1 &&\n \ttest_tick &&\n@@ -253,6 +264,14 @@ test_expect_success 'merge c1 with c2' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge c1 with c2' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\ttest_must_fail git merge --ff-only c2\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c2 and c3' '\n \tgit reset --hard c1 &&\n \ttest_tick &&\n@@ -263,6 +282,14 @@ test_expect_success 'merge c1 with c2 and c3' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge c1 with c2 and c3 (fast forward only' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\ttest_must_fail git merge --ff-only c2 c3\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c0 with c1 (no-commit)' '\n \tgit reset --hard c0 &&\n \tgit merge --no-commit c1 &&\n@@ -470,6 +497,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge fast forward only' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge --ff-only c0 c2 c0 c1\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c0, c2, c0, and c1' '\n        git reset --hard c1 &&\n        git config branch.master.mergeoptions \"\" &&\n@@ -481,6 +517,15 @@ test_expect_success 'merge c1 with c0, c2, c0, and c1' '\n \n test_debug 'gitk --all'\n \n+test_expect_success 'merge fast forward only' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge --ff-only c1 c2\n+'\n+\n+test_debug 'gitk --all'\n+\n test_expect_success 'merge c1 with c1 and c2' '\n        git reset --hard c1 &&\n        git config branch.master.mergeoptions \"\" &&\n-- \n1.6.1\n"}]}