{"thread":{"id":"56173","subject":"[PATCH 0/1] Improve automatic setup of tracking for new branches","startedAt":"2021-07-28T13:53:05Z","lastAt":"2021-08-02T21:17:33Z","messageCount":20,"participants":["Ben Boeckel","Junio C Hamano","Philippe Blain","Ævar Arnfjörð Bjarmason","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"431397","messageId":"20210728135041.501850-1-mathstuf@gmail.com","threadId":"56173","inReplyTo":null,"subject":"[PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-28T13:50:40Z","receivedAt":"2021-07-28T13:53:05Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"Hi,\n\nI recently discovered some of the nicer behaviors of the `--track`\noption for local branches (courtesy of `vim-fugitive`'s status\nrendering). However, after a few weeks of slowly working `-t\norigin/master` into my workflow, I figured that Git could help me out\nhere.\n\nThis patch adds three new configuration variables to initialize the\n`branch.<name>.*` settings for tracking remote branches.\n\nI suspect there are more tests that should be added.\n\nThanks,\n\n--Ben\n\nBen Boeckel (1):\n  config: support setting up a remote tracking branch upon creation\n\n Documentation/config/branch.txt | 15 +++++++++\n branch.c                        | 28 ++++++++++------\n branch.h                        |  3 ++\n config.c                        | 15 +++++++++\n environment.c                   |  3 ++\n t/t3200-branch.sh               | 57 +++++++++++++++++++++++++++++++++\n 6 files changed, 111 insertions(+), 10 deletions(-)\n\n\nbase-commit: eb27b338a3e71c7c4079fbac8aeae3f8fbb5c687\n-- \n2.31.1\n\n"},{"id":"431398","messageId":"20210728135041.501850-2-mathstuf@gmail.com","threadId":"56173","inReplyTo":"20210728135041.501850-1-mathstuf@gmail.com","subject":"[PATCH 1/1] config: support setting up a remote tracking branch upon creation","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-28T13:50:41Z","receivedAt":"2021-07-28T13:53:38Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"The `branch.autoSetupMerge` works well for setting up tracking a local\nbranch, but there is no mechanism to automatically set up a remote\ntracking situation. This patch adds the following configuration values:\n\n  - `branch.defaultRemote`: initializes `branch.<name>.remote` if not\n    otherwise given;\n  - `branch.defaultPushRemote`: initializes `branch.<name>.pushRemote`\n    (currently falls back on `remote.pushDefault` when pushing); and\n  - `branch.defaultMerge`: initializes `branch.<name>.merge` if not\n    otherwise given.\n\nSigned-off-by: Ben Boeckel <mathstuf@gmail.com>\n---\n Documentation/config/branch.txt | 15 +++++++++\n branch.c                        | 28 ++++++++++------\n branch.h                        |  3 ++\n config.c                        | 15 +++++++++\n environment.c                   |  3 ++\n t/t3200-branch.sh               | 57 +++++++++++++++++++++++++++++++++\n 6 files changed, 111 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/config/branch.txt b/Documentation/config/branch.txt\nindex cc5f3249fc..6e9d446066 100644\n--- a/Documentation/config/branch.txt\n+++ b/Documentation/config/branch.txt\n@@ -1,3 +1,18 @@\n+branch.defaultRemote::\n+\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n+\tcheckout', this value will be used to initialize the\n+\t\"branch.<name>.remote\" setting.\n+\n+branch.defaultPushRemote::\n+\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n+\tcheckout', this value will be used to initialize the\n+\t\"branch.<name>.pushRemote\" setting.\n+\n+branch.defaultMerge::\n+\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n+\tcheckout', this value will be used to initialize the\n+\t\"branch.<name>.merge\" setting.\n+\n branch.autoSetupMerge::\n \tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n \tso that linkgit:git-pull[1] will appropriately merge from the\ndiff --git a/branch.c b/branch.c\nindex 7a88a4861e..0e8ece8259 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -60,6 +60,9 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \tconst char *shortname = NULL;\n \tstruct strbuf key = STRBUF_INIT;\n \tint rebasing = should_setup_rebase(origin);\n+\tconst char *actual_origin = origin ? origin : git_branch_remote;\n+\tconst char *actual_push_origin = git_branch_push_remote;\n+\tconst char *actual_remote = remote ? remote : git_branch_merge;\n \n \tif (skip_prefix(remote, \"refs/heads/\", &shortname)\n \t    && !strcmp(local, shortname)\n@@ -70,12 +73,17 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \t}\n \n \tstrbuf_addf(&key, \"branch.%s.remote\", local);\n-\tif (git_config_set_gently(key.buf, origin ? origin : \".\") < 0)\n+\tif (git_config_set_gently(key.buf, actual_origin ? actual_origin : \".\") < 0)\n+\t\tgoto out_err;\n+\n+\tstrbuf_reset(&key);\n+\tstrbuf_addf(&key, \"branch.%s.pushremote\", local);\n+\tif (git_config_set_gently(key.buf, actual_push_origin) < 0)\n \t\tgoto out_err;\n \n \tstrbuf_reset(&key);\n \tstrbuf_addf(&key, \"branch.%s.merge\", local);\n-\tif (git_config_set_gently(key.buf, remote) < 0)\n+\tif (git_config_set_gently(key.buf, actual_remote) < 0)\n \t\tgoto out_err;\n \n \tif (rebasing) {\n@@ -88,27 +96,27 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \n \tif (flag & BRANCH_CONFIG_VERBOSE) {\n \t\tif (shortname) {\n-\t\t\tif (origin)\n+\t\t\tif (actual_origin)\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote branch '%s' from '%s'.\"),\n-\t\t\t\t\t  local, shortname, origin);\n+\t\t\t\t\t  local, shortname, actual_origin);\n \t\t\telse\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track local branch '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track local branch '%s'.\"),\n \t\t\t\t\t  local, shortname);\n \t\t} else {\n-\t\t\tif (origin)\n+\t\t\tif (actual_origin)\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote ref '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote ref '%s'.\"),\n-\t\t\t\t\t  local, remote);\n+\t\t\t\t\t  local, actual_remote);\n \t\t\telse\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track local ref '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track local ref '%s'.\"),\n-\t\t\t\t\t  local, remote);\n+\t\t\t\t\t  local, actual_remote);\n \t\t}\n \t}\n \n@@ -119,9 +127,9 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \terror(_(\"Unable to write upstream branch configuration\"));\n \n \tadvise(_(tracking_advice),\n-\t       origin ? origin : \"\",\n-\t       origin ? \"/\" : \"\",\n-\t       shortname ? shortname : remote);\n+\t       actual_origin ? actual_origin : \"\",\n+\t       actual_origin ? \"/\" : \"\",\n+\t       shortname ? shortname : actual_remote);\n \n \treturn -1;\n }\ndiff --git a/branch.h b/branch.h\nindex df0be61506..6ce978731d 100644\n--- a/branch.h\n+++ b/branch.h\n@@ -14,6 +14,9 @@ enum branch_track {\n };\n \n extern enum branch_track git_branch_track;\n+extern const char* git_branch_remote;\n+extern const char* git_branch_push_remote;\n+extern const char* git_branch_merge;\n \n /* Functions for acting on the information about branches. */\n \ndiff --git a/config.c b/config.c\nindex f33abeab85..42fc510a9f 100644\n--- a/config.c\n+++ b/config.c\n@@ -1599,6 +1599,21 @@ static int git_default_branch_config(const char *var, const char *value)\n \t\t\treturn error(_(\"malformed value for %s\"), var);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"branch.defaultremote\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\treturn git_config_string(&git_branch_remote, var, value);\n+\t}\n+\tif (!strcmp(var, \"branch.defaultpushremote\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\treturn git_config_string(&git_branch_push_remote, var, value);\n+\t}\n+\tif (!strcmp(var, \"branch.defaultmerge\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\treturn git_config_string(&git_branch_merge, var, value);\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 2f27008424..3b4d54e7dc 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -60,6 +60,9 @@ int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n char *check_roundtrip_encoding = \"SHIFT-JIS\";\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n+const char* git_branch_remote = NULL;\n+const char* git_branch_push_remote = NULL;\n+const char* git_branch_merge = NULL;\n enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #ifndef OBJECT_CREATION_MODE\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex cc4b10236e..2edfb50872 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -797,6 +797,63 @@ test_expect_success 'test tracking setup via --track but deeper' '\n \ttest \"$(git config branch.my7.merge)\" = refs/heads/o/o\n '\n \n+test_expect_success 'test tracking setup via branch.default* and --track' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch --track other/foo my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\ttest \"$(git config branch.my2.remote)\" = other &&\n+\t! test \"$(git config branch.my2.pushremote)\" = other &&\n+\ttest \"$(git config branch.my2.merge)\" = refs/heads/foo\n+'\n+\n+test_expect_success 'test tracking setup via branch.default* and --no-track' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch --no-track my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\t! test \"$(git config branch.my2.remote)\" = local &&\n+\t! test \"$(git config branch.my2.pushremote)\" = other &&\n+\t! test \"$(git config branch.my2.merge)\" = refs/heads/main\n+'\n+\n+test_expect_success 'test tracking setup via branch.default*' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\ttest \"$(git config branch.my2.remote)\" = local &&\n+\t! test \"$(git config branch.my2.pushremote)\" = other &&\n+\ttest \"$(git config branch.my2.merge)\" = refs/heads/main\n+'\n+\n+test_expect_success 'test tracking setup via branch.default* with pushremote' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultpushremote other &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\ttest \"$(git config branch.my2.remote)\" = local &&\n+\ttest \"$(git config branch.my2.pushremote)\" = other &&\n+\ttest \"$(git config branch.my2.merge)\" = refs/heads/main\n+'\n+\n test_expect_success 'test deleting branch deletes branch config' '\n \tgit branch -d my7 &&\n \ttest -z \"$(git config branch.my7.remote)\" &&\n-- \n2.31.1\n\n"},{"id":"431411","messageId":"xmqqim0u9vnb.fsf@gitster.g","threadId":"56173","inReplyTo":"20210728135041.501850-2-mathstuf@gmail.com","subject":"Re: [PATCH 1/1] config: support setting up a remote tracking branch upon creation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-07-28T17:48:56Z","receivedAt":"2021-07-28T17:49:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ben Boeckel <mathstuf@gmail.com> writes:\n\n> The `branch.autoSetupMerge` works well for setting up tracking a local\n> branch, but there is no mechanism to automatically set up a remote\n> tracking situation.\n\nThis description is probably insufficient to explain what's missing,\nprobably because \"set up a remote tracking situation\" is a bit\nfuzzy.\n\nWithout this patch, I can do this already:\n\n    $ git checkout -t -b topic origin/topic\n\nAnd after the above, we have\n\n    [branch \"topic\"]\n\tremote = origin\n\tmerge = refs/heads/topic\n\nOf course, you can instead use a short-hand DWIM, e.g.\n\n    $ git checkout topic ;# assuming origin/topic exists\n\ngives us the same thing.  In either case, topic knows to integrate\nwith the 'topic' branch from remote 'origin' and push back there.\n\nSo instead of saying \"there is no mechanism to ...\", be a bit more\nspecific what you can and cannot do in this first paragraph.\n\nThen we can describe the solution we'd propose in the second and\nsubsequent paragraphs.\n\nThanks.\n\n\n\n> +branch.defaultRemote::\n> +\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n> +\tcheckout', this value will be used to initialize the\n> +\t\"branch.<name>.remote\" setting.\n\nYou mean without \"-t\"?  I offhand do not think of a reason why this\nis a good idea.  How would one create local topic branches that you\nplan to merge locally into your own larger topic branch to be shared\nwith others?  Shouldn't there be an easy way to countermand the\nsetting by this configuration?\n\n> +branch.defaultPushRemote::\n> +\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n> +\tcheckout', this value will be used to initialize the\n> +\t\"branch.<name>.pushRemote\" setting.\n\nDitto.\n\n> +branch.defaultMerge::\n> +\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n> +\tcheckout', this value will be used to initialize the\n> +\t\"branch.<name>.merge\" setting.\n\nSo the expected use case is to fork multiple local branches, to\nintegrate with the same branch from the remote?  I think we can\nalready do \n\n    $ git checkout -t -b xyzzy origin/master\n    $ git checkout -t -b frotz origin/master\n\nand you can lose -t with branch.autosetupmerge setting.  As the \"git\nbranch\" command needs to get the name of your branch (e.g. 'xyzzy'\nor 'frotz') and which remote tracking branch you start from\n(e.g. 'origin/master'), even with branch.{defaultRemote,defaultMerge}\nconfiguration, you wouldn't lose that many keystrokes, I suspect.\n\nOr do you plan to make\n\n    $ git branch xyzzy\n\na short-hand for\n\n    $ git branch -t xyzzy origin/master\n\nwhen defaultRemote and defaultMerge are set to 'origin' and\n'refs/heads/master'?  It would be way too confusing to start the\nnew branch from origin/master in such a case, as everybody learned\nthat \"git branch xyzzy\" that does not say where the branch initially\npoints at uses HEAD.\n"},{"id":"431416","messageId":"YQGhSTc9NoB4xEGA@erythro.dev.benboeckel.internal","threadId":"56173","inReplyTo":"xmqqim0u9vnb.fsf@gitster.g","subject":"Re: [PATCH 1/1] config: support setting up a remote tracking branch upon creation","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-28T18:26:17Z","receivedAt":"2021-07-28T18:26:22Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"On Wed, Jul 28, 2021 at 10:48:56 -0700, Junio C Hamano wrote:\n> Ben Boeckel <mathstuf@gmail.com> writes:\n> \n> > The `branch.autoSetupMerge` works well for setting up tracking a local\n> > branch, but there is no mechanism to automatically set up a remote\n> > tracking situation.\n> \n> This description is probably insufficient to explain what's missing,\n> probably because \"set up a remote tracking situation\" is a bit\n> fuzzy.\n\nFair enough. I finally understood what was going on with \"tracking\" only\nrecently. Usually I would track the remote's branch of the same name,\nbut I found that \"tracking\" `origin/master` instead of `myfork/topic`\nmakes `fugitive` render the following:\n\n  - commits on my topic that aren't integrated (this makes it easy to\n    tell it to \"amend this commit\" using its keybinding;\n  - commits on `master` that aren't on my topic (so I can see if there's\n    anything relevant to rebase on top of); and\n  - diffs against my fork's branch (as last fetched) so that I can see\n    the status.\n\nMaybe this is a tooling issue, but I saw this as a potential way to\navoid having to specify this information on every topic I create.\n\n> Without this patch, I can do this already:\n> \n>     $ git checkout -t -b topic origin/topic\n\nI should note that the *vast* majority of my development is done using\nthe fork-based workflow. I have `remote.pushDefault` set to my fork and\nI use `push.default = simple` (there are only a handful of repositories\nwhere \"my fork\" is also `origin` and I have, on multiple occasions,\nwanted to make forks even there).\n\nMy normal pattern is that I'm on the target branch already, so I have:\n\n    $ git checkout -b topic\n\nwhich doesn't do any tracking. Just `-t` makes it track my *local*\n`master` when I really want it to track `origin/master`. AFAIK, there's\nno shortcut for this other than to give the full `-t origin/master` at\nbranch creation time (and as something I do all the time).\n\n> And after the above, we have\n> \n>     [branch \"topic\"]\n> \tremote = origin\n> \tmerge = refs/heads/topic\n> \n> Of course, you can instead use a short-hand DWIM, e.g.\n> \n>     $ git checkout topic ;# assuming origin/topic exists\n> \n> gives us the same thing.  In either case, topic knows to integrate\n> with the 'topic' branch from remote 'origin' and push back there.\n\nThis doesn't match with my usual experience in fork-based workflows. I\nwant the topic to track `master` and then my `remote.pushDefault` makes\nsure it goes to \"the right place\" when pushing.\n\n> So instead of saying \"there is no mechanism to ...\", be a bit more\n> specific what you can and cannot do in this first paragraph.\n> \n> Then we can describe the solution we'd propose in the second and\n> subsequent paragraphs.\n> \n> Thanks.\n\nI'll work on an improved cover letter to give more background.\n\n> > +branch.defaultRemote::\n> > +\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n> > +\tcheckout', this value will be used to initialize the\n> > +\t\"branch.<name>.remote\" setting.\n> \n> You mean without \"-t\"?  I offhand do not think of a reason why this\n> is a good idea.  How would one create local topic branches that you\n> plan to merge locally into your own larger topic branch to be shared\n> with others?  Shouldn't there be an easy way to countermand the\n> setting by this configuration?\n\nEverything goes through merge requests for the projects I work on\nday-to-day (even contributions to \"my own\" projects due to CI\nworkflows). I added a test that `--no-track` works for this case (which\ngiven its rarity for me is the right tradeoff at least).\n\n> > +branch.defaultPushRemote::\n> > +\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n> > +\tcheckout', this value will be used to initialize the\n> > +\t\"branch.<name>.pushRemote\" setting.\n> \n> Ditto.\n> \n> > +branch.defaultMerge::\n> > +\tWhen a new branch is created with 'git branch', 'git switch' or 'git\n> > +\tcheckout', this value will be used to initialize the\n> > +\t\"branch.<name>.merge\" setting.\n> \n> So the expected use case is to fork multiple local branches, to\n> integrate with the same branch from the remote?  I think we can\n> already do \n> \n>     $ git checkout -t -b xyzzy origin/master\n>     $ git checkout -t -b frotz origin/master\n> \n> and you can lose -t with branch.autosetupmerge setting.  As the \"git\n> branch\" command needs to get the name of your branch (e.g. 'xyzzy'\n> or 'frotz') and which remote tracking branch you start from\n> (e.g. 'origin/master'), even with branch.{defaultRemote,defaultMerge}\n> configuration, you wouldn't lose that many keystrokes, I suspect.\n\nThere are times that I want to branch from HEAD, but track `master` (for\nexample, a branch destined for backporting to an older branch). The\nequivalent of:\n\n    $ git checkout release\n    $ git checkout -b backported-branch\n    $ git branch --set-upstream-to=origin/master\n\n> Or do you plan to make\n> \n>     $ git branch xyzzy\n> \n> a short-hand for\n> \n>     $ git branch -t xyzzy origin/master\n> \n> when defaultRemote and defaultMerge are set to 'origin' and\n> 'refs/heads/master'?  It would be way too confusing to start the\n> new branch from origin/master in such a case, as everybody learned\n> that \"git branch xyzzy\" that does not say where the branch initially\n> points at uses HEAD.\n\nNo, it would just *track* `origin/master`, not branch from it. It should\nbe shorthand for:\n\n    $ git branch xyzzy\n    $ git branch --set-upstream-to=origin/master xyzzy\n\nThough I personally use `git checkout -b` far more often to create\nbranches. And since \"every\" branch I make would have `-t origin/master`,\nI wanted to have configuration to do this part for me.\n\nHopefully this gives a clearer picture of where I'm coming from.\n\nThanks,\n\n--Ben\n"},{"id":"431417","messageId":"xmqq5ywu9tar.fsf@gitster.g","threadId":"56173","inReplyTo":"YQGhSTc9NoB4xEGA@erythro.dev.benboeckel.internal","subject":"Re: [PATCH 1/1] config: support setting up a remote tracking branch upon creation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-07-28T18:39:40Z","receivedAt":"2021-07-28T18:39:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ben Boeckel <mathstuf@gmail.com> writes:\n\n> Hopefully this gives a clearer picture of where I'm coming from.\n\nI think you gave descriptions to a reasonable level of detail to\nexplain what your expected workflow is, to what extent the current\ntools support the workflow already, and what are still missing (and\nyou want to extend the system to help).\n\nThe reason I asked these questions is to make sure that future\nreaders of \"git log\" after your contribution becomes part of our\nhistory will not have to ask them (as you won't be as readily\navailable to answer their questions).  So please don't be content\njust because you answered and helped _me_ understand where you're\ncoming from.  Make sure an updated documentation and proposed log\nmessage explains them well to our future readers without your\nassistance.\n\nThanks.\n\n"},{"id":"431452","messageId":"20210729020125.746206-1-mathstuf@gmail.com","threadId":"56173","inReplyTo":"20210728135041.501850-1-mathstuf@gmail.com","subject":"[PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-29T02:01:24Z","receivedAt":"2021-07-29T02:01:36Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"Hi,\n\nI recently discovered some of the nicer behaviors of the `--track`\noption for local branches (courtesy of `vim-fugitive`'s status\nrendering). However, after a few weeks of slowly working `-t\norigin/master` into my workflow, I figured that Git could help me out\nhere.\n\nThis patch adds two new configuration variables to initialize the\n`branch.<name>.*` settings for tracking remote branches.\n\nI searched the docs (including `Documentation/gitworkflows.txt`), but\ndidn't see anywhere to describe the fork-based workflow common on forges\n(such as GitHub and GitLab) where this felt \"at home\". I suppose I could\ndescribe the workflow I'm used to, but I think I'll hammer that out as\nblog posts before submitting it as documentation.\n\nI suspect there are more tests that should be added.\n\nThanks,\n\n--Ben\n\n---\nv1 -> v2:\n  - removed `branch.defaultPushRemote` (`remote.pushDefault` covers this\n    case already)\n  - improved the commit message with more background and an expanation\n    of the intended uses\n\nBen Boeckel (1):\n  config: support a default remote tracking setup upon branch creation\n\n Documentation/config/branch.txt | 14 ++++++++++++\n branch.c                        | 22 ++++++++++---------\n branch.h                        |  2 ++\n config.c                        | 10 +++++++++\n environment.c                   |  2 ++\n t/t3200-branch.sh               | 39 +++++++++++++++++++++++++++++++++\n 6 files changed, 79 insertions(+), 10 deletions(-)\n\n\nbase-commit: eb27b338a3e71c7c4079fbac8aeae3f8fbb5c687\n-- \n2.31.1\n\n"},{"id":"431453","messageId":"20210729020125.746206-2-mathstuf@gmail.com","threadId":"56173","inReplyTo":"20210729020125.746206-1-mathstuf@gmail.com","subject":"[PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-29T02:01:25Z","receivedAt":"2021-07-29T02:01:39Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"The `branch.autoSetupMerge` works well today for setting up tracking a\nlocal branch, but there is no easy mechanism to automatically set up a\nremote tracking situation for workflows which use a single set of\nbranches for integration without specifying `--track` to every branch\ncreation command or branching directly from the remote ref. This patch\nadds the following configuration values:\n\n  - `branch.defaultRemote`: initializes `branch.<name>.remote` if not\n    otherwise given;\n  - `branch.defaultMerge`: initializes `branch.<name>.merge` if not\n    otherwise given.\n\nThese effectively make branch creation commands such as `git branch`,\n`git switch`, and `git checkout -b` have an implicit `-t\n${branch.defaultRemote}/${branch.defaultMerge}` argument and is\nequivalent to doing:\n\n    $ git branch new-topic      # or another branch creation command\n    $ git branch --set-upstream-to=${branch.defaultRemote}/${branch.defaultMerge} new-topic\n\nIn a fork-based workflow where contributions to the main project flow in\nthrough forks of the main repository rather than pushing directly to it\n(not uncommon of forge-hosted projects), the following setup may be\nused:\n\n    $ git config remote.pushDefault myfork    # push to `myfork` by default\n    $ git config push.default simple          # the default\n    $ git config branch.autoSetupMerge always # always setup tracking\n    $ git config branch.defaultRemote origin  # track from `origin`\n    $ git config branch.defaultMerge main     # track the `main` branch\n\nWith this setup, branches will automatically be set up to track\n`origin/main` while being pushed to `myfork` by default. Some tools\n(at least Vim's fugitive plugin) will show the commit differences\nbetween both the tracking branch and the default push target. This\nallows such tools to easily show \"what needs to be merged?\", \"what has\nhappened on the target branch since this topic has been created?\", and\n\"what is my status against my fork's current status?\" at a glance.\n\nAdditionally, with the `extensions.worktreeConfig` setting, when a\nseparate work tree which is used for changes against a different branch\n(e.g., a branch tracking a prior release), the `branch.defaultMerge`\nsetting may be changed independently, e.g., to `maint`.\n\nSigned-off-by: Ben Boeckel <mathstuf@gmail.com>\n---\n Documentation/config/branch.txt | 14 ++++++++++++\n branch.c                        | 22 ++++++++++---------\n branch.h                        |  2 ++\n config.c                        | 10 +++++++++\n environment.c                   |  2 ++\n t/t3200-branch.sh               | 39 +++++++++++++++++++++++++++++++++\n 6 files changed, 79 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/config/branch.txt b/Documentation/config/branch.txt\nindex cc5f3249fc..ab5cd2c1ed 100644\n--- a/Documentation/config/branch.txt\n+++ b/Documentation/config/branch.txt\n@@ -1,3 +1,17 @@\n+branch.defaultRemote::\n+\tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n+\tso that it will track a branch on the specified remote. This can be\n+\tused, in conjunction with `branch.defaultMerge`, in projects where\n+\tbranches tend to target a single branch. This will be used to\n+\tinitialize the \"branch.<name>.remote\" setting.\n+\n+branch.defaultMerge::\n+\tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n+\tso that it will track a branch with this name. This can be used, in\n+\tconjunction with `branch.defaultRemote` in projects where branches tend\n+\tto target a single branch. This will be used to initialize the\n+\t\"branch.<name>.merge\" setting.\n+\n branch.autoSetupMerge::\n \tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n \tso that linkgit:git-pull[1] will appropriately merge from the\ndiff --git a/branch.c b/branch.c\nindex 7a88a4861e..097d5af647 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -60,6 +60,8 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \tconst char *shortname = NULL;\n \tstruct strbuf key = STRBUF_INIT;\n \tint rebasing = should_setup_rebase(origin);\n+\tconst char *actual_origin = origin ? origin : git_branch_remote;\n+\tconst char *actual_remote = remote ? remote : git_branch_merge;\n \n \tif (skip_prefix(remote, \"refs/heads/\", &shortname)\n \t    && !strcmp(local, shortname)\n@@ -70,12 +72,12 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \t}\n \n \tstrbuf_addf(&key, \"branch.%s.remote\", local);\n-\tif (git_config_set_gently(key.buf, origin ? origin : \".\") < 0)\n+\tif (git_config_set_gently(key.buf, actual_origin ? actual_origin : \".\") < 0)\n \t\tgoto out_err;\n \n \tstrbuf_reset(&key);\n \tstrbuf_addf(&key, \"branch.%s.merge\", local);\n-\tif (git_config_set_gently(key.buf, remote) < 0)\n+\tif (git_config_set_gently(key.buf, actual_remote) < 0)\n \t\tgoto out_err;\n \n \tif (rebasing) {\n@@ -88,27 +90,27 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \n \tif (flag & BRANCH_CONFIG_VERBOSE) {\n \t\tif (shortname) {\n-\t\t\tif (origin)\n+\t\t\tif (actual_origin)\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote branch '%s' from '%s'.\"),\n-\t\t\t\t\t  local, shortname, origin);\n+\t\t\t\t\t  local, shortname, actual_origin);\n \t\t\telse\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track local branch '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track local branch '%s'.\"),\n \t\t\t\t\t  local, shortname);\n \t\t} else {\n-\t\t\tif (origin)\n+\t\t\tif (actual_origin)\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote ref '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track remote ref '%s'.\"),\n-\t\t\t\t\t  local, remote);\n+\t\t\t\t\t  local, actual_remote);\n \t\t\telse\n \t\t\t\tprintf_ln(rebasing ?\n \t\t\t\t\t  _(\"Branch '%s' set up to track local ref '%s' by rebasing.\") :\n \t\t\t\t\t  _(\"Branch '%s' set up to track local ref '%s'.\"),\n-\t\t\t\t\t  local, remote);\n+\t\t\t\t\t  local, actual_remote);\n \t\t}\n \t}\n \n@@ -119,9 +121,9 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n \terror(_(\"Unable to write upstream branch configuration\"));\n \n \tadvise(_(tracking_advice),\n-\t       origin ? origin : \"\",\n-\t       origin ? \"/\" : \"\",\n-\t       shortname ? shortname : remote);\n+\t       actual_origin ? actual_origin : \"\",\n+\t       actual_origin ? \"/\" : \"\",\n+\t       shortname ? shortname : actual_remote);\n \n \treturn -1;\n }\ndiff --git a/branch.h b/branch.h\nindex df0be61506..7d7990dda7 100644\n--- a/branch.h\n+++ b/branch.h\n@@ -14,6 +14,8 @@ enum branch_track {\n };\n \n extern enum branch_track git_branch_track;\n+extern const char* git_branch_remote;\n+extern const char* git_branch_merge;\n \n /* Functions for acting on the information about branches. */\n \ndiff --git a/config.c b/config.c\nindex f33abeab85..a46c5a43a1 100644\n--- a/config.c\n+++ b/config.c\n@@ -1599,6 +1599,16 @@ static int git_default_branch_config(const char *var, const char *value)\n \t\t\treturn error(_(\"malformed value for %s\"), var);\n \t\treturn 0;\n \t}\n+\tif (!strcmp(var, \"branch.defaultremote\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\treturn git_config_string(&git_branch_remote, var, value);\n+\t}\n+\tif (!strcmp(var, \"branch.defaultmerge\")) {\n+\t\tif (!value)\n+\t\t\treturn config_error_nonbool(var);\n+\t\treturn git_config_string(&git_branch_merge, var, value);\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 2f27008424..d550deabbd 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -60,6 +60,8 @@ int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n char *check_roundtrip_encoding = \"SHIFT-JIS\";\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n+const char* git_branch_remote = NULL;\n+const char* git_branch_merge = NULL;\n enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #ifndef OBJECT_CREATION_MODE\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex cc4b10236e..82137e8451 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -797,6 +797,45 @@ test_expect_success 'test tracking setup via --track but deeper' '\n \ttest \"$(git config branch.my7.merge)\" = refs/heads/o/o\n '\n \n+test_expect_success 'test tracking setup via branch.default* and --track' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch --track other/foo my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\ttest \"$(git config branch.my2.remote)\" = other &&\n+\ttest \"$(git config branch.my2.merge)\" = refs/heads/foo\n+'\n+\n+test_expect_success 'test tracking setup via branch.default* and --no-track' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch --no-track my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\t! test \"$(git config branch.my2.remote)\" = local &&\n+\t! test \"$(git config branch.my2.merge)\" = refs/heads/main\n+'\n+\n+test_expect_success 'test tracking setup via branch.default*' '\n+\tgit config branch.autosetupmerge always &&\n+\tgit config branch.defaultremote local &&\n+\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n+\tgit branch my2 &&\n+\tgit config branch.autosetupmerge false &&\n+\ttest \"$(git config branch.my2.remote)\" = local &&\n+\ttest \"$(git config branch.my2.merge)\" = refs/heads/main\n+'\n+\n test_expect_success 'test deleting branch deletes branch config' '\n \tgit branch -d my7 &&\n \ttest -z \"$(git config branch.my7.remote)\" &&\n-- \n2.31.1\n\n"},{"id":"431536","messageId":"xmqqim0s394n.fsf@gitster.g","threadId":"56173","inReplyTo":"20210729020125.746206-1-mathstuf@gmail.com","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-07-30T01:04:08Z","receivedAt":"2021-07-30T01:04:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ben Boeckel <mathstuf@gmail.com> writes:\n\n> I searched the docs (including `Documentation/gitworkflows.txt`), but\n> didn't see anywhere to describe the fork-based workflow common on forges\n> (such as GitHub and GitLab) where this felt \"at home\".\n\nBefore you came, many users have used Git with these forges, so it\nmight be just the matter of correct terminology to use to find what\nto read about.  Does the keyword \"triangular workflow\" find what may\nhelp your way of working?\n\n\n"},{"id":"431537","messageId":"YQNW27NAHbET5CeH@erythro.dev.benboeckel.internal","threadId":"56173","inReplyTo":"xmqqim0s394n.fsf@gitster.g","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-30T01:33:15Z","receivedAt":"2021-07-30T01:33:21Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"On Thu, Jul 29, 2021 at 18:04:08 -0700, Junio C Hamano wrote:\n> Ben Boeckel <mathstuf@gmail.com> writes:\n> > I searched the docs (including `Documentation/gitworkflows.txt`), but\n> > didn't see anywhere to describe the fork-based workflow common on forges\n> > (such as GitHub and GitLab) where this felt \"at home\".\n> \n> Before you came, many users have used Git with these forges, so it\n> might be just the matter of correct terminology to use to find what\n> to read about.  Does the keyword \"triangular workflow\" find what may\n> help your way of working?\n\nOh, I'm familiar with it, I just didn't see a place which discussed it\nin the docs with respect to it as a *workflow*. The existing references\nare about the `@{push}`…selector (is there a name for these `@{}`\nsuffixes as a collection?) and a note under \"Future Work\" in\npartial-clone. Neither of these seemed like relevant places to discuss\nhow to set up remotes and tracking branches for the triangular workflow.\nI would expect it to be discussed in `gitworkflows.txt`, but I think\nsuch an addition is worthy of its own patchset rather than tacking it\nonto this.\n\nThanks,\n\n--Ben\n"},{"id":"431566","messageId":"9b8b3a12-6801-1c5d-9cfb-c87b51cd9548@gmail.com","threadId":"56173","inReplyTo":"20210729020125.746206-1-mathstuf@gmail.com","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Philippe Blain","fromEmail":"levraiphilippeblain@gmail.com","sentAt":"2021-07-30T13:35:39Z","receivedAt":"2021-07-30T13:35:44Z","isPatch":true,"sender":{"key":"levraiphilippeblain@gmail.com","avatar":"https://avatars.githubusercontent.com/u/44212482?v=4"},"body":"Hi Ben,\n\nLe 2021-07-28 à 22:01, Ben Boeckel a écrit :\n> Hi,\n> \n> I recently discovered some of the nicer behaviors of the `--track`\n> option for local branches (courtesy of `vim-fugitive`'s status\n> rendering). However, after a few weeks of slowly working `-t\n> origin/master` into my workflow, I figured that Git could help me out\n> here.\n> \n> This patch adds two new configuration variables to initialize the\n> `branch.<name>.*` settings for tracking remote branches.\n> \n> I searched the docs (including `Documentation/gitworkflows.txt`), but\n> didn't see anywhere to describe the fork-based workflow common on forges\n> (such as GitHub and GitLab) where this felt \"at home\". I suppose I could\n> describe the workflow I'm used to, but I think I'll hammer that out as\n> blog posts before submitting it as documentation.\n\nI'm in favor of a change like the one you propose, thanks for working on this!\n\nThe 'triangular' aka 'forking' workflow is, as you discovered, only explicitely\nmentioned in the description of '@{push}' [1]. 'gitworkflows(5)' is mostly about\nhow the workflow used by the Git projet itself (from the description):\n\n     This document attempts to write down and motivate some of the workflow\n     elements used for git.git itself.\n\n> \n> I suspect there are more tests that should be added.\n> \n> Thanks,\n> \n> --Ben\n> \n> ---\n> v1 -> v2:\n>    - removed `branch.defaultPushRemote` (`remote.pushDefault` covers this\n>      case already)\n>    - improved the commit message with more background and an expanation\n>      of the intended uses\n> \n\nSmall nit: usually when sending a second version of a patch, you would use\nthe '-v2' argument to 'git format-patch' so that the patch and cover letter\nis prefixed [PATCH v2].\n\n\n[1] https://git-scm.com/docs/gitrevisions#Documentation/gitrevisions.txt-emltbranchnamegtpushemegemmasterpushemempushem\n"},{"id":"431567","messageId":"bcbe13a8-7f22-7564-77cd-674c7b2acbf6@gmail.com","threadId":"56173","inReplyTo":"20210729020125.746206-2-mathstuf@gmail.com","subject":"Re: [PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Philippe Blain","fromEmail":"levraiphilippeblain@gmail.com","sentAt":"2021-07-30T13:35:49Z","receivedAt":"2021-07-30T13:35:54Z","isPatch":true,"sender":{"key":"levraiphilippeblain@gmail.com","avatar":"https://avatars.githubusercontent.com/u/44212482?v=4"},"body":"\n\nLe 2021-07-28 à 22:01, Ben Boeckel a écrit :\n> The `branch.autoSetupMerge` works well today for setting up tracking a\n> local branch, but there is no easy mechanism to automatically set up a\n> remote tracking situation for workflows which use a single set of\n> branches for integration without specifying `--track` to every branch\n> creation command or branching directly from the remote ref. This patch\n> adds the following configuration values:\n> \n>    - `branch.defaultRemote`: initializes `branch.<name>.remote` if not\n>      otherwise given;\n>    - `branch.defaultMerge`: initializes `branch.<name>.merge` if not\n>      otherwise given.\n> \n> These effectively make branch creation commands such as `git branch`,\n> `git switch`, and `git checkout -b` have an implicit `-t\n> ${branch.defaultRemote}/${branch.defaultMerge}` argument and is\n> equivalent to doing:\n> \n>      $ git branch new-topic      # or another branch creation command\n>      $ git branch --set-upstream-to=${branch.defaultRemote}/${branch.defaultMerge} new-topic\n> \n> In a fork-based workflow where contributions to the main project flow in\n> through forks of the main repository rather than pushing directly to it\n> (not uncommon of forge-hosted projects), the following setup may be\n> used:\n> \n>      $ git config remote.pushDefault myfork    # push to `myfork` by default\n>      $ git config push.default simple          # the default\n>      $ git config branch.autoSetupMerge always # always setup tracking\n\nOK, so if I understand correctly this exisiting setting has to be changed\nto 'always' for the new settings you are adding to take effect, right ?\nI think this does make sense, reading the description of 'branch.autoSetupMerge',\nbut maybe it should be spelled explicitely in the text of the commit message,\nand not just mentioned here in this terminal session excerpt.\n\n>      $ git config branch.defaultRemote origin  # track from `origin`\n>      $ git config branch.defaultMerge main     # track the `main` branch\n\nSmall nit: maybe I would invert these two, so it can read:\n\n       $ git config branch.defaultMerge main     # track the `main` branch ...\n       $ git config branch.defaultRemote origin  # ... from `origin`\n> \n> With this setup, branches will automatically be set up to track\n> `origin/main` while being pushed to `myfork` by default. Some tools\n> (at least Vim's fugitive plugin) will show the commit differences\n> between both the tracking branch and the default push target. This\n> allows such tools to easily show \"what needs to be merged?\", \"what has\n> happened on the target branch since this topic has been created?\", and\n> \"what is my status against my fork's current status?\" at a glance.\n> \n> Additionally, with the `extensions.worktreeConfig` setting, when a\n> separate work tree which is used for changes against a different branch\n> (e.g., a branch tracking a prior release), the `branch.defaultMerge`\n> setting may be changed independently, e.g., to `maint`.\n\nThis last paragraph is not explicitely needed, as nothing relating to\n'extensions.worktreeConfig' is changed here right ? It's just the normal\nway that this setting works.\n\n> \n> Signed-off-by: Ben Boeckel <mathstuf@gmail.com>\n> ---\n>   Documentation/config/branch.txt | 14 ++++++++++++\n>   branch.c                        | 22 ++++++++++---------\n>   branch.h                        |  2 ++\n>   config.c                        | 10 +++++++++\n>   environment.c                   |  2 ++\n>   t/t3200-branch.sh               | 39 +++++++++++++++++++++++++++++++++\n>   6 files changed, 79 insertions(+), 10 deletions(-)\n> \n> diff --git a/Documentation/config/branch.txt b/Documentation/config/branch.txt\n> index cc5f3249fc..ab5cd2c1ed 100644\n> --- a/Documentation/config/branch.txt\n> +++ b/Documentation/config/branch.txt\n> @@ -1,3 +1,17 @@\n> +branch.defaultRemote::\n> +\tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n> +\tso that it will track a branch on the specified remote. This can be\n> +\tused, in conjunction with `branch.defaultMerge`, in projects where\n> +\tbranches tend to target a single branch. This will be used to\n> +\tinitialize the \"branch.<name>.remote\" setting.\n> +\n> +branch.defaultMerge::\n> +\tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n> +\tso that it will track a branch with this name. This can be used, in\n> +\tconjunction with `branch.defaultRemote` in projects where branches tend\n> +\tto target a single branch. This will be used to initialize the\n> +\t\"branch.<name>.merge\" setting.\n\nFor the two setting above, if 'branch.autoSetupMerge' must be set to 'always' for\nthe settings to work, I think it should be explicitely mentioned.\n\n> +\n>   branch.autoSetupMerge::\n>   \tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n>   \tso that linkgit:git-pull[1] will appropriately merge from the\n> diff --git a/branch.c b/branch.c\n> index 7a88a4861e..097d5af647 100644\n> --- a/branch.c\n> +++ b/branch.c\n> @@ -60,6 +60,8 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n>   \tconst char *shortname = NULL;\n>   \tstruct strbuf key = STRBUF_INIT;\n>   \tint rebasing = should_setup_rebase(origin);\n> +\tconst char *actual_origin = origin ? origin : git_branch_remote;\n> +\tconst char *actual_remote = remote ? remote : git_branch_merge;\n>   \n>   \tif (skip_prefix(remote, \"refs/heads/\", &shortname)\n>   \t    && !strcmp(local, shortname)\n> @@ -70,12 +72,12 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n>   \t}\n>   \n>   \tstrbuf_addf(&key, \"branch.%s.remote\", local);\n> -\tif (git_config_set_gently(key.buf, origin ? origin : \".\") < 0)\n> +\tif (git_config_set_gently(key.buf, actual_origin ? actual_origin : \".\") < 0)\n>   \t\tgoto out_err;\n>   \n>   \tstrbuf_reset(&key);\n>   \tstrbuf_addf(&key, \"branch.%s.merge\", local);\n> -\tif (git_config_set_gently(key.buf, remote) < 0)\n> +\tif (git_config_set_gently(key.buf, actual_remote) < 0)\n>   \t\tgoto out_err;\n>   \n>   \tif (rebasing) {\n> @@ -88,27 +90,27 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n>   \n>   \tif (flag & BRANCH_CONFIG_VERBOSE) {\n>   \t\tif (shortname) {\n> -\t\t\tif (origin)\n> +\t\t\tif (actual_origin)\n>   \t\t\t\tprintf_ln(rebasing ?\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track remote branch '%s' from '%s' by rebasing.\") :\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track remote branch '%s' from '%s'.\"),\n> -\t\t\t\t\t  local, shortname, origin);\n> +\t\t\t\t\t  local, shortname, actual_origin);\n>   \t\t\telse\n>   \t\t\t\tprintf_ln(rebasing ?\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track local branch '%s' by rebasing.\") :\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track local branch '%s'.\"),\n>   \t\t\t\t\t  local, shortname);\n>   \t\t} else {\n> -\t\t\tif (origin)\n> +\t\t\tif (actual_origin)\n>   \t\t\t\tprintf_ln(rebasing ?\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track remote ref '%s' by rebasing.\") :\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track remote ref '%s'.\"),\n> -\t\t\t\t\t  local, remote);\n> +\t\t\t\t\t  local, actual_remote);\n>   \t\t\telse\n>   \t\t\t\tprintf_ln(rebasing ?\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track local ref '%s' by rebasing.\") :\n>   \t\t\t\t\t  _(\"Branch '%s' set up to track local ref '%s'.\"),\n> -\t\t\t\t\t  local, remote);\n> +\t\t\t\t\t  local, actual_remote);\n>   \t\t}\n>   \t}\n>   \n> @@ -119,9 +121,9 @@ int install_branch_config(int flag, const char *local, const char *origin, const\n>   \terror(_(\"Unable to write upstream branch configuration\"));\n>   \n>   \tadvise(_(tracking_advice),\n> -\t       origin ? origin : \"\",\n> -\t       origin ? \"/\" : \"\",\n> -\t       shortname ? shortname : remote);\n> +\t       actual_origin ? actual_origin : \"\",\n> +\t       actual_origin ? \"/\" : \"\",\n> +\t       shortname ? shortname : actual_remote);\n>   \n>   \treturn -1;\n>   }\n> diff --git a/branch.h b/branch.h\n> index df0be61506..7d7990dda7 100644\n> --- a/branch.h\n> +++ b/branch.h\n> @@ -14,6 +14,8 @@ enum branch_track {\n>   };\n>   \n>   extern enum branch_track git_branch_track;\n> +extern const char* git_branch_remote;\n> +extern const char* git_branch_merge;\n>   \n>   /* Functions for acting on the information about branches. */\n>   \n> diff --git a/config.c b/config.c\n> index f33abeab85..a46c5a43a1 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -1599,6 +1599,16 @@ static int git_default_branch_config(const char *var, const char *value)\n>   \t\t\treturn error(_(\"malformed value for %s\"), var);\n>   \t\treturn 0;\n>   \t}\n> +\tif (!strcmp(var, \"branch.defaultremote\")) {\n> +\t\tif (!value)\n> +\t\t\treturn config_error_nonbool(var);\n> +\t\treturn git_config_string(&git_branch_remote, var, value);\n> +\t}\n> +\tif (!strcmp(var, \"branch.defaultmerge\")) {\n> +\t\tif (!value)\n> +\t\t\treturn config_error_nonbool(var);\n> +\t\treturn git_config_string(&git_branch_merge, var, value);\n> +\t}\n>   \n>   \t/* Add other config variables here and to Documentation/config.txt. */\n>   \treturn 0;\n> diff --git a/environment.c b/environment.c\n> index 2f27008424..d550deabbd 100644\n> --- a/environment.c\n> +++ b/environment.c\n> @@ -60,6 +60,8 @@ int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n>   char *check_roundtrip_encoding = \"SHIFT-JIS\";\n>   unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n>   enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n> +const char* git_branch_remote = NULL;\n> +const char* git_branch_merge = NULL;\n\nCan the new settings be implemented without adding more global variables ?\nI think we are trying to move away from these. Apart from that the code\nlooks OK to me.\n\n>   enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n>   enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n>   #ifndef OBJECT_CREATION_MODE\n> diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\n> index cc4b10236e..82137e8451 100755\n> --- a/t/t3200-branch.sh\n> +++ b/t/t3200-branch.sh\n> @@ -797,6 +797,45 @@ test_expect_success 'test tracking setup via --track but deeper' '\n>   \ttest \"$(git config branch.my7.merge)\" = refs/heads/o/o\n>   '\n>   \n> +test_expect_success 'test tracking setup via branch.default* and --track' '\n> +\tgit config branch.autosetupmerge always &&\n\nYou can use 'test_config branch.autosetupmerge always' so that the\nconfig is only active for the duration of the 'test_expect_success' block\n(see t/test-lib-functions.sh).\n\n> +\tgit config branch.defaultremote local &&\n> +\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n> +\tgit branch --track other/foo my2 &&\n> +\tgit config branch.autosetupmerge false &&\n> +\ttest \"$(git config branch.my2.remote)\" = other &&\n\nHere and for the following line you can use 'test_cmp_config'.\n\n> +\ttest \"$(git config branch.my2.merge)\" = refs/heads/foo\n> +'\n\nThis tests checks that an explicit '--track' argument overrides the new configs.\nI would name it something like \"'--track overrides 'branch.default{merge,remote}'\"\nor something like this. I would also add another test before this one that just\nchecks that the new settings by themselves work as expected;\ni.e. a simple 'git checkout -b' and verifying that the\ntracking info is correctly configured according to 'branch.default{merge,remote}'.\n\n> +\n> +test_expect_success 'test tracking setup via branch.default* and --no-track' '\n> +\tgit config branch.autosetupmerge always &&\n> +\tgit config branch.defaultremote local &&\n> +\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n> +\tgit branch --no-track my2 &&\n> +\tgit config branch.autosetupmerge false &&\n> +\t! test \"$(git config branch.my2.remote)\" = local &&\n> +\t! test \"$(git config branch.my2.merge)\" = refs/heads/main\n\nHere you expect the configs to be absent, so for more clarity you could\ndo\n\n     git config branch.my2.remote >remote &&\n     test_must_be_empty remote\n\nand the same for merge.\n\n> +'\n> +\n> +test_expect_success 'test tracking setup via branch.default*' '\n> +\tgit config branch.autosetupmerge always &&\n> +\tgit config branch.defaultremote local &&\n> +\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n> +\tgit branch my2 &&\n> +\tgit config branch.autosetupmerge false &&\n> +\ttest \"$(git config branch.my2.remote)\" = local &&\n> +\ttest \"$(git config branch.my2.merge)\" = refs/heads/main\n> +'\n> +\n>   test_expect_success 'test deleting branch deletes branch config' '\n>   \tgit branch -d my7 &&\n>   \ttest -z \"$(git config branch.my7.remote)\" &&\n> \n\nOh, so here is the 'just test the new settings' test. Let's move that\none to be before the two others.\n\nAnother test that could be added is one that does not change\n'branch.autosetupmerge' but sets the new configs, and checks that the\ntracking info is *not* set.\n\nCheers,\n\nPhilippe.\n\n\n"},{"id":"431569","messageId":"YQQFWtKo8b1WJIGe@erythro.dev.benboeckel.internal","threadId":"56173","inReplyTo":"9b8b3a12-6801-1c5d-9cfb-c87b51cd9548@gmail.com","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-30T13:57:46Z","receivedAt":"2021-07-30T13:57:52Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"On Fri, Jul 30, 2021 at 09:35:39 -0400, Philippe Blain wrote:\n> I'm in favor of a change like the one you propose, thanks for working on this!\n\nThanks :) . Nice to know it'll be of use for others.\n\n> The 'triangular' aka 'forking' workflow is, as you discovered, only explicitely\n> mentioned in the description of '@{push}' [1]. 'gitworkflows(5)' is mostly about\n> how the workflow used by the Git projet itself (from the description):\n> \n>      This document attempts to write down and motivate some of the workflow\n>      elements used for git.git itself.\n\nAh, I missed that.\n\n> Le 2021-07-28 à 22:01, Ben Boeckel a écrit :\n> > v1 -> v2:\n> >    - removed `branch.defaultPushRemote` (`remote.pushDefault` covers this\n> >      case already)\n> >    - improved the commit message with more background and an expanation\n> >      of the intended uses\n> > \n> \n> Small nit: usually when sending a second version of a patch, you would use\n> the '-v2' argument to 'git format-patch' so that the patch and cover letter\n> is prefixed [PATCH v2].\n\nYes, I realized that I had forgotten the `--reroll-count=` argument when\nmaking this patch (I suppose a way to store the Cc list for a topic\nsomewhere would be nice so I didn't lean so heavily on shell history\nwould help this).\n\nFWIW, my main gripe with the email-based workflow is the lack of\ncoordinated metadata (LWN has numerous comments by me about my views if\nyou're curious, but I should really formalize them into blog posts). But\nwhen in Rome :) .\n\nThanks,\n\n--Ben\n"},{"id":"431572","messageId":"YQQHv/suvHohpFBe@erythro.dev.benboeckel.internal","threadId":"56173","inReplyTo":"bcbe13a8-7f22-7564-77cd-674c7b2acbf6@gmail.com","subject":"Re: [PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-30T14:07:59Z","receivedAt":"2021-07-30T14:08:04Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"On Fri, Jul 30, 2021 at 09:35:49 -0400, Philippe Blain wrote:\n> Le 2021-07-28 à 22:01, Ben Boeckel a écrit :\n> >      $ git config remote.pushDefault myfork    # push to `myfork` by default\n> >      $ git config push.default simple          # the default\n> >      $ git config branch.autoSetupMerge always # always setup tracking\n> \n> OK, so if I understand correctly this exisiting setting has to be changed\n> to 'always' for the new settings you are adding to take effect, right ?\n> I think this does make sense, reading the description of 'branch.autoSetupMerge',\n> but maybe it should be spelled explicitely in the text of the commit message,\n> and not just mentioned here in this terminal session excerpt.\n\nGood point. I'll add it.\n\n> >      $ git config branch.defaultRemote origin  # track from `origin`\n> >      $ git config branch.defaultMerge main     # track the `main` branch\n> \n> Small nit: maybe I would invert these two, so it can read:\n> \n>        $ git config branch.defaultMerge main     # track the `main` branch ...\n>        $ git config branch.defaultRemote origin  # ... from `origin`\n\nAgreed.\n\n> > Additionally, with the `extensions.worktreeConfig` setting, when a\n> > separate work tree which is used for changes against a different branch\n> > (e.g., a branch tracking a prior release), the `branch.defaultMerge`\n> > setting may be changed independently, e.g., to `maint`.\n> \n> This last paragraph is not explicitely needed, as nothing relating to\n> 'extensions.worktreeConfig' is changed here right ? It's just the normal\n> way that this setting works.\n\nYes. I'll mention more explicitly that this is the reason for preserving\nsplit settings (rather than a single `branch.defaultTrack = origin/main`\nsetting that I had thought about until I saw the `--worktree` flag to\n`git config` and was intrigued).\n\n> > +branch.defaultRemote::\n> > +\tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n> > +\tso that it will track a branch on the specified remote. This can be\n> > +\tused, in conjunction with `branch.defaultMerge`, in projects where\n> > +\tbranches tend to target a single branch. This will be used to\n> > +\tinitialize the \"branch.<name>.remote\" setting.\n> > +\n> > +branch.defaultMerge::\n> > +\tTells 'git branch', 'git switch' and 'git checkout' to set up new branches\n> > +\tso that it will track a branch with this name. This can be used, in\n> > +\tconjunction with `branch.defaultRemote` in projects where branches tend\n> > +\tto target a single branch. This will be used to initialize the\n> > +\t\"branch.<name>.merge\" setting.\n> \n> For the two setting above, if 'branch.autoSetupMerge' must be set to 'always' for\n> the settings to work, I think it should be explicitely mentioned.\n\nWill update.\n\n> > diff --git a/environment.c b/environment.c\n> > index 2f27008424..d550deabbd 100644\n> > --- a/environment.c\n> > +++ b/environment.c\n> > @@ -60,6 +60,8 @@ int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n> >   char *check_roundtrip_encoding = \"SHIFT-JIS\";\n> >   unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n> >   enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n> > +const char* git_branch_remote = NULL;\n> > +const char* git_branch_merge = NULL;\n> \n> Can the new settings be implemented without adding more global variables ?\n> I think we are trying to move away from these. Apart from that the code\n> looks OK to me.\n\nI'm all for that, but didn't see guidance on where such things should be\nstored. There's not a \"context\" object passed around, but I guess\nstuffing it into `repository` is fine? This also gives a nice place to\nfree them rather than just leaking them too.\n\nAlas, after some cursory investigation,\n`config.c@@git_default_branch_config` does not have access to \"the\nrepository\" and the `cb` in `git_default_config` seems to be ~always be\n`NULL`. So maybe that will have to wait for further refactoring of the\nconfiguration tracking logic?\n\n> > diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\n> > index cc4b10236e..82137e8451 100755\n> > --- a/t/t3200-branch.sh\n> > +++ b/t/t3200-branch.sh\n> > @@ -797,6 +797,45 @@ test_expect_success 'test tracking setup via --track but deeper' '\n> >   \ttest \"$(git config branch.my7.merge)\" = refs/heads/o/o\n> >   '\n> >   \n> > +test_expect_success 'test tracking setup via branch.default* and --track' '\n> > +\tgit config branch.autosetupmerge always &&\n> \n> You can use 'test_config branch.autosetupmerge always' so that the\n> config is only active for the duration of the 'test_expect_success' block\n> (see t/test-lib-functions.sh).\n\nNifty.\n\n> > +\tgit config branch.defaultremote local &&\n> > +\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n> > +\tgit branch --track other/foo my2 &&\n> > +\tgit config branch.autosetupmerge false &&\n> > +\ttest \"$(git config branch.my2.remote)\" = other &&\n> \n> Here and for the following line you can use 'test_cmp_config'.\n> \n> > +\ttest \"$(git config branch.my2.merge)\" = refs/heads/foo\n> > +'\n> \n> This tests checks that an explicit '--track' argument overrides the new configs.\n> I would name it something like \"'--track overrides 'branch.default{merge,remote}'\"\n> or something like this. I would also add another test before this one that just\n> checks that the new settings by themselves work as expected;\n> i.e. a simple 'git checkout -b' and verifying that the\n> tracking info is correctly configured according to 'branch.default{merge,remote}'.\n> \n> > +\n> > +test_expect_success 'test tracking setup via branch.default* and --no-track' '\n> > +\tgit config branch.autosetupmerge always &&\n> > +\tgit config branch.defaultremote local &&\n> > +\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n> > +\tgit branch --no-track my2 &&\n> > +\tgit config branch.autosetupmerge false &&\n> > +\t! test \"$(git config branch.my2.remote)\" = local &&\n> > +\t! test \"$(git config branch.my2.merge)\" = refs/heads/main\n> \n> Here you expect the configs to be absent, so for more clarity you could\n> do\n> \n>      git config branch.my2.remote >remote &&\n>      test_must_be_empty remote\n> \n> and the same for merge.\n> \n> > +'\n> > +\n> > +test_expect_success 'test tracking setup via branch.default*' '\n> > +\tgit config branch.autosetupmerge always &&\n> > +\tgit config branch.defaultremote local &&\n> > +\tgit config branch.defaultmerge main &&\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/main || git fetch local) &&\n> > +\tgit branch my2 &&\n> > +\tgit config branch.autosetupmerge false &&\n> > +\ttest \"$(git config branch.my2.remote)\" = local &&\n> > +\ttest \"$(git config branch.my2.merge)\" = refs/heads/main\n> > +'\n> > +\n> >   test_expect_success 'test deleting branch deletes branch config' '\n> >   \tgit branch -d my7 &&\n> >   \ttest -z \"$(git config branch.my7.remote)\" &&\n> > \n> \n> Oh, so here is the 'just test the new settings' test. Let's move that\n> one to be before the two others.\n> \n> Another test that could be added is one that does not change\n> 'branch.autosetupmerge' but sets the new configs, and checks that the\n> tracking info is *not* set.\n\nI'll make the test suite updates as well.\n\nThanks for the review,\n\n--Ben\n"},{"id":"431579","messageId":"7b50ebc6-7b28-412d-b124-9bd54750c922@gmail.com","threadId":"56173","inReplyTo":"YQQFWtKo8b1WJIGe@erythro.dev.benboeckel.internal","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Philippe Blain","fromEmail":"levraiphilippeblain@gmail.com","sentAt":"2021-07-30T16:01:36Z","receivedAt":"2021-07-30T16:01:41Z","isPatch":true,"sender":{"key":"levraiphilippeblain@gmail.com","avatar":"https://avatars.githubusercontent.com/u/44212482?v=4"},"body":"Hi again,\n\nLe 2021-07-30 à 09:57, Ben Boeckel a écrit :\n> On Fri, Jul 30, 2021 at 09:35:39 -0400, Philippe Blain wrote:\n>> Le 2021-07-28 à 22:01, Ben Boeckel a écrit :\n>>\n>> Small nit: usually when sending a second version of a patch, you would use\n>> the '-v2' argument to 'git format-patch' so that the patch and cover letter\n>> is prefixed [PATCH v2].\n> \n> Yes, I realized that I had forgotten the `--reroll-count=` argument when\n> making this patch (I suppose a way to store the Cc list for a topic\n> somewhere would be nice so I didn't lean so heavily on shell history\n> would help this).\n\nThere is 'format.cc', but it's not branch-specific, so you would have to\nuse one worktree per branch with extension.worktreeConfig...\n\n> \n> FWIW, my main gripe with the email-based workflow is the lack of\n> coordinated metadata (LWN has numerous comments by me about my views if\n> you're curious, but I should really formalize them into blog posts). But\n> when in Rome :) .\n> \n\nI agree. I almost always use Gitgitgadget [1], which keeps track of the CC list for\nme, of updating the re-roll count, of adding the in-reply-to header such that subsequent\nversions of the series are sent as a response to the cover letter of the previous version,\ngenerating a range-diff against the previous version,\ncommenting on the PR when the series is mentioned in \"What's cooking\", etc.\n\nSome things it does not support are: sending a patch as a response to some random\nmail on the list, which is sometimes useful, reading the commit notes to generate\nin-patch commentaries [2], customizing the diff generated by 'format-patch'.\nOther things are listed at [3].\n\nRecently I've even been using only the terminal with Gitgitgadget:\nI use 'git branch --edit-description'\nto write my cover letter, and then use the 'gh' GitHub CLI to open my PR:\n\n$ git config --get-regexp alias.desc*\nalias.desc-title !git config branch.$(git branch --show-current).description | head -1\nalias.desc-body !git config branch.$(git branch --show-current).description | tail -n+3\n$ gh pr create --title \"$(git desc-title)\" --body \"$(git desc-body)\" --head phil-blain:$(git branch --show-current)\n\n\nCheers,\nPhilippe.\n\n[1] https://gitgitgadget.github.io/\n[2] https://github.com/gitgitgadget/gitgitgadget/issues/173\n[3] https://github.com/gitgitgadget/gitgitgadget/issues\n"},{"id":"431589","messageId":"xmqqim0r1ze0.fsf@gitster.g","threadId":"56173","inReplyTo":"bcbe13a8-7f22-7564-77cd-674c7b2acbf6@gmail.com","subject":"Re: [PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-07-30T17:32:07Z","receivedAt":"2021-07-30T17:32:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Philippe Blain <levraiphilippeblain@gmail.com> writes:\n\n>> diff --git a/environment.c b/environment.c\n>> index 2f27008424..d550deabbd 100644\n>> --- a/environment.c\n>> +++ b/environment.c\n>> @@ -60,6 +60,8 @@ int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n>>   char *check_roundtrip_encoding = \"SHIFT-JIS\";\n>>   unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n>>   enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n>> +const char* git_branch_remote = NULL;\n>> +const char* git_branch_merge = NULL;\n\nStyle:\n (1) asterisk sticks to the identifier, not type, in our codebase.\n (2) do not initialize globals and statics to 0 or NULL.\n\n> Can the new settings be implemented without adding more global variables ?\n\nThis is worth considering in the longer term.  For things like these\nnew configuration items and existign git_branch_track, we already\nhave reasonably made abstraction that branch.c is where interesting\nactions happen (like setting up remote tracking, etc), so there is\nno reason for them to be in environment.c or *.h to be visible to\nanywhere outside branch.c file.\n\nI wonder if it is a matter of moving git_default_branch_config() to\nbranch.c from config.c and make it global, while moving these global\nvariables also to branch.c and make them file-local?\n\nI am still unsure without the expected use-case well documented, if\nit is clear enough for users to learn how and when these new\nconfigurations should be used (as opposed to following the\ntraditional triangular workflow) with only the documentation updates\nin this patch, but at least I can trust others like you to give\ninput to polish this into a reasonable shape.\n\nThanks for a review (and thanks for starting the effort, Ben).\n\n\n\n\n"},{"id":"431590","messageId":"YQQ6xSlX+0LvBBWX@erythro.dev.benboeckel.internal","threadId":"56173","inReplyTo":"7b50ebc6-7b28-412d-b124-9bd54750c922@gmail.com","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-07-30T17:45:41Z","receivedAt":"2021-07-30T17:45:49Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"On Fri, Jul 30, 2021 at 12:01:36 -0400, Philippe Blain wrote:\n> Hi again,\n> \n> Le 2021-07-30 à 09:57, Ben Boeckel a écrit :\n> > On Fri, Jul 30, 2021 at 09:35:39 -0400, Philippe Blain wrote:\n> >> Le 2021-07-28 à 22:01, Ben Boeckel a écrit :\n> >>\n> >> Small nit: usually when sending a second version of a patch, you would use\n> >> the '-v2' argument to 'git format-patch' so that the patch and cover letter\n> >> is prefixed [PATCH v2].\n> > \n> > Yes, I realized that I had forgotten the `--reroll-count=` argument when\n> > making this patch (I suppose a way to store the Cc list for a topic\n> > somewhere would be nice so I didn't lean so heavily on shell history\n> > would help this).\n> \n> There is 'format.cc', but it's not branch-specific, so you would have to\n> use one worktree per branch with extension.worktreeConfig...\n\nI suppose a `branch.<name>.cc` configuration might be in order :) .\nThough at that point, `branch.<name>.rerollCount` and\n`branch.<name>.sendEmailTo` also make sense…\n\nMore brainstorming below too.\n\n> > FWIW, my main gripe with the email-based workflow is the lack of\n> > coordinated metadata (LWN has numerous comments by me about my views if\n> > you're curious, but I should really formalize them into blog posts). But\n> > when in Rome :) .\n> \n> I agree. I almost always use Gitgitgadget [1], which keeps track of the CC list for\n> me, of updating the re-roll count, of adding the in-reply-to header such that subsequent\n> versions of the series are sent as a response to the cover letter of the previous version,\n> generating a range-diff against the previous version,\n> commenting on the PR when the series is mentioned in \"What's cooking\", etc.\n\nThat's nifty. I guess since I started here, things are a bit messy for\nthis patch though?\n\n> Some things it does not support are: sending a patch as a response to some random\n> mail on the list, which is sometimes useful, reading the commit notes to generate\n> in-patch commentaries [2], customizing the diff generated by 'format-patch'.\n> Other things are listed at [3].\n> \n> Recently I've even been using only the terminal with Gitgitgadget:\n> I use 'git branch --edit-description'\n> to write my cover letter, and then use the 'gh' GitHub CLI to open my PR:\n\nI think having `branch.<name>.coverLetter` and/or\n`branch.coverLetterDirectory` (defaulting to reading `<name>` or\n`<name>.txt`) to store the cover letter contents would be nice. I know\nI've blown away enough `0000-*.patch` edits with an ill-timed `git\nformat-patch` before…\n\nForges could use this to hook in with their push options[1] through\ntheir wrappers or other tools.\n\n--Ben\n\n[1]https://docs.gitlab.com/ee/user/project/push_options.html#push-options-for-merge-requests\n"},{"id":"431684","messageId":"87sfzsngad.fsf@evledraar.gmail.com","threadId":"56173","inReplyTo":"20210729020125.746206-2-mathstuf@gmail.com","subject":"Re: [PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-08-02T13:02:41Z","receivedAt":"2021-08-02T13:10:40Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Wed, Jul 28 2021, Ben Boeckel wrote:\n\n> The `branch.autoSetupMerge` works well today for setting up tracking a\n> local branch, but there is no easy mechanism to automatically set up a\n> remote tracking situation for workflows which use a single set of\n> branches for integration without specifying `--track` to every branch\n> creation command or branching directly from the remote ref. This patch\n> adds the following configuration values:\n>\n>   - `branch.defaultRemote`: initializes `branch.<name>.remote` if not\n>     otherwise given;\n>   - `branch.defaultMerge`: initializes `branch.<name>.merge` if not\n>     otherwise given.\n\nNot a new issue per-se, but what if you've got a branch called\ndefaultRemote? It seems to me that any new branch.<name>.* config closes\nthe door for a <name> we squat on.\n\nGiven that we have checkout.defaultRemote and this also affects\nswitch/checkout it seems better to continue in the checkout.* namespace\neven if it wasn't for that, but given the config squatting issue\nespecially so....\n\nFor what it's worth I usually use the checkout.defaultRemote option\n(which I added) and:\n\n    git checkout master &&\n    git branch -m master <topic-name>\n\nSee 8d7b558baeb (checkout & worktree: introduce checkout.defaultRemote,\n2018-06-05). It seems to me from that patch diff that you could modify\nsome docs / tests for this, no? E.g. how it interacts with git-worktree.\n\nI like this direction, but just have a concern that this is a place\nwhere we need to consider all the UX in the area overall, and that any\noptions/config don't overtly interact in a bad way.\n"},{"id":"431685","messageId":"YQfwJOxlBOUWiH1V@erythro.dev.benboeckel.internal","threadId":"56173","inReplyTo":"87sfzsngad.fsf@evledraar.gmail.com","subject":"Re: [PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Ben Boeckel","fromEmail":"mathstuf@gmail.com","sentAt":"2021-08-02T13:16:20Z","receivedAt":"2021-08-02T13:16:26Z","isPatch":true,"sender":{"key":"mathstuf@gmail.com","avatar":"https://avatars.githubusercontent.com/u/97253?v=4"},"body":"On Mon, Aug 02, 2021 at 15:02:41 +0200, Ævar Arnfjörð Bjarmason wrote:\n> On Wed, Jul 28 2021, Ben Boeckel wrote:\n> > The `branch.autoSetupMerge` works well today for setting up tracking a\n> > local branch, but there is no easy mechanism to automatically set up a\n> > remote tracking situation for workflows which use a single set of\n> > branches for integration without specifying `--track` to every branch\n> > creation command or branching directly from the remote ref. This patch\n> > adds the following configuration values:\n> >\n> >   - `branch.defaultRemote`: initializes `branch.<name>.remote` if not\n> >     otherwise given;\n> >   - `branch.defaultMerge`: initializes `branch.<name>.merge` if not\n> >     otherwise given.\n> \n> Not a new issue per-se, but what if you've got a branch called\n> defaultRemote? It seems to me that any new branch.<name>.* config closes\n> the door for a <name> we squat on.\n\nIt doesn't seem that shadowing is actually a thing:\n\n    % git init\n    Initialized empty Git repository in …/git-shadow/.git/\n    % git config foo.bar true\n    % git config foo.bar.baz true\n    % git config --get foo.bar\n    true\n    % git config --get foo.bar.baz\n    true\n\n> Given that we have checkout.defaultRemote and this also affects\n> switch/checkout it seems better to continue in the checkout.* namespace\n> even if it wasn't for that, but given the config squatting issue\n> especially so....\n> \n> For what it's worth I usually use the checkout.defaultRemote option\n> (which I added) and:\n> \n>     git checkout master &&\n>     git branch -m master <topic-name>\n> \n> See 8d7b558baeb (checkout & worktree: introduce checkout.defaultRemote,\n> 2018-06-05). It seems to me from that patch diff that you could modify\n> some docs / tests for this, no? E.g. how it interacts with git-worktree.\n\nI think it would be weird for `checkout.*` to affect `git branch` which\ndoes no checkout at all. I want it to set up for simple branch creation\nas well, so this would be a hole in my use case.\n\n> I like this direction, but just have a concern that this is a place\n> where we need to consider all the UX in the area overall, and that any\n> options/config don't overtly interact in a bad way.\n\nI'll have to look at adding test cases as to how it interacts with\n`checkout.defaultRemote`.\n\nThanks,\n\n--Ben\n"},{"id":"431700","messageId":"87k0l3oo38.fsf@evledraar.gmail.com","threadId":"56173","inReplyTo":"YQfwJOxlBOUWiH1V@erythro.dev.benboeckel.internal","subject":"Re: [PATCH 1/1] config: support a default remote tracking setup upon branch creation","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-08-02T15:20:01Z","receivedAt":"2021-08-02T15:36:49Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Mon, Aug 02 2021, Ben Boeckel wrote:\n\n> On Mon, Aug 02, 2021 at 15:02:41 +0200, Ævar Arnfjörð Bjarmason wrote:\n>> On Wed, Jul 28 2021, Ben Boeckel wrote:\n>> > The `branch.autoSetupMerge` works well today for setting up tracking a\n>> > local branch, but there is no easy mechanism to automatically set up a\n>> > remote tracking situation for workflows which use a single set of\n>> > branches for integration without specifying `--track` to every branch\n>> > creation command or branching directly from the remote ref. This patch\n>> > adds the following configuration values:\n>> >\n>> >   - `branch.defaultRemote`: initializes `branch.<name>.remote` if not\n>> >     otherwise given;\n>> >   - `branch.defaultMerge`: initializes `branch.<name>.merge` if not\n>> >     otherwise given.\n>> \n>> Not a new issue per-se, but what if you've got a branch called\n>> defaultRemote? It seems to me that any new branch.<name>.* config closes\n>> the door for a <name> we squat on.\n>\n> It doesn't seem that shadowing is actually a thing:\n>\n>     % git init\n>     Initialized empty Git repository in …/git-shadow/.git/\n>     % git config foo.bar true\n>     % git config foo.bar.baz true\n>     % git config --get foo.bar\n>     true\n>     % git config --get foo.bar.baz\n>     true\n\nYou're right, I was misrecalling (or mis-imagining) some edge case there\nthat doesn't exist. I also tested setting branch.defaultRemote=true and\nmoving a branch.defaultRemote.* branch with \"git branch -m\", but it also\ndoes the right thing. Nevermind.\n\n>> Given that we have checkout.defaultRemote and this also affects\n>> switch/checkout it seems better to continue in the checkout.* namespace\n>> even if it wasn't for that, but given the config squatting issue\n>> especially so....\n>> \n>> For what it's worth I usually use the checkout.defaultRemote option\n>> (which I added) and:\n>> \n>>     git checkout master &&\n>>     git branch -m master <topic-name>\n>> \n>> See 8d7b558baeb (checkout & worktree: introduce checkout.defaultRemote,\n>> 2018-06-05). It seems to me from that patch diff that you could modify\n>> some docs / tests for this, no? E.g. how it interacts with git-worktree.\n>\n> I think it would be weird for `checkout.*` to affect `git branch` which\n> does no checkout at all. I want it to set up for simple branch creation\n> as well, so this would be a hole in my use case.\n\n*nod*, although your approach has the opposite problem of making branch\ncreation with \"checkout\" and \"switch\" (and presumably \"worktree\")\nimpacted by \"branch.*' config.\n\nIn a way that's more sensible, in that we can imagine those commands\ncalling \"git branch\" under the hood (which msotly doesn't actually\nhappen, except I think in the worktree case, but it's the same\nunderlying APIs).\n\n..\n\n>> I like this direction, but just have a concern that this is a place\n>> where we need to consider all the UX in the area overall, and that any\n>> options/config don't overtly interact in a bad way.\n>\n> I'll have to look at adding test cases as to how it interacts with\n> `checkout.defaultRemote`.\n>\n> Thanks,\n\n....right, none of that mess is a showstopper, I'm just prodding you to\nlook at if any of those edge cases are made better/worse by these\nadditions. Thanks!\n"},{"id":"431764","messageId":"nycvar.QRO.7.76.6.2108022316370.55@tvgsbejvaqbjf.bet","threadId":"56173","inReplyTo":"7b50ebc6-7b28-412d-b124-9bd54750c922@gmail.com","subject":"Re: [PATCH 0/1] Improve automatic setup of tracking for new branches","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2021-08-02T21:17:13Z","receivedAt":"2021-08-02T21:17:33Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Philippe,\n\nOn Fri, 30 Jul 2021, Philippe Blain wrote:\n\n> Recently I've even been using only the terminal with Gitgitgadget:\n> I use 'git branch --edit-description'\n> to write my cover letter, and then use the 'gh' GitHub CLI to open my PR:\n>\n> $ git config --get-regexp alias.desc*\n> alias.desc-title !git config branch.$(git branch --show-current).description |\n> head -1\n> alias.desc-body !git config branch.$(git branch --show-current).description |\n> tail -n+3\n> $ gh pr create --title \"$(git desc-title)\" --body \"$(git desc-body)\" --head\n> phil-blain:$(git branch --show-current)\n\nI bet you could streamline this even further by defining a `gh` alias:\nhttps://cli.github.com/manual/gh_alias_set\n\nCiao,\nDscho\n"}]}