{"thread":{"id":"34836","subject":"[PATCH 0/6] Preparation for non-ff pulls by default","startedAt":"2013-09-02T22:17:52Z","lastAt":"2013-09-02T22:17:58Z","messageCount":7,"participants":["Felipe Contreras"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"226561","messageId":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":null,"subject":"[PATCH 0/6] Preparation for non-ff pulls by default","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:52Z","receivedAt":"2013-09-02T22:17:52Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"It is very typical for Git newcomers to inadvertently create merges and worst:\ninadvertently pushing them. This is one of the reasons many experienced users\nprefer to avoid 'git pull', and recommend newcomers to avoid it as well.\n\nTo avoid these problems and keep 'git pull' useful, it has been suggested\nthat 'git pull' barfs by default if the merge is non-fast-forward, which\nunfortunately would break backwards compatibility.\n\nThis patch series leaves everything in place to enable this new mode, but it\nonly gets enabled if the user specifically configures it; pull.mode =\nmerge-ff-only.\n\nLater on this mode can be enabled by default (e.g. in v2.0).\n\nTo achieve that first some configurations are renamed: for example: pull.rebase\n=> pull.mode = rebase, but the old ones remain functional, thus there are no\nfunctional changes.\n\nFelipe Contreras (6):\n  merge: simplify ff-only option\n  t: replace pulls with merges\n  pull: rename pull.rename to pull.mode\n  pull: refactor $rebase variable into $mode\n  pull: add --merge option\n  pull: add merge-ff-only option\n\n Documentation/config.txt               | 24 +++++++------\n Documentation/git-pull.txt             | 10 ++++--\n branch.c                               |  4 +--\n builtin/merge.c                        | 20 +++++------\n git-pull.sh                            | 49 ++++++++++++++++++++-------\n t/annotate-tests.sh                    |  2 +-\n t/t3200-branch.sh                      | 40 +++++++++++-----------\n t/t4200-rerere.sh                      |  2 +-\n t/t5520-pull.sh                        | 62 ++++++++++++++++++++++++++++++++++\n t/t5601-clone.sh                       |  4 +--\n t/t9114-git-svn-dcommit-merge.sh       |  2 +-\n t/t9500-gitweb-standalone-no-errors.sh |  2 +-\n 12 files changed, 157 insertions(+), 64 deletions(-)\n\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226562","messageId":"1378160278-14872-2-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 1/6] merge: simplify ff-only option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:53Z","receivedAt":"2013-09-02T22:17:53Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"No functional changes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n builtin/merge.c | 11 ++---------\n 1 file changed, 2 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 34a6166..da9fc08 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -186,13 +186,6 @@ static int option_parse_n(const struct option *opt,\n \treturn 0;\n }\n \n-static int option_parse_ff_only(const struct option *opt,\n-\t\t\t  const char *arg, int unset)\n-{\n-\tfast_forward = FF_ONLY;\n-\treturn 0;\n-}\n-\n static struct option builtin_merge_options[] = {\n \t{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,\n \t\tN_(\"do not show a diffstat at the end of the merge\"),\n@@ -210,9 +203,9 @@ static struct option builtin_merge_options[] = {\n \tOPT_BOOL('e', \"edit\", &option_edit,\n \t\tN_(\"edit message before committing\")),\n \tOPT_SET_INT(0, \"ff\", &fast_forward, N_(\"allow fast-forward (default)\"), FF_ALLOW),\n-\t{ OPTION_CALLBACK, 0, \"ff-only\", NULL, NULL,\n+\t{ OPTION_SET_INT, 0, \"ff-only\", &fast_forward, NULL,\n \t\tN_(\"abort if fast-forward is not possible\"),\n-\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, option_parse_ff_only },\n+\t\tPARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, FF_ONLY },\n \tOPT_RERERE_AUTOUPDATE(&allow_rerere_auto),\n \tOPT_BOOL(0, \"verify-signatures\", &verify_signatures,\n \t\tN_(\"Verify that the named commit has a valid GPG signature\")),\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226563","messageId":"1378160278-14872-3-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 2/6] t: replace pulls with merges","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:54Z","receivedAt":"2013-09-02T22:17:54Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"This is what the code intended.\n\nNo functional changes.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/annotate-tests.sh                    | 2 +-\n t/t4200-rerere.sh                      | 2 +-\n t/t9114-git-svn-dcommit-merge.sh       | 2 +-\n t/t9500-gitweb-standalone-no-errors.sh | 2 +-\n 4 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/annotate-tests.sh b/t/annotate-tests.sh\nindex d4e7f47..01deece 100644\n--- a/t/annotate-tests.sh\n+++ b/t/annotate-tests.sh\n@@ -92,7 +92,7 @@ test_expect_success 'blame 2 authors + 1 branch2 author' '\n '\n \n test_expect_success 'merge branch1 & branch2' '\n-\tgit pull . branch1\n+\tgit merge branch1\n '\n \n test_expect_success 'blame 2 authors + 2 merged-in authors' '\ndiff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh\nindex 7f6666f..cf19eb7 100755\n--- a/t/t4200-rerere.sh\n+++ b/t/t4200-rerere.sh\n@@ -172,7 +172,7 @@ test_expect_success 'first postimage wins' '\n \tgit show second^:a1 | sed \"s/To die: t/To die! T/\" >a1 &&\n \tgit commit -q -a -m third &&\n \n-\ttest_must_fail git pull . first &&\n+\ttest_must_fail git merge first &&\n \t# rerere kicked in\n \t! grep \"^=======\\$\" a1 &&\n \ttest_cmp expect a1\ndiff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh\nindex f524d2f..d33d714 100755\n--- a/t/t9114-git-svn-dcommit-merge.sh\n+++ b/t/t9114-git-svn-dcommit-merge.sh\n@@ -62,7 +62,7 @@ test_expect_success 'setup git mirror and merge' '\n \techo friend > README &&\n \tcat tmp >> README &&\n \tgit commit -a -m \"friend\" &&\n-\tgit pull . merge\n+\tgit merge merge\n \t'\n \n test_debug 'gitk --all & sleep 1'\ndiff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh\nindex 6fca193..3864388 100755\n--- a/t/t9500-gitweb-standalone-no-errors.sh\n+++ b/t/t9500-gitweb-standalone-no-errors.sh\n@@ -328,7 +328,7 @@ test_expect_success \\\n \t git add b &&\n \t git commit -a -m \"On branch\" &&\n \t git checkout master &&\n-\t git pull . b &&\n+\t git merge b &&\n \t git tag merge_commit'\n \n test_expect_success \\\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226564","messageId":"1378160278-14872-4-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 3/6] pull: rename pull.rename to pull.mode","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:55Z","receivedAt":"2013-09-02T22:17:55Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Also 'branch.<name>.rebase' to 'branch.<name>.pullmode'.\n\nThis way 'pull.mode' can be set to 'merge', and the default can be\nsomething else.\n\nThe old configurations still work, but get deprecated.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/config.txt   | 22 +++++++++++-----------\n Documentation/git-pull.txt |  2 +-\n branch.c                   |  4 ++--\n git-pull.sh                | 18 ++++++++++++++++--\n t/t3200-branch.sh          | 40 ++++++++++++++++++++--------------------\n t/t5520-pull.sh            | 26 ++++++++++++++++++++++++++\n t/t5601-clone.sh           |  4 ++--\n 7 files changed, 78 insertions(+), 38 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex ec57a15..9489a59 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -706,7 +706,7 @@ branch.autosetupmerge::\n branch.autosetuprebase::\n \tWhen a new branch is created with 'git branch' or 'git checkout'\n \tthat tracks another branch, this variable tells Git to set\n-\tup pull to rebase instead of merge (see \"branch.<name>.rebase\").\n+\tup pull to rebase instead of merge (see \"branch.<name>.pullmode\").\n \tWhen `never`, rebase is never automatically set to true.\n \tWhen `local`, rebase is set to true for tracked branches of\n \tother local branches.\n@@ -760,11 +760,11 @@ branch.<name>.mergeoptions::\n \toption values containing whitespace characters are currently not\n \tsupported.\n \n-branch.<name>.rebase::\n-\tWhen true, rebase the branch <name> on top of the fetched branch,\n-\tinstead of merging the default branch from the default remote when\n-\t\"git pull\" is run. See \"pull.rebase\" for doing this in a non\n-\tbranch-specific manner.\n+branch.<name>.pullmode::\n+\tWhen \"git pull\" is run, this determines if it would either merge or\n+\trebase the fetched branch. The possible values are 'merge' and\n+\t'rebase'. See \"pull.mode\" for doing this in a non branch-specific\n+\tmanner.\n +\n *NOTE*: this is a possibly dangerous operation; do *not* use\n it unless you understand the implications (see linkgit:git-rebase[1]\n@@ -1820,11 +1820,11 @@ pretty.<name>::\n \tNote that an alias with the same name as a built-in format\n \twill be silently ignored.\n \n-pull.rebase::\n-\tWhen true, rebase branches on top of the fetched branch, instead\n-\tof merging the default branch from the default remote when \"git\n-\tpull\" is run. See \"branch.<name>.rebase\" for setting this on a\n-\tper-branch basis.\n+pull.mode::\n+\tWhen \"git pull\" is run, this determines if it would either merge or\n+\trebase the fetched branch. The possible values are 'merge' and\n+\t'rebase'. See \"branch.<name>.pullmode\" for doing this in a non\n+\tbranch-specific manner.\n +\n *NOTE*: this is a possibly dangerous operation; do *not* use\n it unless you understand the implications (see linkgit:git-rebase[1]\ndiff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt\nindex 6ef8d59..991352f 100644\n--- a/Documentation/git-pull.txt\n+++ b/Documentation/git-pull.txt\n@@ -109,7 +109,7 @@ include::merge-options.txt[]\n \tfetched, the rebase uses that information to avoid rebasing\n \tnon-local changes.\n +\n-See `pull.rebase`, `branch.<name>.rebase` and `branch.autosetuprebase` in\n+See `pull.mode`, `branch.<name>.pullmode` and `branch.autosetuprebase` in\n linkgit:git-config[1] if you want to make `git pull` always use\n `--rebase` instead of merging.\n +\ndiff --git a/branch.c b/branch.c\nindex c5c6984..c6b70c2 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -71,8 +71,8 @@ void install_branch_config(int flag, const char *local, const char *origin, cons\n \n \tif (rebasing) {\n \t\tstrbuf_reset(&key);\n-\t\tstrbuf_addf(&key, \"branch.%s.rebase\", local);\n-\t\tgit_config_set(key.buf, \"true\");\n+\t\tstrbuf_addf(&key, \"branch.%s.pullmode\", local);\n+\t\tgit_config_set(key.buf, \"rebase\");\n \t}\n \tstrbuf_release(&key);\n \ndiff --git a/git-pull.sh b/git-pull.sh\nindex f0df41c..de57c1d 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -43,10 +43,24 @@ log_arg= verbosity= progress= recurse_submodules= verify_signatures=\n merge_args= edit=\n curr_branch=$(git symbolic-ref -q HEAD)\n curr_branch_short=\"${curr_branch#refs/heads/}\"\n-rebase=$(git config --bool branch.$curr_branch_short.rebase)\n+mode=$(git config branch.${curr_branch_short}.pullmode)\n+if test -z \"$mode\"\n+then\n+\tmode=$(git config pull.mode)\n+fi\n+test \"$mode\" == 'rebase' && rebase=\"true\"\n if test -z \"$rebase\"\n then\n-\trebase=$(git config --bool pull.rebase)\n+\trebase=$(git config --bool branch.$curr_branch_short.rebase)\n+\tif test -z \"$rebase\"\n+\tthen\n+\t\trebase=$(git config --bool pull.rebase)\n+\tfi\n+\tif test \"$rebase\" = 'true'\n+\tthen\n+\t\techo \"The configurations pull.rebase and branch.<name>.rebase are deprecated.\"\n+\t\techo \"Please use pull.mode and branch.<name>.pullmode instead.\"\n+\tfi\n fi\n dry_run=\n while :\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex 44ec6a4..b620798 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -557,7 +557,7 @@ test_expect_success 'autosetuprebase local on a tracked local branch' '\n \tgit branch --track myr1 mybase &&\n \ttest \"$(git config branch.myr1.remote)\" = . &&\n \ttest \"$(git config branch.myr1.merge)\" = refs/heads/mybase &&\n-\ttest \"$(git config branch.myr1.rebase)\" = true\n+\ttest \"$(git config branch.myr1.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase always on a tracked local branch' '\n@@ -569,7 +569,7 @@ test_expect_success 'autosetuprebase always on a tracked local branch' '\n \tgit branch --track myr2 mybase &&\n \ttest \"$(git config branch.myr2.remote)\" = . &&\n \ttest \"$(git config branch.myr2.merge)\" = refs/heads/mybase &&\n-\ttest \"$(git config branch.myr2.rebase)\" = true\n+\ttest \"$(git config branch.myr2.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase remote on a tracked local branch' '\n@@ -581,7 +581,7 @@ test_expect_success 'autosetuprebase remote on a tracked local branch' '\n \tgit branch --track myr3 mybase2 &&\n \ttest \"$(git config branch.myr3.remote)\" = . &&\n \ttest \"$(git config branch.myr3.merge)\" = refs/heads/mybase2 &&\n-\t! test \"$(git config branch.myr3.rebase)\" = true\n+\t! test \"$(git config branch.myr3.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase never on a tracked local branch' '\n@@ -593,7 +593,7 @@ test_expect_success 'autosetuprebase never on a tracked local branch' '\n \tgit branch --track myr4 mybase2 &&\n \ttest \"$(git config branch.myr4.remote)\" = . &&\n \ttest \"$(git config branch.myr4.merge)\" = refs/heads/mybase2 &&\n-\t! test \"$(git config branch.myr4.rebase)\" = true\n+\t! test \"$(git config branch.myr4.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase local on a tracked remote branch' '\n@@ -604,7 +604,7 @@ test_expect_success 'autosetuprebase local on a tracked remote branch' '\n \tgit branch --track myr5 local/master &&\n \ttest \"$(git config branch.myr5.remote)\" = local &&\n \ttest \"$(git config branch.myr5.merge)\" = refs/heads/master &&\n-\t! test \"$(git config branch.myr5.rebase)\" = true\n+\t! test \"$(git config branch.myr5.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase never on a tracked remote branch' '\n@@ -615,7 +615,7 @@ test_expect_success 'autosetuprebase never on a tracked remote branch' '\n \tgit branch --track myr6 local/master &&\n \ttest \"$(git config branch.myr6.remote)\" = local &&\n \ttest \"$(git config branch.myr6.merge)\" = refs/heads/master &&\n-\t! test \"$(git config branch.myr6.rebase)\" = true\n+\t! test \"$(git config branch.myr6.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase remote on a tracked remote branch' '\n@@ -626,7 +626,7 @@ test_expect_success 'autosetuprebase remote on a tracked remote branch' '\n \tgit branch --track myr7 local/master &&\n \ttest \"$(git config branch.myr7.remote)\" = local &&\n \ttest \"$(git config branch.myr7.merge)\" = refs/heads/master &&\n-\ttest \"$(git config branch.myr7.rebase)\" = true\n+\ttest \"$(git config branch.myr7.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase always on a tracked remote branch' '\n@@ -637,7 +637,7 @@ test_expect_success 'autosetuprebase always on a tracked remote branch' '\n \tgit branch --track myr8 local/master &&\n \ttest \"$(git config branch.myr8.remote)\" = local &&\n \ttest \"$(git config branch.myr8.merge)\" = refs/heads/master &&\n-\ttest \"$(git config branch.myr8.rebase)\" = true\n+\ttest \"$(git config branch.myr8.pullmode)\" = rebase\n '\n \n test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' '\n@@ -648,7 +648,7 @@ test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' '\n \tgit branch --track myr9 local/master &&\n \ttest \"$(git config branch.myr9.remote)\" = local &&\n \ttest \"$(git config branch.myr9.merge)\" = refs/heads/master &&\n-\ttest \"z$(git config branch.myr9.rebase)\" = z\n+\ttest \"z$(git config branch.myr9.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase unconfigured on a tracked local branch' '\n@@ -659,7 +659,7 @@ test_expect_success 'autosetuprebase unconfigured on a tracked local branch' '\n \tgit branch --track myr10 mybase2 &&\n \ttest \"$(git config branch.myr10.remote)\" = . &&\n \ttest \"$(git config branch.myr10.merge)\" = refs/heads/mybase2 &&\n-\ttest \"z$(git config branch.myr10.rebase)\" = z\n+\ttest \"z$(git config branch.myr10.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase unconfigured on untracked local branch' '\n@@ -669,7 +669,7 @@ test_expect_success 'autosetuprebase unconfigured on untracked local branch' '\n \tgit branch --no-track myr11 mybase2 &&\n \ttest \"z$(git config branch.myr11.remote)\" = z &&\n \ttest \"z$(git config branch.myr11.merge)\" = z &&\n-\ttest \"z$(git config branch.myr11.rebase)\" = z\n+\ttest \"z$(git config branch.myr11.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase unconfigured on untracked remote branch' '\n@@ -679,7 +679,7 @@ test_expect_success 'autosetuprebase unconfigured on untracked remote branch' '\n \tgit branch --no-track myr12 local/master &&\n \ttest \"z$(git config branch.myr12.remote)\" = z &&\n \ttest \"z$(git config branch.myr12.merge)\" = z &&\n-\ttest \"z$(git config branch.myr12.rebase)\" = z\n+\ttest \"z$(git config branch.myr12.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase never on an untracked local branch' '\n@@ -690,7 +690,7 @@ test_expect_success 'autosetuprebase never on an untracked local branch' '\n \tgit branch --no-track myr13 mybase2 &&\n \ttest \"z$(git config branch.myr13.remote)\" = z &&\n \ttest \"z$(git config branch.myr13.merge)\" = z &&\n-\ttest \"z$(git config branch.myr13.rebase)\" = z\n+\ttest \"z$(git config branch.myr13.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase local on an untracked local branch' '\n@@ -701,7 +701,7 @@ test_expect_success 'autosetuprebase local on an untracked local branch' '\n \tgit branch --no-track myr14 mybase2 &&\n \ttest \"z$(git config branch.myr14.remote)\" = z &&\n \ttest \"z$(git config branch.myr14.merge)\" = z &&\n-\ttest \"z$(git config branch.myr14.rebase)\" = z\n+\ttest \"z$(git config branch.myr14.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase remote on an untracked local branch' '\n@@ -712,7 +712,7 @@ test_expect_success 'autosetuprebase remote on an untracked local branch' '\n \tgit branch --no-track myr15 mybase2 &&\n \ttest \"z$(git config branch.myr15.remote)\" = z &&\n \ttest \"z$(git config branch.myr15.merge)\" = z &&\n-\ttest \"z$(git config branch.myr15.rebase)\" = z\n+\ttest \"z$(git config branch.myr15.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase always on an untracked local branch' '\n@@ -723,7 +723,7 @@ test_expect_success 'autosetuprebase always on an untracked local branch' '\n \tgit branch --no-track myr16 mybase2 &&\n \ttest \"z$(git config branch.myr16.remote)\" = z &&\n \ttest \"z$(git config branch.myr16.merge)\" = z &&\n-\ttest \"z$(git config branch.myr16.rebase)\" = z\n+\ttest \"z$(git config branch.myr16.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase never on an untracked remote branch' '\n@@ -734,7 +734,7 @@ test_expect_success 'autosetuprebase never on an untracked remote branch' '\n \tgit branch --no-track myr17 local/master &&\n \ttest \"z$(git config branch.myr17.remote)\" = z &&\n \ttest \"z$(git config branch.myr17.merge)\" = z &&\n-\ttest \"z$(git config branch.myr17.rebase)\" = z\n+\ttest \"z$(git config branch.myr17.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase local on an untracked remote branch' '\n@@ -745,7 +745,7 @@ test_expect_success 'autosetuprebase local on an untracked remote branch' '\n \tgit branch --no-track myr18 local/master &&\n \ttest \"z$(git config branch.myr18.remote)\" = z &&\n \ttest \"z$(git config branch.myr18.merge)\" = z &&\n-\ttest \"z$(git config branch.myr18.rebase)\" = z\n+\ttest \"z$(git config branch.myr18.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase remote on an untracked remote branch' '\n@@ -756,7 +756,7 @@ test_expect_success 'autosetuprebase remote on an untracked remote branch' '\n \tgit branch --no-track myr19 local/master &&\n \ttest \"z$(git config branch.myr19.remote)\" = z &&\n \ttest \"z$(git config branch.myr19.merge)\" = z &&\n-\ttest \"z$(git config branch.myr19.rebase)\" = z\n+\ttest \"z$(git config branch.myr19.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase always on an untracked remote branch' '\n@@ -767,7 +767,7 @@ test_expect_success 'autosetuprebase always on an untracked remote branch' '\n \tgit branch --no-track myr20 local/master &&\n \ttest \"z$(git config branch.myr20.remote)\" = z &&\n \ttest \"z$(git config branch.myr20.merge)\" = z &&\n-\ttest \"z$(git config branch.myr20.rebase)\" = z\n+\ttest \"z$(git config branch.myr20.pullmode)\" = z\n '\n \n test_expect_success 'autosetuprebase always on detached HEAD' '\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex ed4d9c8..978a3c1 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -284,4 +284,30 @@ test_expect_success 'git pull --rebase against local branch' '\n \ttest file = \"$(cat file2)\"\n '\n \n+test_expect_success 'pull.mode' '\n+\tgit checkout to-rebase &&\n+\tgit reset --hard before-rebase &&\n+\ttest_config pull.mode rebase &&\n+\tgit pull . copy &&\n+\ttest $(git rev-parse HEAD^) = $(git rev-parse copy) &&\n+\ttest new = $(git show HEAD:file2)\n+'\n+\n+test_expect_success 'branch.to-rebase.pullmode' '\n+\tgit reset --hard before-rebase &&\n+\ttest_config branch.to-rebase.pullmode rebase &&\n+\tgit pull . copy &&\n+\ttest $(git rev-parse HEAD^) = $(git rev-parse copy) &&\n+\ttest new = $(git show HEAD:file2)\n+'\n+\n+test_expect_success 'branch.to-rebase.pullmode should override pull.mode' '\n+\tgit reset --hard before-rebase &&\n+\ttest_config pull.mode rebase &&\n+\ttest_config branch.to-rebase.pullmode merge &&\n+\tgit pull . copy &&\n+\ttest $(git rev-parse HEAD^) != $(git rev-parse copy) &&\n+\ttest new = $(git show HEAD:file2)\n+'\n+\n test_done\ndiff --git a/t/t5601-clone.sh b/t/t5601-clone.sh\nindex 0629149..6c888ae 100755\n--- a/t/t5601-clone.sh\n+++ b/t/t5601-clone.sh\n@@ -191,8 +191,8 @@ test_expect_success 'clone respects global branch.autosetuprebase' '\n \t\trm -fr dst &&\n \t\tgit clone src dst &&\n \t\tcd dst &&\n-\t\tactual=\"z$(git config branch.master.rebase)\" &&\n-\t\ttest ztrue = $actual\n+\t\tactual=\"$(git config branch.master.pullmode)\" &&\n+\t\ttest \"$actual\" = rebase\n \t)\n '\n \n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226567","messageId":"1378160278-14872-5-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 4/6] pull: refactor $rebase variable into $mode","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:56Z","receivedAt":"2013-09-02T22:17:56Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n git-pull.sh | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex de57c1d..f53d193 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -48,8 +48,7 @@ if test -z \"$mode\"\n then\n \tmode=$(git config pull.mode)\n fi\n-test \"$mode\" == 'rebase' && rebase=\"true\"\n-if test -z \"$rebase\"\n+if test -z \"$mode\"\n then\n \trebase=$(git config --bool branch.$curr_branch_short.rebase)\n \tif test -z \"$rebase\"\n@@ -58,6 +57,7 @@ then\n \tfi\n \tif test \"$rebase\" = 'true'\n \tthen\n+\t\tmode=\"rebase\"\n \t\techo \"The configurations pull.rebase and branch.<name>.rebase are deprecated.\"\n \t\techo \"Please use pull.mode and branch.<name>.pullmode instead.\"\n \tfi\n@@ -125,10 +125,10 @@ do\n \t\tmerge_args=\"$merge_args$xx \"\n \t\t;;\n \t-r|--r|--re|--reb|--reba|--rebas|--rebase)\n-\t\trebase=true\n+\t\tmode=rebase\n \t\t;;\n \t--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)\n-\t\trebase=false\n+\t\tmode=\n \t\t;;\n \t--recurse-submodules)\n \t\trecurse_submodules=--recurse-submodules\n@@ -171,7 +171,7 @@ error_on_no_merge_candidates () {\n \t\tesac\n \tdone\n \n-\tif test true = \"$rebase\"\n+\tif test \"$mode\" = rebase\n \tthen\n \t\top_type=rebase\n \t\top_prep=against\n@@ -185,7 +185,7 @@ error_on_no_merge_candidates () {\n \tremote=$(git config \"branch.$curr_branch.remote\")\n \n \tif [ $# -gt 1 ]; then\n-\t\tif [ \"$rebase\" = true ]; then\n+\t\tif [ \"$mode\" = rebase ]; then\n \t\t\tprintf \"There is no candidate for rebasing against \"\n \t\telse\n \t\t\tprintf \"There are no candidates for merging \"\n@@ -208,7 +208,7 @@ error_on_no_merge_candidates () {\n \texit 1\n }\n \n-test true = \"$rebase\" && {\n+test \"$mode\" = rebase && {\n \tif ! git rev-parse -q --verify HEAD >/dev/null\n \tthen\n \t\t# On an unborn branch\n@@ -273,7 +273,7 @@ case \"$merge_head\" in\n \tthen\n \t\tdie \"$(gettext \"Cannot merge multiple branches into empty head\")\"\n \tfi\n-\tif test true = \"$rebase\"\n+\tif test \"$mode\" = rebase\n \tthen\n \t\tdie \"$(gettext \"Cannot rebase onto multiple branches\")\"\n \tfi\n@@ -294,7 +294,7 @@ then\n \texit\n fi\n \n-if test true = \"$rebase\"\n+if test \"$mode\" = rebase\n then\n \to=$(git show-branch --merge-base $curr_branch $merge_head $oldremoteref)\n \tif test \"$oldremoteref\" = \"$o\"\n@@ -304,8 +304,8 @@ then\n fi\n \n merge_name=$(git fmt-merge-msg $log_arg <\"$GIT_DIR/FETCH_HEAD\") || exit\n-case \"$rebase\" in\n-true)\n+case \"$mode\" in\n+rebase)\n \teval=\"git-rebase $diffstat $strategy_args $merge_args $verbosity\"\n \teval=\"$eval --onto $merge_head ${oldremoteref:-$merge_head}\"\n \t;;\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226566","messageId":"1378160278-14872-6-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 5/6] pull: add --merge option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:57Z","receivedAt":"2013-09-02T22:17:57Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Also, deprecate --no-rebase since there's no need for it any more.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/git-pull.txt | 8 ++++++--\n git-pull.sh                | 6 +++++-\n 2 files changed, 11 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt\nindex 991352f..e09f004 100644\n--- a/Documentation/git-pull.txt\n+++ b/Documentation/git-pull.txt\n@@ -119,8 +119,12 @@ It rewrites history, which does not bode well when you\n published that history already.  Do *not* use this option\n unless you have read linkgit:git-rebase[1] carefully.\n \n---no-rebase::\n-\tOverride earlier --rebase.\n+-m::\n+--merge::\n+\tForce a merge.\n++\n+See `pull.mode`, `branch.<name>.pullmode` in linkgit:git-config[1] if you want\n+to make `git pull` always use `--merge`.\n \n Options related to fetching\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~\ndiff --git a/git-pull.sh b/git-pull.sh\nindex f53d193..fbb8a9b 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -127,8 +127,12 @@ do\n \t-r|--r|--re|--reb|--reba|--rebas|--rebase)\n \t\tmode=rebase\n \t\t;;\n+\t-m|--m|--me|--mer|--merg|--merge)\n+\t\tmode=merge\n+\t\t;;\n \t--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)\n-\t\tmode=\n+\t\tmode=merge\n+\t\techo \"--no-rebase is deprecated, please use --merge instead\"\n \t\t;;\n \t--recurse-submodules)\n \t\trecurse_submodules=--recurse-submodules\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226565","messageId":"1378160278-14872-7-git-send-email-felipe.contreras@gmail.com","threadId":"34836","inReplyTo":"1378160278-14872-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 6/6] pull: add merge-ff-only option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T22:17:58Z","receivedAt":"2013-09-02T22:17:58Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"It is very typical for Git newcomers to inadvertently create merges and\nworst, inadvertently pushing them. This is one of the reasons many\nexperienced users prefer to avoid 'git pull', and recommend newcomers to\navoid it as well.\n\nTo avoid these problems and keep 'git pull' useful it has been suggested\nthat 'git pull' barfs by default if the merge is non-fast-forward, which\nunfortunately would break backwards compatibility.\n\nThis patch leaves everything in place to enable this new mode, but it\nonly gets enabled if the user specifically configures it; pull.mode =\nmerge-ff-only.\n\nLater on this mode can be enabled by default (e.g. in v2.0).\n\nFor the full discussion you can read:\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/225146/focus=225305\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/config.txt |  8 +++++---\n builtin/merge.c          |  9 ++++++++-\n git-pull.sh              |  7 +++++++\n t/t5520-pull.sh          | 36 ++++++++++++++++++++++++++++++++++++\n 4 files changed, 56 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 9489a59..13635e0 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1822,9 +1822,11 @@ pretty.<name>::\n \n pull.mode::\n \tWhen \"git pull\" is run, this determines if it would either merge or\n-\trebase the fetched branch. The possible values are 'merge' and\n-\t'rebase'. See \"branch.<name>.pullmode\" for doing this in a non\n-\tbranch-specific manner.\n+\trebase the fetched branch. The possible values are 'merge',\n+\t'rebase', and 'merge-ff-only'. If 'merge-ff-only' is specified, the\n+\tmerge will only succeed if it's fast-forward. See\n+\t\"branch.<name>.pullmode\" for doing this in a non branch-specific\n+\tmanner.\n +\n *NOTE*: this is a possibly dangerous operation; do *not* use\n it unless you understand the implications (see linkgit:git-rebase[1]\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex da9fc08..97b4205 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -1437,8 +1437,15 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \n-\tif (fast_forward == FF_ONLY)\n+\tif (fast_forward == FF_ONLY) {\n+\t\tconst char *msg = getenv(\"GIT_MERGE_FF_ONLY_HELP\");\n+\t\tif (msg) {\n+\t\t\tfprintf(stderr, \"%s\\n\", msg);\n+\t\t\tret = 1;\n+\t\t\tgoto done;\n+\t\t}\n \t\tdie(_(\"Not possible to fast-forward, aborting.\"));\n+\t}\n \n \t/* We are going to make a new commit. */\n \tgit_committer_info(IDENT_STRICT);\ndiff --git a/git-pull.sh b/git-pull.sh\nindex fbb8a9b..a9cf7ac 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -62,6 +62,7 @@ then\n \t\techo \"Please use pull.mode and branch.<name>.pullmode instead.\"\n \tfi\n fi\n+test -z \"$mode\" && mode=merge\n dry_run=\n while :\n do\n@@ -307,6 +308,12 @@ then\n \tfi\n fi\n \n+if test \"$mode\" = merge-ff-only -a -z \"$no_ff$ff_only${squash#--no-squash}\"\n+then\n+\tff_only=--ff-only\n+\texport GIT_MERGE_FF_ONLY_HELP=\"The pull was not fast-forward, please either merge or rebase.\"\n+fi\n+\n merge_name=$(git fmt-merge-msg $log_arg <\"$GIT_DIR/FETCH_HEAD\") || exit\n case \"$mode\" in\n rebase)\ndiff --git a/t/t5520-pull.sh b/t/t5520-pull.sh\nindex 978a3c1..798ae2f 100755\n--- a/t/t5520-pull.sh\n+++ b/t/t5520-pull.sh\n@@ -310,4 +310,40 @@ test_expect_success 'branch.to-rebase.pullmode should override pull.mode' '\n \ttest new = $(git show HEAD:file2)\n '\n \n+test_expect_success 'git pull fast-forward' '\n+\ttest_when_finished \"git checkout master && git branch -D other test\" &&\n+\ttest_config pull.mode merge-ff-only &&\n+\tgit checkout -b other master &&\n+\t>new &&\n+\tgit add new &&\n+\tgit commit -m new &&\n+\tgit checkout -b test -t other &&\n+\tgit reset --hard master &&\n+\tgit pull\n+'\n+\n+test_expect_success 'git pull non-fast-forward' '\n+\ttest_when_finished \"git checkout master && git branch -D other test\" &&\n+\ttest_config pull.mode merge-ff-only &&\n+\tgit checkout -b other master^ &&\n+\t>new &&\n+\tgit add new &&\n+\tgit commit -m new &&\n+\tgit checkout -b test -t other &&\n+\tgit reset --hard master &&\n+\ttest_must_fail git pull\n+'\n+\n+test_expect_success 'git pull non-fast-forward (merge)' '\n+\ttest_when_finished \"git checkout master && git branch -D other test\" &&\n+\ttest_config pull.mode merge-ff-only &&\n+\tgit checkout -b other master^ &&\n+\t>new &&\n+\tgit add new &&\n+\tgit commit -m new &&\n+\tgit checkout -b test -t other &&\n+\tgit reset --hard master &&\n+\tgit pull --merge\n+'\n+\n test_done\n-- \n1.8.4-338-gefd7fa6\n"}]}