{"thread":{"id":"12870","subject":"Re: [RFC/PATCH 4/4] Introduce fast forward option only","startedAt":"2008-03-26T03:59:55Z","lastAt":"2008-03-26T03:59:55Z","messageCount":1,"participants":["Sverre Hvammen Johansen"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"73107","messageId":"402c10cd0803252059x3f6c0f18o86fc514cf04b2da3@mail.gmail.com","threadId":"12870","inReplyTo":null,"subject":"Re: [RFC/PATCH 4/4] Introduce fast forward option only","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-03-26T03:59:55Z","receivedAt":"2008-03-26T03:59:55Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":"This feature is needed for git integration with accurev.\nSee the documentation for an explanation of this feature.\n\nSigned-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>\n---\n Documentation/fast-forward-options.txt |    9 ++\n git-merge.sh                           |   12 +-\n git-pull.sh                            |    2 +-\n t/t7601-merge-ff-options.sh            |  214 ++++++++++++++++++++++++++++++++\n 4 files changed, 231 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/fast-forward-options.txt\nb/Documentation/fast-forward-options.txt\nindex 95d0e6f..4445b0e 100644\n--- a/Documentation/fast-forward-options.txt\n+++ b/Documentation/fast-forward-options.txt\n@@ -12,6 +12,10 @@ never::\n        Generate a merge commit even if the merge resolves as a\n        fast-forward.  This option is equivalent of '--no-ff'.\n\n+only::\n+       Only allow a fast-forward.  The merge will fail unless HEAD is\n+       up to date or the merge resolves as a fast-forward.\n+\n If your workflow is always to branch from the special branch\n (\"master\") when working on a topic and merge that back to \"master\", if\n you happen to have worked only on a single topic and the \"master\" was\n@@ -42,3 +46,8 @@ The first merge of topicA or the only merge of\ntopicB would have\n resulted in a fast forward without '--ff=never'.  Topic A consist of\n those commits that can be reached from master^2 without passing\n through any of the first-parent ancestries of master.\n+\n+However, if the workflow require that the branch you are merging with\n+is based on the current HEAD you can use \"only fast forward\" policy to\n+enforce fast forward or a failure.  The last merge of topicA in\n+the example above would have failed with '--ff=only'.\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 5398606..b6c428f 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -162,21 +162,21 @@ parse_config () {\n                        no_commit=t ;;\n                --ff)\n                        case \"$2\" in\n-                       allow|never)\n+                       allow|never|only)\n                                fast_forward=$2; shift ;;\n                        -*)\n                                fast_forward=allow ;;\n                        *)\n-                               die \"Available fast-forward options\nare: allow and newer\" ;;\n+                               die \"Available fast-forward options\nare: allow, newer, and only\" ;;\n                        esac\n                        ;;\n                --ff=*)\n                        fast_forward=${1#--ff=}\n                        case \"$fast_forward\" in\n-                       allow|never)\n+                       allow|never|only)\n                                ;;\n                        *)\n-                               die \"Available fast-forward options\nare: allow and newer\" ;;\n+                               die \"Available fast-forward options\nare: allow, newer, and only\" ;;\n                        esac\n                        ;;\n                --no-ff)\n@@ -203,7 +203,7 @@ parse_config () {\n                shift\n        done\n        test \"$fast_forward\" = allow -o \"$squash\" = \"\" ||\n-               die \"You cannot combine --squash with --ff=never\"\n+               die \"You cannot combine --squash with --ff=never or --ff=only.\"\n        args_left=$#\n }\n\n@@ -338,6 +338,8 @@ find_real_parents \"$@\"\n\n if test -n \"$real_parents\"\n then\n+       test $fast_forward = only &&\n+               die \"--ff=only can not handle more than one real parent\"\n        test $head = $ff_head ||\n                real_parents=\"$ff_head$LF$real_parents\"\n fi\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 2d7293a..5bc84a6 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -41,7 +41,7 @@ do\n                no_ff=--ff ;;\n        --no-ff)\n                no_ff=--no-ff ;;\n-       --ff=allow|--ff=never)\n+       --ff=allow|--ff=only|--ff=never)\n                no_ff=$1 ;;\n        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\\\n                --strateg=*|--strategy=*|\\\ndiff --git a/t/t7601-merge-ff-options.sh b/t/t7601-merge-ff-options.sh\nindex 636e71e..ca4cc67 100755\n--- a/t/t7601-merge-ff-options.sh\n+++ b/t/t7601-merge-ff-options.sh\n@@ -636,4 +636,218 @@ test_expect_success 'merge c1 with new\nrepository (pull --ff=never)' '\n\n test_debug 'gitk --all'\n\n+test_expect_success 'merge c0 with c1 (--ff=only overrides --no-ff)' '\n+       git reset --hard c0 &&\n+       git config branch.master.mergeoptions \"--no-ff\" &&\n+       git merge --ff=only c1 &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with c1 (--ff=only in config)' '\n+       git reset --hard c0 &&\n+       git config branch.master.mergeoptions \"--ff=only\" &&\n+       git merge c1 &&\n+       test_tick &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c0 (--ff=only in config)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"--ff=only\" &&\n+       git merge c0 &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c2 (--ff=only in config)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git config branch.master.mergeoptions \"--ff=only\" &&\n+       test_must_fail git merge c2 &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with c1 (--ff=only)' '\n+       git reset --hard c0 &&\n+       test_tick &&\n+       git merge --ff=only c1 &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c0 (--ff=only)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git merge --ff=only c0 &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with c1 and c2 (--ff=only)' '\n+       git reset --hard c0 &&\n+       test_must_fail git merge --ff=only c1 c2 &&\n+       verify_merge file result.0 &&\n+       verify_head $c0\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c0 (--ff=only)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git merge --ff=only c0 &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c2 (--ff=only overrides --no-ff)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"--no-ff\" &&\n+       test_tick &&\n+       test_must_fail git merge c2 --ff=only &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with c1 (--no-ff overrides --ff=only)' '\n+       git reset --hard c0 &&\n+       git config branch.master.mergeoptions \"--ff=only\" &&\n+       test_tick &&\n+       git merge --no-ff c1 &&\n+       verify_merge file result.1 &&\n+       verify_parents $c0 $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c2 (--ff owerrides --ff=only)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"--ff=only\" &&\n+       test_tick &&\n+       git merge --ff c2 &&\n+       verify_merge file result.1-5 &&\n+       verify_parents $c1 $c2\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with x0 (--squash combined with --ff=only)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge x0 --squash --ff=only &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge x0 with c1 (--squash combined with --ff=only)' '\n+       git reset --hard x0 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge c1 --squash --ff=only &&\n+       verify_merge file result.1-5 &&\n+       verify_head $x0\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge c1 with c2 (--squash combined with --ff=only)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge c2 --squash --ff=only &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge c1 with x0 (--no-commit combined with --ff=only)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge x0 --no-commit --ff=only &&\n+       verify_merge file result.1-5 &&\n+       verify_head $x0\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge x0 with c1 (--no-commit combined with --ff=only)' '\n+       git reset --hard x0 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c1 --no-commit --ff=only &&\n+       verify_merge file result.1-5 &&\n+       verify_head $x0\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c2 (--no-commit combined with --ff=only)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge c2 --no-commit --ff=only &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with x1 (pull --ff=only)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git pull --ff=only clone refs/heads/master &&\n+       verify_merge file result.1-13 &&\n+       verify_head $x1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge x2 with x1 (pull --ff=only)' '\n+       git reset --hard x2 &&\n+       test_tick &&\n+       test_must_fail git pull --ff=only clone refs/heads/master &&\n+       verify_merge file result.5-13 &&\n+       verify_head $x2\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=only)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       test_must_fail git pull --ff=only new refs/heads/master &&\n+       verify_merge file result.1 &&\n+       verify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n test_done\n\n-- \nSverre Hvammen Johansen\n"}]}