{"thread":{"id":"35117","subject":"[PATCH v4 4/7] pull: add merge-ff-only option","startedAt":"2013-10-12T07:01:55Z","lastAt":"2013-10-12T07:02:02Z","messageCount":8,"participants":["Felipe Contreras"],"isPatch":true,"patchVersion":4,"patchTotal":7},"messages":[{"id":"228778","messageId":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":null,"subject":"[PATCH v4 4/7] pull: add merge-ff-only option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:01:55Z","receivedAt":"2013-10-12T07:01:55Z","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\nsuggested that 'git pull' barfs by default if the merge is\nnon-fast-forward, which unfortunately would break backwards\ncompatibility.\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 git-pull.sh              | 13 +++++++++++++\n t/t5520-pull.sh          | 36 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 54 insertions(+), 3 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/git-pull.sh b/git-pull.sh\nindex fbb8a9b..6e6b887 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@@ -282,6 +283,18 @@ case \"$merge_head\" in\n \t\tdie \"$(gettext \"Cannot rebase onto multiple branches\")\"\n \tfi\n \t;;\n+*)\n+\t# check if a non-fast-foward merge would be needed\n+\tmerge_head=${merge_head% }\n+\tif test \"$mode\" = merge-ff-only -a -z \"$no_ff$ff_only${squash#--no-squash}\" &&\n+\t\ttest -n \"$orig_head\" &&\n+\t\t! git merge-base --is-ancestor \"$orig_head\" \"$merge_head\" &&\n+\t\t! git merge-base --is-ancestor \"$merge_head\" \"$orig_head\"\n+\tthen\n+\t\tdie \"$(gettext \"The pull was not fast-forward, please either merge or rebase.\n+If unsure, run 'git pull --merge'.\")\"\n+\tfi\n+\t;;\n esac\n \n # Pulling into unborn branch: a shorthand for branching off\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-fc\n"},{"id":"228779","messageId":"1381561322-20059-2-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 0/7] Reject non-ff pulls by default","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:01:56Z","receivedAt":"2013-10-12T07:01:56Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Minor changes since v3.\n\nJunio already sent a similar patch, but I think this is simpler.\n\nIt 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\nThen the new mode 'merge-ff-only' is added, but not enabled by default, and\nfinally, a warning is added so the users will know what to do when the new\nmode is indeed enabled by default.\n\nDiff from last version:\n\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -293,12 +293,13 @@ case \"$merge_head\" in\n        then\n                case \"$mode\" in\n                merge-ff-only)\n-                       die \"The pull was not fast-forward, please either merge or rebase.\"\n+                       die \"$(gettext \"The pull was not fast-forward, please either merge or rebase.\n+If unsure, run 'git pull --merge'.\")\"\n                        ;;\n                default)\n-                       say \"The pull was not fast-forward, in the future you would have to choose\n+                       echo \"$(gettext \"warning: the pull was not fast-forward, in the future you would have to choose\n a merge or a rebase, falling back to old style for now (git pull --merge).\n-Read 'git pull --help' for more information.\"\n+Read 'git pull --help' for more information.\")\" >&2\n                        ;;\n                esac\n        fi\n\nFelipe Contreras (7):\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  pull: add warning on non-ff merges\n  pull: cleanup documentation\n  pull: add documentation about non-ff merges\n\n Documentation/config.txt   | 24 +++++++++--------\n Documentation/git-pull.txt | 32 +++++++++++++++++++----\n branch.c                   |  4 +--\n git-pull.sh                | 64 +++++++++++++++++++++++++++++++++++++---------\n t/t3200-branch.sh          | 40 ++++++++++++++---------------\n t/t5520-pull.sh            | 62 ++++++++++++++++++++++++++++++++++++++++++++\n t/t5601-clone.sh           |  4 +--\n 7 files changed, 178 insertions(+), 52 deletions(-)\n\n-- \n1.8.4-fc\n"},{"id":"228780","messageId":"1381561322-20059-3-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 3/7] pull: add --merge option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:01:57Z","receivedAt":"2013-10-12T07:01: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-fc\n"},{"id":"228781","messageId":"1381561322-20059-4-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 5/7] pull: add warning on non-ff merges","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:01:58Z","receivedAt":"2013-10-12T07:01:58Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"To prepare our uses for the upcoming changes we should warn them and let\nthem know that they will need to specify a merge or a rebase in the\nfuture (when a non-fast-forward situation arises). Also, let them know\nwe fallback to 'git pull --merge', so when the obsoletion of this mode\ncomes, they know what to type without interrupting or changing their\nworkflow.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n git-pull.sh | 15 ++++++++++++---\n 1 file changed, 12 insertions(+), 3 deletions(-)\n\ndiff --git a/git-pull.sh b/git-pull.sh\nindex 6e6b887..d1b07d8 100755\n--- a/git-pull.sh\n+++ b/git-pull.sh\n@@ -62,7 +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+test -z \"$mode\" && mode=default\n dry_run=\n while :\n do\n@@ -286,13 +286,22 @@ case \"$merge_head\" in\n *)\n \t# check if a non-fast-foward merge would be needed\n \tmerge_head=${merge_head% }\n-\tif test \"$mode\" = merge-ff-only -a -z \"$no_ff$ff_only${squash#--no-squash}\" &&\n+\tif test -z \"$no_ff$ff_only${squash#--no-squash}\" &&\n \t\ttest -n \"$orig_head\" &&\n \t\t! git merge-base --is-ancestor \"$orig_head\" \"$merge_head\" &&\n \t\t! git merge-base --is-ancestor \"$merge_head\" \"$orig_head\"\n \tthen\n-\t\tdie \"$(gettext \"The pull was not fast-forward, please either merge or rebase.\n+\t\tcase \"$mode\" in\n+\t\tmerge-ff-only)\n+\t\t\tdie \"$(gettext \"The pull was not fast-forward, please either merge or rebase.\n If unsure, run 'git pull --merge'.\")\"\n+\t\t\t;;\n+\t\tdefault)\n+\t\t\techo \"$(gettext \"warning: the pull was not fast-forward, in the future you would have to choose\n+a merge or a rebase, falling back to old style for now (git pull --merge).\n+Read 'git pull --help' for more information.\")\" >&2\n+\t\t\t;;\n+\t\tesac\n \tfi\n \t;;\n esac\n-- \n1.8.4-fc\n"},{"id":"228782","messageId":"1381561322-20059-5-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 6/7] pull: cleanup documentation","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:01:59Z","receivedAt":"2013-10-12T07:01:59Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"'origin/master' is very clear, no need to specify the 'remotes/' prefix,\nor babysit the user.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/git-pull.txt | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt\nindex e09f004..6d55737 100644\n--- a/Documentation/git-pull.txt\n+++ b/Documentation/git-pull.txt\n@@ -39,7 +39,7 @@ Assume the following history exists and the current branch is\n \"`master`\":\n \n ------------\n-\t  A---B---C master on origin\n+\t  A---B---C origin/master\n \t /\n     D---E---F---G master\n ------------\n@@ -51,7 +51,7 @@ result in a new commit along with the names of the two parent commits\n and a log message from the user describing the changes.\n \n ------------\n-\t  A---B---C remotes/origin/master\n+\t  A---B---C origin/master\n \t /         \\\n     D---E---F---G---H master\n ------------\n-- \n1.8.4-fc\n"},{"id":"228783","messageId":"1381561322-20059-6-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 2/7] pull: refactor $rebase variable into $mode","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:02:00Z","receivedAt":"2013-10-12T07:02:00Z","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 8363647..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-fc\n"},{"id":"228784","messageId":"1381561322-20059-7-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 1/7] pull: rename pull.rename to pull.mode","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:02:01Z","receivedAt":"2013-10-12T07:02:01Z","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..8363647 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-fc\n"},{"id":"228785","messageId":"1381561322-20059-8-git-send-email-felipe.contreras@gmail.com","threadId":"35117","inReplyTo":"1381561322-20059-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v4 7/7] pull: add documentation about non-ff merges","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-10-12T07:02:02Z","receivedAt":"2013-10-12T07:02:02Z","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 Documentation/git-pull.txt | 18 ++++++++++++++++++\n 1 file changed, 18 insertions(+)\n\ndiff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt\nindex 6d55737..b4053a8 100644\n--- a/Documentation/git-pull.txt\n+++ b/Documentation/git-pull.txt\n@@ -23,6 +23,7 @@ More precisely, 'git pull' runs 'git fetch' with the given\n parameters and calls 'git merge' to merge the retrieved branch\n heads into the current branch.\n With `--rebase`, it runs 'git rebase' instead of 'git merge'.\n+With `--merge`, it forces the merge, even if it's non-fast forward.\n \n <repository> should be the name of a remote repository as\n passed to linkgit:git-fetch[1].  <refspec> can name an\n@@ -41,9 +42,26 @@ Assume the following history exists and the current branch is\n ------------\n \t  A---B---C origin/master\n \t /\n+    D---E master\n+------------\n+\n+Then `git pull` will merge in a fast-foward way up to the new master.\n+\n+------------\n+    D---E---A---B---C master, origin/master\n+------------\n+\n+However, a non-fast-foward case looks very different.\n+\n+------------\n+\t  A---B---C origin/master\n+\t /\n     D---E---F---G master\n ------------\n \n+In the future, `git pull` will fail on these situations, however, most likely\n+you would want to force a merge, which you can do with `git pull --merge`.\n+\n Then \"`git pull`\" will fetch and replay the changes from the remote\n `master` branch since it diverged from the local `master` (i.e., `E`)\n until its current commit (`C`) on top of `master` and record the\n-- \n1.8.4-fc\n"}]}