{"thread":{"id":"13239","subject":"[PATCH 2/5] Introduce -ff=<fast forward option>","startedAt":"2008-04-24T05:46:41Z","lastAt":"2008-05-03T22:04:08Z","messageCount":3,"participants":["Sverre Hvammen Johansen","Ping Yin"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"75131","messageId":"402c10cd0804232246i6f7cd946h955b75832cf32876@mail.gmail.com","threadId":"13239","inReplyTo":null,"subject":"[PATCH 2/5] Introduce -ff=<fast forward option>","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-04-24T05:46:41Z","receivedAt":"2008-04-24T05:46:41Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":"--ff now takes an argument allowing --ff to be written\nas --ff=allow and -no-ff to be written as --ff=never.\nThis change allow other fast forward options to be\nintroduced later.\n\nSee the documentation for a further explanation of these options.\n\nSigned-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>\n---\n Documentation/fast-forward-options.txt |   44 ++++++++\n Documentation/git-merge.txt            |    6 +-\n Documentation/git-pull.txt             |    2 +\n Documentation/merge-options.txt        |    9 +-\n git-merge.sh                           |   47 +++++---\n git-pull.sh                            |    4 +-\n t/t7601-merge-ff-options.sh            |  188 ++++++++++++++++++++++++++++++++\n 7 files changed, 277 insertions(+), 23 deletions(-)\n create mode 100644 Documentation/fast-forward-options.txt\n\ndiff --git a/Documentation/fast-forward-options.txt\nb/Documentation/fast-forward-options.txt\nnew file mode 100644\nindex 0000000..95d0e6f\n--- /dev/null\n+++ b/Documentation/fast-forward-options.txt\n@@ -0,0 +1,44 @@\n+FAST FORWARD OPTIONS\n+--------------------\n+\n+allow::\n+\n+       Do not generate a merge commit if the merge resolves as a\n+       fast-forward, only update the branch pointer.  This option is\n+       equivalent of '--ff' without any argument.  This is the\n+       default behavior.\n+\n+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+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+never advanced during the time you worked on that topic, merging the\n+topic back to \"master\" will result in a fast-forward.  When you look\n+back that history, you will not be able to tell where the topic\n+started and ended by following the ancestry chain of the \"master\"\n+branch.\n+\n+Using \"never fast forward\" policy on such a special branch will be a\n+way to make sure that all commits on the first-parent ancestry of that\n+special branch will be merges from something else.  From the history\n+you can determine where the topic started and ended.\n+\n+The following shows two branches forked off from \"master\".  The branch\n+\"master\" have merged in changes from branch \"topicA\" twice and\n+\"topicB\" once:\n+\n+------------\n+         o---o---o---o---o  topicA\n+        /     \\           \\\n+    ---*-------*-------*---*  master\n+      /         \\     /\n+                 o---o  topicB\n+------------\n+\n+The first merge of topicA or the only merge of topicB 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.\ndiff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt\nindex c136b10..2af33d8 100644\n--- a/Documentation/git-merge.txt\n+++ b/Documentation/git-merge.txt\n@@ -9,7 +9,8 @@ git-merge - Join two or more development histories together\n SYNOPSIS\n --------\n [verse]\n-'git-merge' [-n] [--summary] [--no-commit] [--squash] [-s <strategy>]...\n+'git-merge' [-n] [--summary] [--no-commit] [--squash]\n+       [-s <strategy>]... [--ff[=<fast forward option>]]\n        [-m <msg>] <remote> <remote>...\n 'git-merge' <msg> HEAD <remote>...\n\n@@ -37,6 +38,9 @@ include::merge-options.txt[]\n        least one <remote>.  Specifying more than one <remote>\n        obviously means you are trying an Octopus.\n\n+\n+include::fast-forward-options.txt[]\n+\n include::merge-strategies.txt[]\n\n\ndiff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt\nindex 3405ca0..e4e013c 100644\n--- a/Documentation/git-pull.txt\n+++ b/Documentation/git-pull.txt\n@@ -52,6 +52,8 @@ include::pull-fetch-param.txt[]\n\n include::urls-remotes.txt[]\n\n+include::fast-forward-options.txt[]\n+\n include::merge-strategies.txt[]\n\n DEFAULT BEHAVIOUR\ndiff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\nindex 9f1fc82..cf4881b 100644\n--- a/Documentation/merge-options.txt\n+++ b/Documentation/merge-options.txt\n@@ -29,12 +29,11 @@\n\n --no-ff::\n        Generate a merge commit even if the merge resolved as a\n-       fast-forward.\n+       fast-forward.  --no-ff is an alias for --ff=never.\n\n---ff::\n-       Do not generate a merge commit if the merge resolved as\n-       a fast-forward, only update the branch pointer. This is\n-       the default behavior of git-merge.\n+--ff[=<fast forward option>]::\n+       Select fast forward option.  --ff without any argument\n+       is an alias for --ff=allow which is the default behavior.\n\n -s <strategy>, \\--strategy=<strategy>::\n        Use the given merge strategy; can be supplied more than\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 7dbbb1d..17f40f2 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -12,7 +12,7 @@ summary              show a diffstat at the end of the merge\n n,no-summary         don't show a diffstat at the end of the merge\n squash               create a single commit instead of doing a merge\n commit               perform a commit if the merge sucesses (default)\n-ff                   allow fast forward (default)\n+ff?                  fast forward options\n s,strategy=          merge strategy to use\n m,message=           message to be used for the merge commit (if any)\n \"\n@@ -35,7 +35,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+fast_forward=allow\n allow_trivial_merge=t\n squash= no_commit=\n\n@@ -153,8 +153,6 @@ parse_config () {\n                --summary)\n                        show_diffstat=t ;;\n                --squash)\n-                       test \"$allow_fast_forward\" = t ||\n-                               die \"You cannot combine --squash with --no-ff.\"\n                        squash=t no_commit=t ;;\n                --no-squash)\n                        squash= no_commit= ;;\n@@ -163,11 +161,26 @@ parse_config () {\n                --no-commit)\n                        no_commit=t ;;\n                --ff)\n-                       allow_fast_forward=t ;;\n+                       case \"$2\" in\n+                       allow|never)\n+                               fast_forward=$2; shift ;;\n+                       -*)\n+                               fast_forward=allow ;;\n+                       *)\n+                               die \"Available fast-forward options\nare: allow and newer\" ;;\n+                       esac\n+                       ;;\n+               --ff=*)\n+                       fast_forward=${1#--ff=}\n+                       case \"$fast_forward\" in\n+                       allow|never)\n+                               ;;\n+                       *)\n+                               die \"Available fast-forward options\nare: allow and newer\" ;;\n+                       esac\n+                       ;;\n                --no-ff)\n-                       test \"$squash\" != t ||\n-                               die \"You cannot combine --squash with --no-ff.\"\n-                       allow_fast_forward=f ;;\n+                       fast_forward=never ;;\n                -s|--strategy)\n                        shift\n                        case \" $all_strategies \" in\n@@ -189,6 +202,8 @@ parse_config () {\n                esac\n                shift\n        done\n+       test \"$fast_forward\" = allow -o \"$squash\" = \"\" ||\n+               die \"You cannot combine --squash with --ff=never\"\n        args_left=$#\n }\n\n@@ -308,7 +323,7 @@ do\n        do\n                case \" $s \" in\n                *\" $ss \"*)\n-                       allow_fast_forward=f\n+                       fast_forward=never\n                        break\n                        ;;\n                esac\n@@ -334,17 +349,17 @@ case \"$#\" in\n esac\n echo \"$head\" >\"$GIT_DIR/ORIG_HEAD\"\n\n-case \"$allow_fast_forward,$#,$common,$no_commit\" in\n-?,*,'',*)\n+case \"$fast_forward,$#,$common,$no_commit\" in\n+*,*,'',*)\n        # No common ancestors found. We need a real merge.\n        ;;\n-?,1,\"$1\",*)\n+*,1,\"$1\",*)\n        # If head can reach all the merge then we are up to date.\n        # but first the most common case of merging one remote.\n        finish_up_to_date \"Already up-to-date.\"\n        exit 0\n        ;;\n-t,1,\"$head\",*)\n+allow,1,\"$head\",*)\n        # Again the most common case of merging one remote.\n        echo \"Updating $(git rev-parse --short $head)..$(git rev-parse\n--short $1)\"\n        git update-index --refresh 2>/dev/null\n@@ -359,11 +374,11 @@ t,1,\"$head\",*)\n        dropsave\n        exit 0\n        ;;\n-?,1,?*\"$LF\"?*,*)\n+*,1,?*\"$LF\"?*,*)\n        # We are not doing octopus and not fast forward.  Need a\n        # real merge.\n        ;;\n-?,1,*,)\n+*,1,*,)\n        # We are not doing octopus, not fast forward, and have only\n        # one common.\n        git update-index --refresh 2>/dev/null\n@@ -481,7 +496,7 @@ done\n # auto resolved the merge cleanly.\n if test '' != \"$result_tree\"\n then\n-    if test \"$allow_fast_forward\" = \"t\"\n+    if test $fast_forward = allow\n     then\n         parents=$(git show-branch --independent \"$head\" \"$@\")\n     else\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 3ce32b5..2d7293a 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -4,7 +4,7 @@\n #\n # Fetch one or more remote refs and merge it/them into the current HEAD.\n\n-USAGE='[-n | --no-summary] [--[no-]commit] [--[no-]squash]\n[--[no-]ff] [-s strategy]... [<fetch-options>] <repo> <head>...'\n+USAGE='[-n | --no-summary] [--[no-]commit] [--[no-]squash]\n[--ff=<ff-strategy>] [-s strategy]... [<fetch-options>] <repo>\n<head>...'\n LONG_USAGE='Fetch one or more remote refs and merge it/them into the\ncurrent HEAD.'\n SUBDIRECTORY_OK=Yes\n OPTIONS_SPEC=\n@@ -41,6 +41,8 @@ do\n                no_ff=--ff ;;\n        --no-ff)\n                no_ff=--no-ff ;;\n+       --ff=allow|--ff=never)\n+               no_ff=$1 ;;\n        -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\\\n                --strateg=*|--strategy=*|\\\n        -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)\ndiff --git a/t/t7601-merge-ff-options.sh b/t/t7601-merge-ff-options.sh\nindex 408122e..2749f4f 100755\n--- a/t/t7601-merge-ff-options.sh\n+++ b/t/t7601-merge-ff-options.sh\n@@ -458,4 +458,192 @@ test_expect_success 'merge c1 with c2 and x1' '\n\n test_debug 'gitk --all'\n\n+test_expect_success 'merge x0 with c1 (--squash combined with --ff=allow)' '\n+       git reset --hard x0 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c1 --squash --ff=allow &&\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=allow)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c2 --squash --ff=allow &&\n+       verify_merge file result.1-5 &&\n+       verify_head $c1 &&\n+       git commit &&\n+       verify_parents $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge c1 with x0 (--no-commit combined with --ff=allow)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge x0 --no-commit --ff=allow &&\n+       verify_merge file result.1-5 &&\n+       verify_parents $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge x0 with c1 (--no-commit combined with --ff=allow)' '\n+       git reset --hard x0 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c1 --no-commit --ff=allow &&\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 (--no-commit combined with --ff=allow)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c2 --no-commit --ff=allow &&\n+       verify_merge file result.1-5 &&\n+       verify_head $c1 &&\n+       git commit &&\n+       verify_parents $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge c1 with x1 (pull --ff=allow)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git pull --ff=allow 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=allow)' '\n+       git reset --hard x2 &&\n+       test_tick &&\n+       git pull --ff=allow clone refs/heads/master &&\n+       verify_merge file result.1-5-13 &&\n+       verify_parents $x2 $x1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=allow)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git pull --ff=allow new refs/heads/master &&\n+       verify_merge file result.1 &&\n+       verify_merge file2 result.9\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge x0 with c1 (--squash combined with --ff=never)' '\n+       git reset --hard x0 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge c1 --squash --ff=never &&\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=never)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       test_must_fail git merge c2 --squash --ff=never &&\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=never)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge x0 --no-commit --ff=never &&\n+       verify_merge file result.1-5 &&\n+       verify_head $c1 &&\n+       git commit &&\n+       verify_parents $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge x0 with c1 (--no-commit combined with --ff=never)' '\n+       git reset --hard x0 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c1 --no-commit --ff=never &&\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 (--no-commit combined with --ff=never)' '\n+       git reset --hard c1 &&\n+       git config branch.master.mergeoptions \"\" &&\n+       test_tick &&\n+       git merge c2 --no-commit --ff=never &&\n+       verify_merge file result.1-5 &&\n+       verify_head $c1 &&\n+       git commit &&\n+       verify_parents $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+test_expect_success 'merge c1 with x1 (pull --ff=never)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git pull --ff=never clone refs/heads/master &&\n+       verify_merge file result.1-13 &&\n+       verify_parents $c1 $x1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge x2 with x1 (pull --ff=never)' '\n+       git reset --hard x2 &&\n+       test_tick &&\n+       git pull --ff=never clone refs/heads/master &&\n+       verify_merge file result.1-5-13 &&\n+       verify_parents $x2 $x1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=never)' '\n+       git reset --hard c1 &&\n+       test_tick &&\n+       git pull --ff=never new refs/heads/master &&\n+       verify_merge file result.1 &&\n+       verify_merge file2 result.9\n+'\n+\n+test_debug 'gitk --all'\n+\n test_done\n-- \nSverre Hvammen Johansen\n"},{"id":"75825","messageId":"46dff0320805020533u179e16cej2c4db3105252d0bd@mail.gmail.com","threadId":"13239","inReplyTo":"402c10cd0804232246i6f7cd946h955b75832cf32876@mail.gmail.com","subject":"Re: [PATCH 2/5] Introduce -ff=<fast forward option>","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-05-02T12:33:00Z","receivedAt":"2008-05-02T12:33:00Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"On Thu, Apr 24, 2008 at 1:46 PM, Sverre Hvammen Johansen\n<hvammen@gmail.com> wrote:\n> --ff now takes an argument allowing --ff to be written\n>  as --ff=allow and -no-ff to be written as --ff=never.\n>  This change allow other fast forward options to be\n>  introduced later.\n>\n>  See the documentation for a further explanation of these options.\n>\n>  Signed-off-by: Sverre Hvammen Johansen <hvammen@gmail.com>\n>  ---\n>   Documentation/fast-forward-options.txt |   44 ++++++++\n>   Documentation/git-merge.txt            |    6 +-\n>   Documentation/git-pull.txt             |    2 +\n>   Documentation/merge-options.txt        |    9 +-\n>   git-merge.sh                           |   47 +++++---\n>   git-pull.sh                            |    4 +-\n>   t/t7601-merge-ff-options.sh            |  188 ++++++++++++++++++++++++++++++++\n>   7 files changed, 277 insertions(+), 23 deletions(-)\n>   create mode 100644 Documentation/fast-forward-options.txt\n>\n>  diff --git a/Documentation/fast-forward-options.txt\n>  b/Documentation/fast-forward-options.txt\n>  new file mode 100644\n>  index 0000000..95d0e6f\n>  --- /dev/null\n>  +++ b/Documentation/fast-forward-options.txt\n>  @@ -0,0 +1,44 @@\n>  +FAST FORWARD OPTIONS\n>  +--------------------\n>  +\n>  +allow::\n>  +\n>  +       Do not generate a merge commit if the merge resolves as a\n>  +       fast-forward, only update the branch pointer.  This option is\n>  +       equivalent of '--ff' without any argument.  This is the\n>  +       default behavior.\n\nonly and never are both adverb，but allow is a verb. So how about using\nauto instead of allow?\n\n\n-- \nPing Yin\n"},{"id":"75962","messageId":"402c10cd0805031504t276e95ffx662004a25c85957f@mail.gmail.com","threadId":"13239","inReplyTo":"46dff0320805020533u179e16cej2c4db3105252d0bd@mail.gmail.com","subject":"Re: [PATCH 2/5] Introduce -ff=<fast forward option>","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-05-03T22:04:08Z","receivedAt":"2008-05-03T22:04:08Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":"On Fri, May 2, 2008 at 5:33 AM, Ping Yin <pkufranky@gmail.com> wrote:\n>  only and never are both adverb，but allow is a verb. So how about using\n>  auto instead of allow?\n\nI don;t intend to change this this late.  I think we are fine with the\ncurrent names.\n\n-- \nSverre Hvammen Johansen\n"}]}