{"thread":{"id":"12629","subject":"[RFC/PATCH] Additional fast forward strategies.","startedAt":"2008-03-11T03:04:38Z","lastAt":"2008-03-12T06:03:19Z","messageCount":4,"participants":["Sverre Hvammen Johansen","Junio C Hamano","Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"71644","messageId":"402c10cd0803102004x7892f01cledfef6f277fba26a@mail.gmail.com","threadId":"12629","inReplyTo":null,"subject":"[RFC/PATCH] Additional fast forward strategies.","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-03-11T03:04:38Z","receivedAt":"2008-03-11T03:04:38Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":">From 779142c6b22f032c877f550733e1bccc99aca761 Mon Sep 17 00:00:00 2001\nFrom: Sverre Hvammen Johansen <hvammen@gmail.com>\nDate: Sun, 9 Mar 2008 21:16:03 -0800\nSubject: [PATCH] Additional fast forward strategies.\n\nNew fast forward strategies, common, fork, path, and same\nis introduced.  These new fast forward strategies allows\nadditional work flows.\n\nFF strategy \"common\" does a fast-forward to the common ancestor\nof the specified heads.  The merge will fail unless HEAD is the\ncommon ancestor or HEAD can be fast-forwarded to the common ancestor.\n\nFF strategy \"fork\" does a fast-forward to the common ancestor\nof the real heads.  The merge will fail unless HEAD is the\ncommon ancestor of these heads or HEAD can be fast-forwarded\nto the common ancestor of the real heads.\n\nFF strategy \"path\" does a fast-forward to the first possible\nbranch that no other branches are ahead of.  HEAD will be\nfast-forwarded to such a branch if it exist.  If no such branch\nexist, HEAD is considered to be up to date.\n\nFF strategy \"same\" does a fast forward where all branches are\nrequired to point to the same commit.  HEAD will be\nfast-forwarded to this branch unless it is up to date.\n\nSigned-off-by: Sverre Hvammen Johansen <sj@black.local>\n---\n Documentation/fast-forward-strategies.txt |   25 ++\n git-merge.sh                              |   53 ++++-\n t/t7601-merge-ff-strategies.sh            |  373 +++++++++++++++++++++++++++++\n 3 files changed, 446 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/fast-forward-strategies.txt\nb/Documentation/fast-forward-strategies.txt\nindex 1d6da26..be94cfc 100644\n--- a/Documentation/fast-forward-strategies.txt\n+++ b/Documentation/fast-forward-strategies.txt\n@@ -14,3 +14,28 @@ only::\n \tOnly allow a fast-forward.  The merge will fail\n \tunless HEAD is up to date or the merge resolved as\n         a fast-forward.\n+\n+common::\n+\tFast-forward to the common ancestor of the specified\n+\tbranches if possible.  The merge will fail unless\n+\tHEAD is the common ancestor or HEAD can be\n+\tfast-forwarded to the common ancestor.\n+\n+fork::\n+\tFast-forward to the earliest fork if possible.\n+\tThe earliest fork is defined as the common ancestor\n+\tof the real branches.  The merge will fail unless\n+\tHEAD is the earliest fork or HEAD can be\n+\tfast-forwarded to the earliest fork.\n+\n+path::\n+\tFast-forward to the first possible branch that\n+\tno other branches are ahead of.  HEAD will be\n+\tfast-forwarded to such a branch if it exist.\n+\tIf no such branch exist, HEAD is considered to be\n+\tup to date.\n+\n+same::\n+\tThe merge will fail unless HEAD is up to date or\n+\tthe merge resolved as a fast-forward and each\n+\tbranch is pointing to the same commit.\ndiff --git a/git-merge.sh b/git-merge.sh\nindex 873e4cb..d474f03 100755\n--- a/git-merge.sh\n+++ b/git-merge.sh\n@@ -164,21 +164,21 @@ parse_config () {\n \t\t\tno_commit=t ;;\n \t\t--ff)\n \t\t\tcase \"$2\" in\n-\t\t\tallow|never|only)\n+\t\t\tallow|never|only|common|fork|path|same)\n \t\t\t\tfast_forward=$2 squash= no_commit= ; shift ;;\n \t\t\t-*)\n \t\t\t\tfast_forward=allow squash= no_commit= ;;\n \t\t\t*)\n-\t\t\t\tdie \"available fast-forward strategies are: allow, newer, and only\" ;;\n+\t\t\t\tdie \"available fast-forward strategies are: allow, newer, only,\ncommon, path\" ;;\n \t\t\tesac\n \t\t\t;;\n \t\t--ff=*)\n \t\t\tfast_forward=$(echo $1 |cut -d = -f 2) squash= no_commit=\n \t\t\tcase $fast_forward in\n-\t\t\t    allow|never|only)\n+\t\t\t    allow|never|only|common|fork|path|same)\n \t\t\t\t;;\n \t\t\t    *)\n-\t\t\t\tdie \"available fast-forward strategies are: allow, newer, and only\" ;;\n+\t\t\t\tdie \"available fast-forward strategies are: allow, newer, only,\ncommon, path\" ;;\n \t\t\tesac\n \t\t\t;;\n \t\t--no-ff)\n@@ -374,12 +374,22 @@ find_real_parents () {\n     done\n }\n\n-if test $fast_forward = never -o\n+if test $fast_forward = never -o $fast_forward = common\n then\n \treal_parents=\"$@\"\n \tff_head=$head\n else\n \tfind_real_parents \"$@\"\n+\tif test $fast_forward = same\n+\tthen\n+\t\tfor b in \"$@\"\n+\t\tdo\n+\t\t\tif test \"$b\" != \"$1\"\n+\t\t\tthen\n+\t\t\t\tdie \"Fast forward strategy same requires all heads to be the same\"\n+\t\t\tfi\n+\t\tdone\n+\tfi\n fi\n\n if test -n \"$real_parents\"\n@@ -387,6 +397,39 @@ then\n \tcase $fast_forward in\n \tonly)\n \t\tdie \"Fast forward strategy only can only handle one real parent\" ;;\n+\tsame)\n+\t\tdie \"Fast forward strategy same have unexpected parents\" ;;\n+\tpath)\n+\t\techo \"Ignoring branches $real_parents\"\n+\t\treal_parents=\n+\t\t;;\n+\tcommon|fork)\n+\t\tif test $fast_forward = fork\n+\t\tthen\n+\t\t\tcommon=$(git show-branch --merge-base $ff_head $real_parents)\n+\t\telse\n+\t\t\tcommon=$(git show-branch --merge-base $real_parents)\n+\t\tfi\n+\t\tif test -n \"$common\"\n+\t\tthen\n+\t\t\tcommon_h=$(git show-branch --merge-base $common $head)\n+\t\t\tif test \"$common_h\" = $head\n+\t\t\tthen\n+\t\t\t\tif test $common = $head\n+\t\t\t\tthen\n+\t\t\t\t\techo \"Ignoring all branches\"\n+\t\t\t\telse\n+\t\t\t\t\techo \"Ignoring all branches except for $common\"\n+\t\t\t\tfi\n+\t\t\t\tff_head=$common\n+\t\t\telse\n+\t\t\t\tdie \"HEAD is ahead of the common anchestor\"\n+\t\t\tfi\n+\t\telse\n+\t\t\tdie \"The specified branches does not have any common anchestor\"\n+\t\tfi\n+\t\treal_parents=\n+\t\t;;\n \tnever|allow)\n \t\tif test $head != $ff_head\n \t\tthen\ndiff --git a/t/t7601-merge-ff-strategies.sh b/t/t7601-merge-ff-strategies.sh\nindex 6c0a91a..43cbe81 100755\n--- a/t/t7601-merge-ff-strategies.sh\n+++ b/t/t7601-merge-ff-strategies.sh\n@@ -546,4 +546,377 @@ test_expect_success 'merge x0 with y2, c3, and c0' '\n\n test_debug 'gitk --all'\n\n+test_expect_success 'merge y2 with x0, c3, and c0 (--ff=path)' '\n+\tgit reset --hard y2 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path x0 c3 c0 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y2\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge x0 with y2, c3, and c0 (--ff=path)' '\n+\tgit reset --hard x0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path y2 c3 c0 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y2\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with x0, c3, and c0 (--ff=path)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path x0 c3 c0 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y2, c3, and c0 (--ff=path)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path y2 c3 c0 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y2\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with x0, y3, and c0 (--ff=path)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path x0 y3 c0 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y3\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with x0, c3, and y3 (--ff=path)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path x0 c3 y3 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y3\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y1, y2, and y3 (--ff=path)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=path y1 y2 y3 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y3\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y1 (--ff=common)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=common y1 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y1, y2, and y3 (--ff=common)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=common y1 y2 y3 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with c1 and c2 (--ff=common)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=common c1 c2 &&\n+\tverify_merge file result.0 &&\n+\tverify_head $c0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y1 and y2 (--ff=common)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=common y1 y2 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with y1 and y2 (--ff=common)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=common y1 y2 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with y1 and y2 c0 (--ff=common)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tif git merge --ff=common y1 y2 c0\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1 &&\n+\t\tverify_head $c1;\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with x1 and c2 (--ff=common)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tif git merge --ff=common x1 c2\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1 &&\n+\t\tverify_head $c1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with x0 (--ff=fork)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=fork x0 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y1, y2, and y3 (--ff=fork)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=fork y1 y2 y3 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y3\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with c1 and c2 (--ff=fork)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=fork c1 c2 &&\n+\tverify_merge file result.0 &&\n+\tverify_head $c0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c0 with y1 and y2 (--ff=fork)' '\n+\tgit reset --hard c0 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=fork y1 y2 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with y1 and y2 (--ff=fork)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=fork y1 y2 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with y1 and y2 c0 (--ff=fork)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=fork y1 y2 c0 &&\n+\tverify_merge file result.1-5 &&\n+\tverify_head $x0;\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with x1 and c2 (--ff=fork)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tif git merge --ff=fork x1 c2\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1 &&\n+\t\tverify_head $c1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with x1 (pull --ff=only)' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\tgit pull --ff=only clone refs/heads/master &&\n+\tverify_merge file result.1-13 &&\n+\tverify_head $x1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge x2 with x1 (pull --ff=only)' '\n+\tgit reset --hard x2 &&\n+\ttest_tick &&\n+\tif git pull --ff=only clone refs/heads/master\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.5-13 &&\n+\t\tverify_head $x2\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=only)' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\tif git pull --ff=only new refs/heads/master\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1 &&\n+\t\tverify_head $c1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=common)' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\tif git pull --ff=common new refs/heads/master\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1 &&\n+\t\tverify_head $c1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=fork)' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\tif git pull --ff=fork new refs/heads/master\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1 &&\n+\t\tverify_head $c1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with new repository (pull --ff=path)' '\n+\tgit reset --hard c1 &&\n+\ttest_tick &&\n+\tgit pull --ff=path new refs/heads/master &&\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 y1 and y1 (--ff=same)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=same y1 y1 &&\n+\tverify_merge file result.1-5-13 &&\n+\tverify_head $y1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge c1 with c0 and c0 (--ff=same)' '\n+\tgit reset --hard c1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tgit merge --ff=same c0 c0 &&\n+\tverify_merge file result.1 &&\n+\tverify_head $c1\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge x1 with c2 and c2 (--ff=same)' '\n+\tgit reset --hard x1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tif git merge --ff=same c2 c2\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1-13 &&\n+\t\tverify_head $x1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n+test_expect_success 'merge y1 with c1 and x1 (--ff=same)' '\n+\tgit reset --hard y1 &&\n+\tgit config branch.master.mergeoptions \"\" &&\n+\ttest_tick &&\n+\tif git merge --ff=same c1 x1\n+\tthen\n+\t\tfalse\n+\telse\n+\t\tverify_merge file result.1-5-13 &&\n+\t\tverify_head $y1\n+\tfi\n+'\n+\n+test_debug 'gitk --all'\n+\n test_done\n-- \n1.5.3.3\n\n-- \nSverre Hvammen Johansen\n"},{"id":"71656","messageId":"7v8x0pepl8.fsf@gitster.siamese.dyndns.org","threadId":"12629","inReplyTo":"402c10cd0803102004x7892f01cledfef6f277fba26a@mail.gmail.com","subject":"Re: [RFC/PATCH] Additional fast forward strategies.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-03-11T06:34:27Z","receivedAt":"2008-03-11T06:34:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Sverre Hvammen Johansen\" <hvammen@gmail.com> writes:\n\n>>From 779142c6b22f032c877f550733e1bccc99aca761 Mon Sep 17 00:00:00 2001\n> From: Sverre Hvammen Johansen <hvammen@gmail.com>\n> Date: Sun, 9 Mar 2008 21:16:03 -0800\n> Subject: [PATCH] Additional fast forward strategies.\n\nDitto..\n\n> New fast forward strategies, common, fork, path, and same\n> is introduced.  These new fast forward strategies allows\n> additional work flows.\n\nIs it sufficient to say \"allows additional work flows\" here?  I only see\nwhat they do, and do not see why these are needed/useful anywhere in the\nproposed commit log message nor documentation. \n\nYou need to illustrate the motivation after the above three-line paragraph\nand before the description of what each of them does below.  \"Suppose your\nhistory looks like this, and you and your group's workflow is like this.\nThen you would want to only allow these but want to forbid those for such\nand such reasons.\"  Then list what the \"FF options\" do.  After that, you\ncan conclude \"By using these FF options this way, you can achieve that\ncontrol like this...\"\n\nThen people might be convinced that \"these allow additional work flows\".\nWhat you wrote is insufficient, I am afraid.  At least to me.\n\n> +\tif test $fast_forward = same\n> +\tthen\n> +\t\tfor b in \"$@\"\n\n'in \"$@\"' is always redundant after \"for X\".\n\nMore seriously, why is the user forced to give more than one \"same\" thing\nto begin with?  The user can give a single thing and be done with it.\n"},{"id":"71670","messageId":"m37ig9zky7.fsf@localhost.localdomain","threadId":"12629","inReplyTo":"402c10cd0803102004x7892f01cledfef6f277fba26a@mail.gmail.com","subject":"Re: [RFC/PATCH] Additional fast forward strategies.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-03-11T09:09:12Z","receivedAt":"2008-03-11T09:09:12Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"\"Sverre Hvammen Johansen\" <hvammen@gmail.com> writes:\n\n> From: Sverre Hvammen Johansen <hvammen@gmail.com>\n> Subject: [PATCH] Additional fast forward strategies.\n> \n> New fast forward strategies, common, fork, path, and same\n> is introduced.  These new fast forward strategies allows\n> additional work flows.\n\nIt would be better (read: greater chance to be accepted) if you had\nprovided examples of those \"additional workflows\", best in EXAMPLES\nsection (or something like that) of fast-forward documentation, and\n\"see documentation\" (or something like that) in commit message.\n \n> FF strategy \"common\" does a fast-forward to the common ancestor\n> of the specified heads.  The merge will fail unless HEAD is the\n> common ancestor or HEAD can be fast-forwarded to the common ancestor.\n\nDon't you mean \"common descendant\" here?\n\n> FF strategy \"fork\" does a fast-forward to the common ancestor\n> of the real heads.  The merge will fail unless HEAD is the\n> common ancestor of these heads or HEAD can be fast-forwarded\n> to the common ancestor of the real heads.\n\nWhat is the difference between 'real heads' and 'soecified heads'?\nExample, please.\n\n> FF strategy \"path\" does a fast-forward to the first possible\n> branch that no other branches are ahead of.  HEAD will be\n> fast-forwarded to such a branch if it exist.  If no such branch\n> exist, HEAD is considered to be up to date.\n> \n> FF strategy \"same\" does a fast forward where all branches are\n> required to point to the same commit.  HEAD will be\n> fast-forwarded to this branch unless it is up to date.\n> \n> Signed-off-by: Sverre Hvammen Johansen <sj@black.local>\n\nIt will be easier to understand those descriptions if you have\nprovided with ASCII-art diagrams (in the documentation, not\nnecessarily in fast-forward strategies^W options description, but\nperhaps somewhere below, above FAST-FORWARD OPTIONS EXAMPLES section).\n\nFor example, by default you can fast-forward only when doing single\nbranch merge.\n\n%%\n\n  A---B---C---D   <--- master <--- HEAD\n       \\\n        \\-1---2   <--- a\n\nIf you have situation as above, you are on branch 'master',\nand you do \"git merge a\" it would result in merge commit.\n\n  A---B---C---D---M   <--- master <--- HEAD\n       \\         /\n        \\-1---2-/     <--- a\n\n%%\n\n  A---B           <--- master <--- HEAD\n       \\\n        \\-1---2   <--- a\n\nIf you have situation as above, you are on branch 'master',\nand you do \"git merge a\" it would result in fast-forward.\n\n  A---B---1---2   <--- master <--- HEAD\n                    \n              ^------- a\n\nor\n\n  A---B---1---2   <--- master <--- HEAD\n              ^      \n               \\------ a\n\n\n%%\n\n  A---B           <--- master <--- HEAD\n       \\\n        \\-1---2   <--- a\n              \n              ^------- b\n\nThis I think is 'FF strategy \"same\"' situation.\n\n%%\n\n  A---B              <--- master <--- HEAD\n       \\\n        \\-1---2      <--- a\n               \\\n                \\-3  <--- b\n\nThis I guess is either 'common' or 'fork' situation.\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"71785","messageId":"402c10cd0803112303r4eb7c98fgf129c1387fdf55f6@mail.gmail.com","threadId":"12629","inReplyTo":"402c10cd0803102004x7892f01cledfef6f277fba26a@mail.gmail.com","subject":"Re: [RFC/PATCH] Additional fast forward strategies.","fromName":"Sverre Hvammen Johansen","fromEmail":"hvammen@gmail.com","sentAt":"2008-03-12T06:03:19Z","receivedAt":"2008-03-12T06:03:19Z","isPatch":true,"sender":{"key":"hvammen@gmail.com","avatar":"https://gravatar.com/avatar/d1fc25ec327eea135af60fe7b56b2a2e21f711aa32167e7f505014ec88aa24bc?d=mp&s=160"},"body":"I may drop this patch or at least not prioritize it for now.  I don't\nneed it and implemented it just for fun.  There are other features\nthat are fare more important.  The other patch I am working on that\nimplement \"--ff=only\" is something I need\n\n-- \nSverre Hvammen Johansen\n"}]}