{"thread":{"id":"13322","subject":"[PATCH] Allow local branching to set up rebase by default.","startedAt":"2008-04-29T20:49:42Z","lastAt":"2008-05-10T22:36:29Z","messageCount":12,"participants":["Dustin Sallings","Jay Soffian","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"75575","messageId":"1209502182-39800-1-git-send-email-dustin@spy.net","threadId":"13322","inReplyTo":null,"subject":"[PATCH] Allow local branching to set up rebase by default.","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-04-29T20:49:42Z","receivedAt":"2008-04-29T20:49:42Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"Change cd67e4d4 introduced a new configuration parameter that told\npull to automatically perform a rebase instead of a merge.  I use this\nfeature quite a bit in topic branches and would like it to be the\ndefault behavior for a topic branch.\n\nIf the parameter branch.autosetuprebase applies for a branch that's\nbeing created, that branch will have branch.<name>.rebase set to true.\n\nSee the documentation for how this may be applied.\n\nNew model.\n---\n Documentation/config.txt |   14 +++++++\n branch.c                 |   26 ++++++++++++-\n cache.h                  |    8 ++++\n config.c                 |   14 +++++++\n environment.c            |    1 +\n t/t3200-branch.sh        |   92 ++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 154 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 7a24f6e..1994895 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -393,6 +393,20 @@ branch.autosetupmerge::\n \tdone when the starting point is either a local branch or remote\n \tbranch. This option defaults to true.\n \n+branch.autosetuprebase::\n+\tWhen a new branch is created with `git-branch` or `git-checkout`\n+\tthat tracks another branch, this parameter tells git to set\n+\tup pull to rebase instead of merge (see \"branch.<name>.rebase\")\n+\tbelow.\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+\tWhen `remote`, rebase is set to true for tracked branches of\n+\tremote branches.\n+\tWhen `always`, rebase will be set to true for all tracking\n+\tbranches.\n+\tThis option defaults to never.\n+\n branch.<name>.remote::\n \tWhen in branch <name>, it tells `git fetch` which remote to fetch.\n \tIf this option is not given, `git fetch` defaults to remote \"origin\".\ndiff --git a/branch.c b/branch.c\nindex daf862e..2a731e4 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -32,6 +32,25 @@ static int find_tracked_branch(struct remote *remote, void *priv)\n \treturn 0;\n }\n \n+static int should_setup_rebase(struct tracking tracking) {\n+\tint rv=0;\n+\tswitch(autorebase) {\n+\tcase AUTOREBASE_NEVER:\n+\t\trv = 0;\n+\t\tbreak;\n+\tcase AUTOREBASE_LOCAL:\n+\t\trv = tracking.matches == 0;\n+\t\tbreak;\n+\tcase AUTOREBASE_REMOTE:\n+\t\trv = tracking.matches > 0;\n+\t\tbreak;\n+\tcase AUTOREBASE_ALWAYS:\n+\t\trv = 1;\n+\t\tbreak;\n+\t}\n+\treturn rv;\n+}\n+\n /*\n  * This is called when new_ref is branched off of orig_ref, and tries\n  * to infer the settings for branch.<new_ref>.{remote,merge} from the\n@@ -69,9 +88,14 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,\n \tgit_config_set(key, tracking.remote ?  tracking.remote : \".\");\n \tsprintf(key, \"branch.%s.merge\", new_ref);\n \tgit_config_set(key, tracking.src ? tracking.src : orig_ref);\n-\tfree(tracking.src);\n \tprintf(\"Branch %s set up to track %s branch %s.\\n\", new_ref,\n \t\ttracking.remote ? \"remote\" : \"local\", orig_ref);\n+\tif (should_setup_rebase(tracking)) {\n+\t\tsprintf(key, \"branch.%s.rebase\", new_ref);\n+\t\tgit_config_set(key, \"true\");\n+\t\tprintf(\"This branch will rebase on pull.\\n\");\n+\t}\n+\tfree(tracking.src);\n \n \treturn 0;\n }\ndiff --git a/cache.h b/cache.h\nindex 3fcc283..5c9aff8 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -433,7 +433,15 @@ enum branch_track {\n \tBRANCH_TRACK_EXPLICIT,\n };\n \n+enum rebase_setup_type {\n+\tAUTOREBASE_NEVER = 0,\n+\tAUTOREBASE_LOCAL,\n+\tAUTOREBASE_REMOTE,\n+\tAUTOREBASE_ALWAYS,\n+};\n+\n extern enum branch_track git_branch_track;\n+extern enum rebase_setup_type autorebase;\n \n #define GIT_REPO_VERSION 0\n extern int repository_format_version;\ndiff --git a/config.c b/config.c\nindex b0ada51..2959087 100644\n--- a/config.c\n+++ b/config.c\n@@ -487,6 +487,20 @@ int git_default_config(const char *var, const char *value)\n \t\tgit_branch_track = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"branch.autosetuprebase\")) {\n+\t\tif (!strcmp(value, \"never\"))\n+\t\t\tautorebase = AUTOREBASE_NEVER;\n+\t\telse if (!strcmp(value, \"local\"))\n+\t\t\tautorebase = AUTOREBASE_LOCAL;\n+\t\telse if (!strcmp(value, \"remote\"))\n+\t\t\tautorebase = AUTOREBASE_REMOTE;\n+\t\telse if (!strcmp(value, \"always\"))\n+\t\t\tautorebase = AUTOREBASE_ALWAYS;\n+\t\telse\n+\t\t\tdie_bad_config(\n+\t\t\t\t\"Invalid value for branch.autosetupmerge\");\n+\t\treturn 0;\n+\t}\n \n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 6739a3f..6fb3b97 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -38,6 +38,7 @@ int auto_crlf = 0;\t/* 1: both ways, -1: only when adding git objects */\n enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n+enum rebase_setup_type autorebase = 0;\n \n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex cb5f7a4..10bb429 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -224,4 +224,96 @@ test_expect_success 'avoid ambiguous track' '\n \ttest -z \"$(git config branch.all1.merge)\"\n '\n \n+test_expect_success 'autosetuprebase local on a tracked local branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase local &&\n+\t (git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\t git branch mybase &&\n+\t git branch --track myr1 mybase &&\n+\t test \"$(git config branch.myr1.remote)\" = . &&\n+\t test \"$(git config branch.myr1.merge)\" = refs/heads/mybase &&\n+\t test \"$(git config branch.myr1.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase always on a tracked local branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase always &&\n+\t (git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\t git branch mybase2 &&\n+\t git branch --track myr2 mybase &&\n+\t test \"$(git config branch.myr2.remote)\" = . &&\n+\t test \"$(git config branch.myr2.merge)\" = refs/heads/mybase &&\n+\t test \"$(git config branch.myr2.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase remote on a tracked local branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase remote &&\n+\t (git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\t git branch mybase3 &&\n+\t git branch --track myr3 mybase2 &&\n+\t test \"$(git config branch.myr3.remote)\" = . &&\n+\t test \"$(git config branch.myr3.merge)\" = refs/heads/mybase2 &&\n+\t ! test \"$(git config branch.myr3.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase never on a tracked local branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase never &&\n+\t (git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\t git branch mybase4 &&\n+\t git branch --track myr4 mybase2 &&\n+\t test \"$(git config branch.myr4.remote)\" = . &&\n+\t test \"$(git config branch.myr4.merge)\" = refs/heads/mybase2 &&\n+\t ! test \"$(git config branch.myr4.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase local on a tracked remote branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase local &&\n+\t (git show-ref -q refs/remotes/local/master || git-fetch local) &&\n+\t git branch --track myr5 local/master &&\n+\t test \"$(git config branch.myr5.remote)\" = local &&\n+\t test \"$(git config branch.myr5.merge)\" = refs/heads/master &&\n+\t ! test \"$(git config branch.myr5.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase never on a tracked remote branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase never &&\n+\t (git show-ref -q refs/remotes/local/master || git-fetch local) &&\n+\t git branch --track myr6 local/master &&\n+\t test \"$(git config branch.myr6.remote)\" = local &&\n+\t test \"$(git config branch.myr6.merge)\" = refs/heads/master &&\n+\t ! test \"$(git config branch.myr6.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase remote on a tracked remote branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase remote &&\n+\t (git show-ref -q refs/remotes/local/master || git-fetch local) &&\n+\t git branch --track myr7 local/master &&\n+\t test \"$(git config branch.myr7.remote)\" = local &&\n+\t test \"$(git config branch.myr7.merge)\" = refs/heads/master &&\n+\t test \"$(git config branch.myr7.rebase)\" = true\n+'\n+\n+test_expect_success 'autosetuprebase always on a tracked remote branch' \\\n+\t'git config remote.local.url . &&\n+\t git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t git config branch.autosetuprebase remote &&\n+\t (git show-ref -q refs/remotes/local/master || git-fetch local) &&\n+\t git branch --track myr8 local/master &&\n+\t test \"$(git config branch.myr8.remote)\" = local &&\n+\t test \"$(git config branch.myr8.merge)\" = refs/heads/master &&\n+\t test \"$(git config branch.myr8.rebase)\" = true\n+'\n+\n test_done\n-- \n1.5.5.1.100.g65b98\n"},{"id":"75595","messageId":"76718490804291456r7d1ef385q4e51a5705fdd26ef@mail.gmail.com","threadId":"13322","inReplyTo":"1209502182-39800-1-git-send-email-dustin@spy.net","subject":"Re: [PATCH] Allow local branching to set up rebase by default.","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2008-04-29T21:56:45Z","receivedAt":"2008-04-29T21:56:45Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Tue, Apr 29, 2008 at 4:49 PM, Dustin Sallings <dustin@spy.net> wrote:\n> Change cd67e4d4 introduced a new configuration parameter that told\n>  pull to automatically perform a rebase instead of a merge.  I use this\n>  feature quite a bit in topic branches and would like it to be the\n>  default behavior for a topic branch.\n>\n>  If the parameter branch.autosetuprebase applies for a branch that's\n>  being created, that branch will have branch.<name>.rebase set to true.\n>\n>  See the documentation for how this may be applied.\n>\n\nI've had this change parked in one of my branches forever. Consider\nthis a UI suggestion to go with the new config option?\n\n    [WIP] new --rebase option to set branch.*.rebase for new branches\n\n    Add a --rebase option to git-branch and git-checkout. If given, it\n    implies --track but additionally sets branch.<newbranch>.rebase to true.\n\n    [NOTE TO SELF: this is based off the old next branch, and also it sitting on\n    top of my old --track changes, so it will need to be reworked.]\n"},{"id":"76250","messageId":"76B5A8CE-EFFF-48BE-AD2C-45527D7AB04D@spy.net","threadId":"13322","inReplyTo":"02471C27-C99D-43E7-BC58-50F2B86ED159@spy.net","subject":"Re: [PATCH] Allow local branching to set up rebase by default.","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-05-07T06:01:33Z","receivedAt":"2008-05-07T06:01:33Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"\nOn Apr 29, 2008, at 14:49, Dustin Sallings wrote:\n\n\t[a patch]\n\n\tI haven't seen any activity related to this in a week.  This  \nfunctionality is interesting to my coworkers and a small sampling I've  \npolled.  Does it require any kind of cleanup, will it be completely  \nrejected, or should I just be more patient?  :)\n\n-- \nDustin Sallings\n"},{"id":"76290","messageId":"7vwsm6dtva.fsf@gitster.siamese.dyndns.org","threadId":"13322","inReplyTo":"76B5A8CE-EFFF-48BE-AD2C-45527D7AB04D@spy.net","subject":"Re: [PATCH] Allow local branching to set up rebase by default.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-07T15:19:37Z","receivedAt":"2008-05-07T15:19:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dustin Sallings <dustin@spy.net> writes:\n\n> On Apr 29, 2008, at 14:49, Dustin Sallings wrote:\n>\n> \t[a patch]\n>\n> \tI haven't seen any activity related to this in a week.  This\n> functionality is interesting to my coworkers and a small sampling I've\n> polled.  Does it require any kind of cleanup, will it be completely\n> rejected, or should I just be more patient?  :)\n\nWhat happened probably is that nobody on the list found it interesting.  I\ndo not offhand recall what the patch was about.\n\nYou cited <02471C27-C99D-43E7-BC58-50F2B86ED159@spy.net> as the original\nmessage that your message is a reply to, but I do not seem to be able to\nget it via mail archives.  I am guessing you meant this one:\n\n    Message-ID: <1209502182-39800-1-git-send-email-dustin@spy.net>\n    http://news.gmane.org/gmane.comp.version-control.git/80732\n"},{"id":"76304","messageId":"7vprrycce9.fsf@gitster.siamese.dyndns.org","threadId":"13322","inReplyTo":"1209502182-39800-1-git-send-email-dustin@spy.net","subject":"Re: [PATCH] Allow local branching to set up rebase by default.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-07T16:22:22Z","receivedAt":"2008-05-07T16:22:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dustin Sallings <dustin@spy.net> writes:\n\n> Change cd67e4d4 introduced a new configuration parameter that told\n> pull to automatically perform a rebase instead of a merge.  I use this\n> feature quite a bit in topic branches and would like it to be the\n> default behavior for a topic branch.\n>\n> If the parameter branch.autosetuprebase applies for a branch that's\n> being created, that branch will have branch.<name>.rebase set to true.\n>\n> See the documentation for how this may be applied.\n>\n> New model.\n> ---\n\nThe commit log message is both a sales pitch to get people interested in\nyour change and an explanation of why the change was needed once it gets\netched into the history.\n\nThe above starts out very nicely by stating the background of the change\nin the first sentence.  However, \"I use this ...\" is too subjective and\nmakes others on the list who would comment on it go \"Huh, you do?  So\nwhat?\" and lose interest in the patch.  You got no reactions, neither\npositive nor negative, partly due to this sentence, I suspect.  It would\nbe better received if you make it less subjective (e.g. 'This can be used\nto maintain tidy history of topic branches until they get merged, but\nhaving to say \"git pull --rebase\" every time is a nuisance.\").\n\nWith the background and motivation clearly explained, then you would\ndescribe what the change solves and how.  The second paragraph is fine.\n\n\"See the documentation\" is a key phrase to turn off people's interest; you\nwould never want to say it, for two reasons:\n\n (1) people are busy and first scan only the commit log message without\n     reading diffs, so that they do not have to waste time on patches that\n     are ill conceived.\n\n (2) once the change is committed, people read \"git log\" output to get\n     overview of the history, and expect the commit log messages to be\n     sufficient for that purpose.\n\n\"See the doc\" tells the reader that \"What I have here in the commit log is\ninsufficient and useless; you need to go to the documentation\".  But that\nis not the case for your commit log message --- you gave a very good\noverview and ruined it by having this needless sentence.  Drop it.\n\n\"New model.\"???\n\nI certainly went \"Huh?\" and stopped reading when I hit that line.\n\nPlease sign-off your patches (see Documentation/SubmittingPatches).\n\n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 7a24f6e..1994895 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -393,6 +393,20 @@ branch.autosetupmerge::\n>  \tdone when the starting point is either a local branch or remote\n>  \tbranch. This option defaults to true.\n>  \n> +branch.autosetuprebase::\n> +\tWhen a new branch is created with `git-branch` or `git-checkout`\n> +\tthat tracks another branch, this parameter tells git to set\n\nThis is probably not a \"parameter\" but a \"variable\".\n\n> +\tup pull to rebase instead of merge (see \"branch.<name>.rebase\")\n> +\tbelow.\n\n\"below\"?\n\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> +\tWhen `remote`, rebase is set to true for tracked branches of\n> +\tremote branches.\n> +\tWhen `always`, rebase will be set to true for all tracking\n> +\tbranches.\n> +\tThis option defaults to never.\n\nHow does this interact with a similarly named configuration option,\nautosetupmerge, whose settings can be false, true, and always?\n\n>  branch.<name>.remote::\n>  \tWhen in branch <name>, it tells `git fetch` which remote to fetch.\n>  \tIf this option is not given, `git fetch` defaults to remote \"origin\".\n\nThis is not your fault, but can anybody guess what the exact command\nsequence to cause the named branch to be advanced by rebasing, only by\nreading this entry?\n\n    branch.<name>.rebase::\n            When true, rebase the branch <name> on top of the fetched branch,\n            instead of merging the default branch from the default remote.\n\nI can't.  Perhaps we would need \"when \"git pull\" is run\" or something at\nthe end.\n\n> diff --git a/branch.c b/branch.c\n> index daf862e..2a731e4 100644\n> --- a/branch.c\n> +++ b/branch.c\n> @@ -32,6 +32,25 @@ static int find_tracked_branch(struct remote *remote, void *priv)\n>  \treturn 0;\n>  }\n>  \n> +static int should_setup_rebase(struct tracking tracking) {\n\nStyle.\n\n - The \"{\" to start a function body comes at the beginning on its own\n   line.\n\n - Pass struct (especially a read-only one) by a (const) pointer, not by\n   value:\n\n\tstatic int foo(const struct tracking *tracking)\n        {\n        \t...\n\n> +\tint rv=0;\n\nStyle.  s/=/ = /;\n\n> +\tswitch(autorebase) {\n\nStyle. s/(/ (/;\n\n> +\tcase AUTOREBASE_NEVER:\n> +\t\trv = 0;\n> +\t\tbreak;\n> +\tcase AUTOREBASE_LOCAL:\n> +\t\trv = tracking.matches == 0;\n> +\t\tbreak;\n\nIs this correct?  Earlier you said \"local\" is about a branch that trails\nother local branches, but this seems to be checking only if the branch is\nnot tracking anything remote.  Would it be possible for this branch to be\nnot trailing anything, not even local?\n\n\tThe answer turns out to be \"no\", only because this function\n\timplicitly relies on the fact that setup_tracking() never calls it\n\tif the branch does not track anything, but it was hard to guess\n\tduring the first pass.\n\nYou might want to check how the setup_tracking() decides when to say\nremote/local in its printf().\n\n> +\tcase AUTOREBASE_REMOTE:\n> +\t\trv = tracking.matches > 0;\n> +\t\tbreak;\n\nThis somehow feels awkward because (tracking->matches > 1) is an ambiguous\nsituation (perhaps a misconfiguration) that setup_tracking() rejects but\nyou are allowing it here.  Admittedly, the former would never call you\nwhen it detects the case, but it still feels awkward...\n\n> +\tcase AUTOREBASE_ALWAYS:\n> +\t\trv = 1;\n> +\t\tbreak;\n> +\t}\n> +\treturn rv;\n> +}\n\nAfter all you might be better off without a temporary variable rv and\nreturn from within the switch().\n\n> diff --git a/cache.h b/cache.h\n> index 3fcc283..5c9aff8 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -433,7 +433,15 @@ enum branch_track {\n>  \tBRANCH_TRACK_EXPLICIT,\n>  };\n>  \n> +enum rebase_setup_type {\n> +\tAUTOREBASE_NEVER = 0,\n> +\tAUTOREBASE_LOCAL,\n> +\tAUTOREBASE_REMOTE,\n> +\tAUTOREBASE_ALWAYS,\n> +};\n> +\n>  extern enum branch_track git_branch_track;\n> +extern enum rebase_setup_type autorebase;\n>  \n>  #define GIT_REPO_VERSION 0\n>  extern int repository_format_version;\n> diff --git a/config.c b/config.c\n> index b0ada51..2959087 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -487,6 +487,20 @@ int git_default_config(const char *var, const char *value)\n>  \t\tgit_branch_track = git_config_bool(var, value);\n>  \t\treturn 0;\n>  \t}\n> +\tif (!strcmp(var, \"branch.autosetuprebase\")) {\n> +\t\tif (!strcmp(value, \"never\"))\n> +\t\t\tautorebase = AUTOREBASE_NEVER;\n\nHave this in your .git/config:\n\n        [branch]\n                autosetuprebase\n\nand you will strcmp(NULL, \"never\") here.\n\n> +\t\telse if (!strcmp(value, \"local\"))\n> +\t\t\tautorebase = AUTOREBASE_LOCAL;\n> +\t\telse if (!strcmp(value, \"remote\"))\n> +\t\t\tautorebase = AUTOREBASE_REMOTE;\n> +\t\telse if (!strcmp(value, \"always\"))\n> +\t\t\tautorebase = AUTOREBASE_ALWAYS;\n> +\t\telse\n> +\t\t\tdie_bad_config(\n> +\t\t\t\t\"Invalid value for branch.autosetupmerge\");\n\nA line slightly longer than 80-cols is better than this artificial line\nsplit, I think.\n\n> diff --git a/environment.c b/environment.c\n> index 6739a3f..6fb3b97 100644\n> --- a/environment.c\n> +++ b/environment.c\n> @@ -38,6 +38,7 @@ int auto_crlf = 0;\t/* 1: both ways, -1: only when adding git objects */\n>  enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n>  unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n>  enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n> +enum rebase_setup_type autorebase = 0;\n\nDo not initialize to 0; BSS takes care of it.  Explicitly initializing to\na symbolic constant, by using AUTOREBASE_NEVER, is very much Ok.\n\n> diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\n> index cb5f7a4..10bb429 100755\n> --- a/t/t3200-branch.sh\n> +++ b/t/t3200-branch.sh\n> @@ -224,4 +224,96 @@ test_expect_success 'avoid ambiguous track' '\n>  \ttest -z \"$(git config branch.all1.merge)\"\n>  '\n>  \n> +test_expect_success 'autosetuprebase local on a tracked local branch' \\\n> +\t'git config remote.local.url . &&\n\nMove the opening \"'\" to the end of the first line so you can lose\nbackslash there and it becomes easier to read.\n"},{"id":"76388","messageId":"585390AA-289C-4B2F-B851-DD383C6C7A73@spy.net","threadId":"13322","inReplyTo":"7vprrycce9.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Allow local branching to set up rebase by default.","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-05-08T17:32:59Z","receivedAt":"2008-05-08T17:32:59Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"\n\tHi, thanks for the response.\n\nOn May 7, 2008, at 9:22, Junio C Hamano wrote:\n\n> You got no reactions, neither\n> positive nor negative, partly due to this sentence, I suspect.\n\n\tI got one response from someone who said he had implemented the same  \nthing in one of his branches.  That seemed to confirm the idea for  \nme.  Some additional features were suggested to be built on top of  \nthis, but I didn't read it as necessary for proceeding.\n\n> Please sign-off your patches (see Documentation/SubmittingPatches).\n\n\tOh thanks, I hadn't seen this.  I read it as well as the  \nCodingGuidelines document.\n\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>> +\tWhen `remote`, rebase is set to true for tracked branches of\n>> +\tremote branches.\n>> +\tWhen `always`, rebase will be set to true for all tracking\n>> +\tbranches.\n>> +\tThis option defaults to never.\n>\n> How does this interact with a similarly named configuration option,\n> autosetupmerge, whose settings can be false, true, and always?\n\n\tI can direct the user to the autosetupmerge config documentation  \nsince it also documents the flags that override its behavior.  Is this  \nacceptable?\n\n>> branch.<name>.remote::\n>> \tWhen in branch <name>, it tells `git fetch` which remote to fetch.\n>> \tIf this option is not given, `git fetch` defaults to remote  \n>> \"origin\".\n>\n> This is not your fault, but can anybody guess what the exact command\n> sequence to cause the named branch to be advanced by rebasing, only by\n> reading this entry?\n>\n>    branch.<name>.rebase::\n>            When true, rebase the branch <name> on top of the fetched  \n> branch,\n>            instead of merging the default branch from the default  \n> remote.\n>\n> I can't.  Perhaps we would need \"when \"git pull\" is run\" or  \n> something at\n> the end.\n\n\tI'll submit this as a separate patch.\n\n> Is this correct?\n\n\t[...]\n\n> You might want to check how the setup_tracking() decides when to say\n> remote/local in its printf().\n\n\tOh thanks, I clearly didn't understand this and just relied on my  \ntests passing by coincidence.\n\n\tI'll resubmit my patch with your recommendations, thanks.\n\n-- \nDustin Sallings\n"},{"id":"76391","messageId":"7v1w4cd590.fsf@gitster.siamese.dyndns.org","threadId":"13322","inReplyTo":"585390AA-289C-4B2F-B851-DD383C6C7A73@spy.net","subject":"Re: [PATCH] Allow local branching to set up rebase by default.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-08T18:23:39Z","receivedAt":"2008-05-08T18:23:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dustin Sallings <dustin@spy.net> writes:\n\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>>> +\tWhen `remote`, rebase is set to true for tracked branches of\n>>> +\tremote branches.\n>>> +\tWhen `always`, rebase will be set to true for all tracking\n>>> +\tbranches.\n>>> +\tThis option defaults to never.\n>>\n>> How does this interact with a similarly named configuration option,\n>> autosetupmerge, whose settings can be false, true, and always?\n>\n> \tI can direct the user to the autosetupmerge config\n> documentation since it also documents the flags that override its\n> behavior.  Is this  acceptable?\n\nOh, it was not a request to change the description quoted above but a pure\nquestion -- asking for information.  \"This new configuration variable is\northogonal and does not interact with the autosetupmerge\", \"This takes\neffect only the other one decides (or --track is given from the command\nline) to make it track\", etc.  were the expected answers.  It might not\nhurt to insert \"(see branch.<name>.autosetupmerge)\" before the comma in\n\"tracks another branch,\" below, though...\n\n    +branch.autosetuprebase::\n    +       When a new branch is created with `git-branch` or `git-checkout`\n    +       that tracks another branch, this parameter tells git to set\n"},{"id":"76393","messageId":"1210271287-36719-1-git-send-email-dustin@spy.net","threadId":"13322","inReplyTo":"7vprrycce9.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] Allow tracking branches to set up rebase by default.","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-05-08T18:28:06Z","receivedAt":"2008-05-08T18:28:06Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"Change cd67e4d4 introduced a new configuration parameter that told\npull to automatically perform a rebase instead of a merge.  This\nchange provides a configuration option to enable this feature\nautomatically when creating a new branch.\n\nIf the variable branch.autosetuprebase applies for a branch that's\nbeing created, that branch will have branch.<name>.rebase set to true.\n\nSigned-off-by: Dustin Sallings <dustin@spy.net>\n---\n Documentation/config.txt |   15 +++++++\n branch.c                 |   22 ++++++++++-\n cache.h                  |    8 ++++\n config.c                 |   13 ++++++\n environment.c            |    1 +\n t/t3200-branch.sh        |   92 ++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 150 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 00f089f..6413f70 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -399,6 +399,21 @@ branch.autosetupmerge::\n \tdone when the starting point is either a local branch or remote\n \tbranch. This option defaults to true.\n \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+\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+\tWhen `remote`, rebase is set to true for tracked branches of\n+\tremote branches.\n+\tWhen `always`, rebase will be set to true for all tracking\n+\tbranches.\n+\tSee \"branch.autosetupmerge\" for details on how to set up a\n+\tbranch to track another branch.\n+\tThis option defaults to never.\n+\n branch.<name>.remote::\n \tWhen in branch <name>, it tells `git fetch` which remote to fetch.\n \tIf this option is not given, `git fetch` defaults to remote \"origin\".\ndiff --git a/branch.c b/branch.c\nindex daf862e..56e9492 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -32,6 +32,21 @@ static int find_tracked_branch(struct remote *remote, void *priv)\n \treturn 0;\n }\n \n+static int should_setup_rebase(const struct tracking *tracking)\n+{\n+\tswitch (autorebase) {\n+\tcase AUTOREBASE_NEVER:\n+\t\treturn 0;\n+\tcase AUTOREBASE_LOCAL:\n+\t\treturn tracking->remote == NULL;\n+\tcase AUTOREBASE_REMOTE:\n+\t\treturn tracking->remote != NULL;\n+\tcase AUTOREBASE_ALWAYS:\n+\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * This is called when new_ref is branched off of orig_ref, and tries\n  * to infer the settings for branch.<new_ref>.{remote,merge} from the\n@@ -69,9 +84,14 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,\n \tgit_config_set(key, tracking.remote ?  tracking.remote : \".\");\n \tsprintf(key, \"branch.%s.merge\", new_ref);\n \tgit_config_set(key, tracking.src ? tracking.src : orig_ref);\n-\tfree(tracking.src);\n \tprintf(\"Branch %s set up to track %s branch %s.\\n\", new_ref,\n \t\ttracking.remote ? \"remote\" : \"local\", orig_ref);\n+\tif (should_setup_rebase(&tracking)) {\n+\t\tsprintf(key, \"branch.%s.rebase\", new_ref);\n+\t\tgit_config_set(key, \"true\");\n+\t\tprintf(\"This branch will rebase on pull.\\n\");\n+\t}\n+\tfree(tracking.src);\n \n \treturn 0;\n }\ndiff --git a/cache.h b/cache.h\nindex d5d5dad..19f2930 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -434,7 +434,15 @@ enum branch_track {\n \tBRANCH_TRACK_EXPLICIT,\n };\n \n+enum rebase_setup_type {\n+\tAUTOREBASE_NEVER = 0,\n+\tAUTOREBASE_LOCAL,\n+\tAUTOREBASE_REMOTE,\n+\tAUTOREBASE_ALWAYS,\n+};\n+\n extern enum branch_track git_branch_track;\n+extern enum rebase_setup_type autorebase;\n \n #define GIT_REPO_VERSION 0\n extern int repository_format_version;\ndiff --git a/config.c b/config.c\nindex b0ada51..7d76986 100644\n--- a/config.c\n+++ b/config.c\n@@ -487,6 +487,19 @@ int git_default_config(const char *var, const char *value)\n \t\tgit_branch_track = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n+\tif (value && !strcmp(var, \"branch.autosetuprebase\")) {\n+\t\tif (!strcmp(value, \"never\"))\n+\t\t\tautorebase = AUTOREBASE_NEVER;\n+\t\telse if (!strcmp(value, \"local\"))\n+\t\t\tautorebase = AUTOREBASE_LOCAL;\n+\t\telse if (!strcmp(value, \"remote\"))\n+\t\t\tautorebase = AUTOREBASE_REMOTE;\n+\t\telse if (!strcmp(value, \"always\"))\n+\t\t\tautorebase = AUTOREBASE_ALWAYS;\n+\t\telse\n+\t\t\tdie_bad_config(\"Invalid value for branch.autosetupmerge\");\n+\t\treturn 0;\n+\t}\n \n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\ndiff --git a/environment.c b/environment.c\nindex fcd1ee5..4892a30 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -38,6 +38,7 @@ int auto_crlf = 0;\t/* 1: both ways, -1: only when adding git objects */\n enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n+enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n \n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex cb5f7a4..d11dd41 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -224,4 +224,96 @@ test_expect_success 'avoid ambiguous track' '\n \ttest -z \"$(git config branch.all1.merge)\"\n '\n \n+test_expect_success 'autosetuprebase local on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase local &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase &&\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+'\n+\n+test_expect_success 'autosetuprebase always on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase always &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase2 &&\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+'\n+\n+test_expect_success 'autosetuprebase remote on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase remote &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase3 &&\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+'\n+\n+test_expect_success 'autosetuprebase never on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase never &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase4 &&\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+'\n+\n+test_expect_success 'autosetuprebase local on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase local &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase never on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase never &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase remote on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase remote &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase always on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase remote &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n test_done\n-- \n1.5.5.1.100.g65b98\n"},{"id":"76392","messageId":"1210271287-36719-2-git-send-email-dustin@spy.net","threadId":"13322","inReplyTo":"7vprrycce9.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] Doc: Mention branch.<name>.rebase applies to \"git pull\"","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-05-08T18:28:07Z","receivedAt":"2008-05-08T18:28:07Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"Signed-off-by: Dustin Sallings <dustin@spy.net>\n---\n Documentation/config.txt |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 6413f70..44bd20b 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -441,7 +441,8 @@ branch.<name>.mergeoptions::\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.\n+\tinstead of merging the default branch from the default remote when\n+\t\"git pull\" is run.\n \t*NOTE*: this is a possibly dangerous operation; do *not* use\n \tit unless you understand the implications (see linkgit:git-rebase[1]\n \tfor details).\n-- \n1.5.5.1.100.g65b98\n"},{"id":"76534","messageId":"7vfxsq9f3n.fsf@gitster.siamese.dyndns.org","threadId":"13322","inReplyTo":"1210271287-36719-1-git-send-email-dustin@spy.net","subject":"Re: [PATCH] Allow tracking branches to set up rebase by default.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-05-10T18:41:16Z","receivedAt":"2008-05-10T18:41:16Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The patch is looking better.\n\nI'd suggest further fixes like the attached patch to address the following\nissues:\n\n - Do not ignore misconfiguration, but diagnose it.\n\n - die_bad_config() takes a variable name without surrounding explanatory\n   text.  If you actually tested your patch and looked at the error\n   message, it would have been blatantly obvious and you would have\n   noticed it.  Not a good sign.\n\n - Test not just the success cases but failure cases; test not just\n   explicitly configured cases but also default cases.\n\nThe last one is something everybody tends to forget, but is very\nimportant.  It is human nature that anybody would eagerly want to\ndemonstrate what new things their shiny new toy does, but would forget to\nmake sure that it does not take effect when people do not want it (either\nsaying 'never' which you do have test, which is good, or not asking for it\nby not setting the variable, which you didn't).  You'd notice that I\nplayed lazy and added a check for only the \"tracked remote\" case when the\nnew variable is left unspecified, but you might want to add tests for\nother variants.  Also I suspect that we would want to test cases where\nautosetuprebase is given but autosetupmerge is not.\n\nAnother thing we might want to address is to move parsing of branch.*\nconfiguration variables out of git_default_config().  They are unnecessary\nfor majority of commands that do not create new branches.  But that would\nbe a separate topic if we were to do so.\n\n\n config.c          |    8 +++++---\n t/t3200-branch.sh |   24 ++++++++++++++++++++++++\n 2 files changed, 29 insertions(+), 3 deletions(-)\n\ndiff --git a/config.c b/config.c\nindex 7d76986..cf2bfd3 100644\n--- a/config.c\n+++ b/config.c\n@@ -487,8 +487,10 @@ int git_default_config(const char *var, const char *value)\n \t\tgit_branch_track = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n-\tif (value && !strcmp(var, \"branch.autosetuprebase\")) {\n-\t\tif (!strcmp(value, \"never\"))\n+\tif (!strcmp(var, \"branch.autosetuprebase\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\telse if (!strcmp(value, \"never\"))\n \t\t\tautorebase = AUTOREBASE_NEVER;\n \t\telse if (!strcmp(value, \"local\"))\n \t\t\tautorebase = AUTOREBASE_LOCAL;\n@@ -497,7 +499,7 @@ int git_default_config(const char *var, const char *value)\n \t\telse if (!strcmp(value, \"always\"))\n \t\t\tautorebase = AUTOREBASE_ALWAYS;\n \t\telse\n-\t\t\tdie_bad_config(\"Invalid value for branch.autosetupmerge\");\n+\t\t\treturn error(\"Malformed value for %s\", var);\n \t\treturn 0;\n \t}\n \ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex d11dd41..5cfeaa7 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -144,6 +144,18 @@ test_expect_success 'test tracking setup (non-wildcard, not matching)' \\\n      ! test \"$(git config branch.my5.remote)\" = local &&\n      ! test \"$(git config branch.my5.merge)\" = refs/heads/master'\n \n+test_expect_success 'detect misconfigured autosetuprebase' '\n+\tgit config branch.autosetuprebase garbage &&\n+\ttest_must_fail git branch\n+'\n+\n+test_expect_success 'detect misconfigured autosetuprebase' '\n+\tgit config --unset branch.autosetuprebase &&\n+\techo \"[branch] autosetuprebase\" >>.git/config &&\n+\ttest_must_fail git branch &&\n+\tgit config --unset branch.autosetuprebase\n+'\n+\n test_expect_success 'test tracking setup via config' \\\n     'git config branch.autosetupmerge true &&\n      git config remote.local.url . &&\n@@ -316,4 +328,16 @@ test_expect_success 'autosetuprebase always on a tracked remote branch' '\n \ttest \"$(git config branch.myr8.rebase)\" = true\n '\n \n+test_expect_success 'without autosetuprebase' '\n+\tgit config --unset branch.autosetuprebase\n+\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n test_done\n"},{"id":"76553","messageId":"1206EB02-2AE6-4A97-AF00-D16B8E686D9B@spy.net","threadId":"13322","inReplyTo":"7vfxsq9f3n.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Allow tracking branches to set up rebase by default.","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-05-10T22:36:13Z","receivedAt":"2008-05-10T22:36:13Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"\nOn May 10, 2008, at 11:41, Junio C Hamano wrote:\n\n> - die_bad_config() takes a variable name without surrounding  \n> explanatory\n>   text.  If you actually tested your patch and looked at the error\n>   message, it would have been blatantly obvious and you would have\n>   noticed it.  Not a good sign.\n>\n> - Test not just the success cases but failure cases; test not just\n>   explicitly configured cases but also default cases.\n\n\tYou're right, I didn't test misconfiguration cases.  I've updated the  \npatch per your recommendations with a lot more tests and have manually  \ntested the error messages to ensure they make sense.\n\n\tDoes it make sense in the cases where a value is bad to list the  \nvalid values?  I don't see a precedent (so I don't know what format  \nwould be most desirable), but it might be friendly.\n\n> Also I suspect that we would want to test cases where\n> autosetuprebase is given but autosetupmerge is not.\n\n\tThis code isn't so much dependent on that variable, but on the  \neffects of that variable, which may be overridden by the --track and -- \nno-track parameters.  I think it'd be best to leave the effects of  \nthat variable in its own tests wrt tracking since this code doesn't  \nkick in until after the tracking is set up.\n\n> Another thing we might want to address is to move parsing of branch.*\n> configuration variables out of git_default_config().  They are  \n> unnecessary\n> for majority of commands that do not create new branches.  But that  \n> would\n> be a separate topic if we were to do so.\n\n\tI agree with this.  I tried initially to not have it be part of the  \ndefault config parser, but it seemed a lot more disruptive, so I just  \nfollowed autosetupmerge.\n\n\tThanks for your input again.  New patch to follow.\n\n-- \nDustin Sallings\n"},{"id":"76554","messageId":"1210458989-87248-1-git-send-email-dustin@spy.net","threadId":"13322","inReplyTo":"7vfxsq9f3n.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] Allow tracking branches to set up rebase by default.","fromName":"Dustin Sallings","fromEmail":"dustin@spy.net","sentAt":"2008-05-10T22:36:29Z","receivedAt":"2008-05-10T22:36:29Z","isPatch":true,"sender":{"key":"dustin@spy.net","avatar":"https://gravatar.com/avatar/1750c3935110d421b32d60d412eae0eb49acfcf181605df9adaddb04a9878664?d=mp&s=160"},"body":"Change cd67e4d4 introduced a new configuration parameter that told\npull to automatically perform a rebase instead of a merge.  This\nchange provides a configuration option to enable this feature\nautomatically when creating a new branch.\n\nIf the variable branch.autosetuprebase applies for a branch that's\nbeing created, that branch will have branch.<name>.rebase set to true.\n\nSigned-off-by: Dustin Sallings <dustin@spy.net>\n---\n Documentation/config.txt |   15 +++\n branch.c                 |   22 ++++-\n cache.h                  |    8 ++\n config.c                 |   15 +++\n environment.c            |    1 +\n t/t3200-branch.sh        |  234 ++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 294 insertions(+), 1 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex a6fc5a2..217980f 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -399,6 +399,21 @@ branch.autosetupmerge::\n \tdone when the starting point is either a local branch or remote\n \tbranch. This option defaults to true.\n \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+\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+\tWhen `remote`, rebase is set to true for tracked branches of\n+\tremote branches.\n+\tWhen `always`, rebase will be set to true for all tracking\n+\tbranches.\n+\tSee \"branch.autosetupmerge\" for details on how to set up a\n+\tbranch to track another branch.\n+\tThis option defaults to never.\n+\n branch.<name>.remote::\n \tWhen in branch <name>, it tells `git fetch` which remote to fetch.\n \tIf this option is not given, `git fetch` defaults to remote \"origin\".\ndiff --git a/branch.c b/branch.c\nindex daf862e..56e9492 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -32,6 +32,21 @@ static int find_tracked_branch(struct remote *remote, void *priv)\n \treturn 0;\n }\n \n+static int should_setup_rebase(const struct tracking *tracking)\n+{\n+\tswitch (autorebase) {\n+\tcase AUTOREBASE_NEVER:\n+\t\treturn 0;\n+\tcase AUTOREBASE_LOCAL:\n+\t\treturn tracking->remote == NULL;\n+\tcase AUTOREBASE_REMOTE:\n+\t\treturn tracking->remote != NULL;\n+\tcase AUTOREBASE_ALWAYS:\n+\t\treturn 1;\n+\t}\n+\treturn 0;\n+}\n+\n /*\n  * This is called when new_ref is branched off of orig_ref, and tries\n  * to infer the settings for branch.<new_ref>.{remote,merge} from the\n@@ -69,9 +84,14 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,\n \tgit_config_set(key, tracking.remote ?  tracking.remote : \".\");\n \tsprintf(key, \"branch.%s.merge\", new_ref);\n \tgit_config_set(key, tracking.src ? tracking.src : orig_ref);\n-\tfree(tracking.src);\n \tprintf(\"Branch %s set up to track %s branch %s.\\n\", new_ref,\n \t\ttracking.remote ? \"remote\" : \"local\", orig_ref);\n+\tif (should_setup_rebase(&tracking)) {\n+\t\tsprintf(key, \"branch.%s.rebase\", new_ref);\n+\t\tgit_config_set(key, \"true\");\n+\t\tprintf(\"This branch will rebase on pull.\\n\");\n+\t}\n+\tfree(tracking.src);\n \n \treturn 0;\n }\ndiff --git a/cache.h b/cache.h\nindex 7fb8f33..3442130 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -434,7 +434,15 @@ enum branch_track {\n \tBRANCH_TRACK_EXPLICIT,\n };\n \n+enum rebase_setup_type {\n+\tAUTOREBASE_NEVER = 0,\n+\tAUTOREBASE_LOCAL,\n+\tAUTOREBASE_REMOTE,\n+\tAUTOREBASE_ALWAYS,\n+};\n+\n extern enum branch_track git_branch_track;\n+extern enum rebase_setup_type autorebase;\n \n #define GIT_REPO_VERSION 0\n extern int repository_format_version;\ndiff --git a/config.c b/config.c\nindex b0ada51..cf2bfd3 100644\n--- a/config.c\n+++ b/config.c\n@@ -487,6 +487,21 @@ int git_default_config(const char *var, const char *value)\n \t\tgit_branch_track = git_config_bool(var, value);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"branch.autosetuprebase\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\telse if (!strcmp(value, \"never\"))\n+\t\t\tautorebase = AUTOREBASE_NEVER;\n+\t\telse if (!strcmp(value, \"local\"))\n+\t\t\tautorebase = AUTOREBASE_LOCAL;\n+\t\telse if (!strcmp(value, \"remote\"))\n+\t\t\tautorebase = AUTOREBASE_REMOTE;\n+\t\telse if (!strcmp(value, \"always\"))\n+\t\t\tautorebase = AUTOREBASE_ALWAYS;\n+\t\telse\n+\t\t\treturn error(\"Malformed value for %s\", var);\n+\t\treturn 0;\n+\t}\n \n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\ndiff --git a/environment.c b/environment.c\nindex fcd1ee5..4892a30 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -38,6 +38,7 @@ int auto_crlf = 0;\t/* 1: both ways, -1: only when adding git objects */\n enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n+enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n \n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex cb5f7a4..8d87686 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -224,4 +224,238 @@ test_expect_success 'avoid ambiguous track' '\n \ttest -z \"$(git config branch.all1.merge)\"\n '\n \n+test_expect_success 'autosetuprebase local on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase local &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase &&\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+'\n+\n+test_expect_success 'autosetuprebase always on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase always &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase2 &&\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+'\n+\n+test_expect_success 'autosetuprebase remote on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase remote &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase3 &&\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+'\n+\n+test_expect_success 'autosetuprebase never on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase never &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase4 &&\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+'\n+\n+test_expect_success 'autosetuprebase local on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase local &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase never on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase never &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase remote on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase remote &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase always on a tracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\tgit config branch.autosetuprebase remote &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase unconfigured on a tracked remote branch' '\n+\tgit config --unset branch.autosetuprebase &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase unconfigured on a tracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/o || git-fetch local) &&\n+\tgit branch mybase10 &&\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+'\n+\n+test_expect_success 'autosetuprebase unconfigured on untracked local branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase unconfigured on untracked remote branch' '\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase never on an untracked local branch' '\n+\tgit config branch.autosetuprebase never &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase local on an untracked local branch' '\n+\tgit config branch.autosetuprebase local &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase remote on an untracked local branch' '\n+\tgit config branch.autosetuprebase remote &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase always on an untracked local branch' '\n+\tgit config branch.autosetuprebase always &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase never on an untracked remote branch' '\n+\tgit config branch.autosetuprebase never &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase local on an untracked remote branch' '\n+\tgit config branch.autosetuprebase local &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase remote on an untracked remote branch' '\n+\tgit config branch.autosetuprebase remote &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'autosetuprebase always on an untracked remote branch' '\n+\tgit config branch.autosetuprebase always &&\n+\tgit config remote.local.url . &&\n+\tgit config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+\t(git show-ref -q refs/remotes/local/master || git-fetch local) &&\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+'\n+\n+test_expect_success 'detect misconfigured autosetuprebase (bad value)' '\n+\tgit config branch.autosetuprebase garbage &&\n+\ttest_must_fail git branch\n+'\n+\n+test_expect_success 'detect misconfigured autosetuprebase (no value)' '\n+\tgit config --unset branch.autosetuprebase &&\n+\techo \"[branch] autosetuprebase\" >> .git/config &&\n+\ttest_must_fail git branch &&\n+\tgit config --unset branch.autosetuprebase\n+'\n+\n test_done\n-- \n1.5.5.1.179.g0325e.dirty\n"}]}