{"thread":{"id":"21966","subject":"[RFC/PATCH] branch: new option --will-track","startedAt":"2009-12-16T09:39:59Z","lastAt":"2010-01-05T22:38:18Z","messageCount":5,"participants":["Dave Olszewski","Junio C Hamano","Andreas Krey","Nanako Shiraishi"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"129986","messageId":"1260956399-13802-1-git-send-email-cxreg@pobox.com","threadId":"21966","inReplyTo":null,"subject":"[RFC/PATCH] branch: new option --will-track","fromName":"Dave Olszewski","fromEmail":"cxreg@pobox.com","sentAt":"2009-12-16T09:39:59Z","receivedAt":"2009-12-16T09:39:59Z","isPatch":true,"sender":{"key":"cxreg@pobox.com","avatar":"https://avatars.githubusercontent.com/u/55474?v=4"},"body":"A common question from users creating branches in an environment where\nthey intend to push the branch to a shared bare repository, and then\nlater pull commits from upstream into the branch that they initially\ncreated, is how do they create the branch with this tracking info\nalready set up.\n\nThis feature allows them to pre-specify the tracking info in their\nconfig, so that after the branch has been pushed, no futher action is\nneeded to pull future commits.\n\nSigned-off-by: Dave Olszewski <cxreg@pobox.com>\n---\n Documentation/git-branch.txt   |    7 +++++++\n Documentation/git-checkout.txt |    4 ++++\n branch.c                       |    7 +++++--\n branch.h                       |    2 +-\n builtin-branch.c               |   18 +++++++++++++++++-\n builtin-checkout.c             |   19 +++++++++++++++++--\n cache.h                        |    1 +\n t/t3200-branch.sh              |    8 ++++++++\n t/t7201-co.sh                  |   10 ++++++++++\n 9 files changed, 70 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt\nindex 0e83680..ca7b120 100644\n--- a/Documentation/git-branch.txt\n+++ b/Documentation/git-branch.txt\n@@ -129,6 +129,13 @@ start-point is either a local or remote branch.\n \tDo not set up \"upstream\" configuration, even if the\n \tbranch.autosetupmerge configuration variable is true.\n \n+--will-track <remote ref>::\n+\tInstead of tracking the starting point, a user might wish to set\n+\tup tracking info for a future location of the branch once it's\n+\tbeen pushed to a remote.  Specifying this allows you to\n+\tconfigure the branch in such a way before the branch actually\n+\texists on the remote.\n+\n --contains <commit>::\n \tOnly list branches which contain the specified commit.\n \ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex 37c1810..c18852a 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -86,6 +86,10 @@ explicitly give a name with '-b' in such a case.\n \tDo not set up \"upstream\" configuration, even if the\n \tbranch.autosetupmerge configuration variable is true.\n \n+--will-track <remote ref>::\n+\tConfigure \"upstream\" as a yet-nonexistent remote branch.  See\n+\t\"--will-track\" in linkgit:git-branch[1] for details.\n+\n -l::\n \tCreate the new branch's reflog; see linkgit:git-branch[1] for\n \tdetails.\ndiff --git a/branch.c b/branch.c\nindex 05ef3f5..c3f6bbe 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -126,7 +126,8 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,\n \n void create_branch(const char *head,\n \t\t   const char *name, const char *start_name,\n-\t\t   int force, int reflog, enum branch_track track)\n+\t\t   int force, int reflog, enum branch_track track,\n+\t\t   const char *will_track)\n {\n \tstruct ref_lock *lock;\n \tstruct commit *commit;\n@@ -184,7 +185,9 @@ void create_branch(const char *head,\n \t\tsnprintf(msg, sizeof msg, \"branch: Created from %s\",\n \t\t\t start_name);\n \n-\tif (real_ref && track)\n+\tif (will_track)\n+\t\tsetup_tracking(name, will_track, track);\n+\telse if (real_ref && track)\n \t\tsetup_tracking(name, real_ref, track);\n \n \tif (write_ref_sha1(lock, sha1, msg) < 0)\ndiff --git a/branch.h b/branch.h\nindex eed817a..30fd5c7 100644\n--- a/branch.h\n+++ b/branch.h\n@@ -13,7 +13,7 @@\n  * branch for (if any).\n  */\n void create_branch(const char *head, const char *name, const char *start_name,\n-\t\t   int force, int reflog, enum branch_track track);\n+\t\t   int force, int reflog, enum branch_track track, const char *will_track);\n \n /*\n  * Remove information about the state of working on the current\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 05e876e..b29e6cf 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -556,12 +556,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tenum branch_track track;\n \tint kinds = REF_LOCAL_BRANCH;\n \tstruct commit_list *with_commit = NULL;\n+\tchar *will_track = NULL;\n \n \tstruct option options[] = {\n \t\tOPT_GROUP(\"Generic options\"),\n \t\tOPT__VERBOSE(&verbose),\n \t\tOPT_SET_INT('t', \"track\",  &track, \"set up tracking mode (see git-pull(1))\",\n \t\t\tBRANCH_TRACK_EXPLICIT),\n+\t\tOPT_STRING(0, \"will-track\", &will_track, \"future remote branch\",\n+\t\t\t\"set up branch to track future remote branch\"),\n \t\tOPT_BOOLEAN( 0 , \"color\",  &branch_use_color, \"use colored output\"),\n \t\tOPT_SET_INT('r', NULL,     &kinds, \"act on remote-tracking branches\",\n \t\t\tREF_REMOTE_BRANCH),\n@@ -628,6 +631,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tif (!!delete + !!rename + !!force_create > 1)\n \t\tusage_with_options(builtin_branch_usage, options);\n \n+\tif (will_track) {\n+\t\twill_track = xstrdup(will_track);\n+\t\tif (strncmp(will_track, \"refs/remotes/\", 13)) {\n+\t\t\twill_track = xrealloc(will_track, sizeof(char) * (strlen(will_track) + 14));\n+\t\t\tmemmove(will_track + 13, will_track, strlen(will_track) + 1);\n+\t\t\tmemcpy(will_track, \"refs/remotes/\", 13);\n+\t\t}\n+\t\ttrack = BRANCH_TRACK_FUTURE;\n+\t}\n+\n \tif (delete)\n \t\treturn delete_branches(argc, argv, delete > 1, kinds);\n \telse if (argc == 0)\n@@ -638,9 +651,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\trename_branch(argv[0], argv[1], rename > 1);\n \telse if (argc <= 2)\n \t\tcreate_branch(head, argv[0], (argc == 2) ? argv[1] : head,\n-\t\t\t      force_create, reflog, track);\n+\t\t\t      force_create, reflog, track, will_track);\n \telse\n \t\tusage_with_options(builtin_branch_usage, options);\n \n+\tif (will_track)\n+\t\tfree(will_track);\n+\n \treturn 0;\n }\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 64f3a11..f69be79 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -34,6 +34,7 @@ struct checkout_opts {\n \tconst char *new_branch;\n \tint new_branch_log;\n \tenum branch_track track;\n+\tchar *will_track;\n };\n \n static int post_checkout_hook(struct commit *old, struct commit *new,\n@@ -484,7 +485,7 @@ static void update_refs_for_switch(struct checkout_opts *opts,\n \tconst char *old_desc;\n \tif (opts->new_branch) {\n \t\tcreate_branch(old->name, opts->new_branch, new->name, 0,\n-\t\t\t      opts->new_branch_log, opts->track);\n+\t\t\t      opts->new_branch_log, opts->track, opts->will_track);\n \t\tnew->name = opts->new_branch;\n \t\tsetup_branch_path(new);\n \t}\n@@ -621,6 +622,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\n \t\tOPT__QUIET(&opts.quiet),\n \t\tOPT_STRING('b', NULL, &opts.new_branch, \"new branch\", \"branch\"),\n+\t\tOPT_STRING(0, \"will-track\", &opts.will_track, \"future remote branch\", \"nonexistent branch on remote that will be tracked\"),\n \t\tOPT_BOOLEAN('l', NULL, &opts.new_branch_log, \"log for new branch\"),\n \t\tOPT_SET_INT('t', \"track\",  &opts.track, \"track\",\n \t\t\tBRANCH_TRACK_EXPLICIT),\n@@ -650,7 +652,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options, checkout_usage,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n-\tif (patch_mode && (opts.track > 0 || opts.new_branch\n+\tif (patch_mode && (opts.track > 0 || opts.new_branch || opts.will_track\n \t\t\t   || opts.new_branch_log || opts.merge || opts.force))\n \t\tdie (\"--patch is incompatible with all other options\");\n \n@@ -810,6 +812,19 @@ no_reference:\n \t\tif (!get_sha1(buf.buf, rev))\n \t\t\tdie(\"git checkout: branch %s already exists\", opts.new_branch);\n \t\tstrbuf_release(&buf);\n+\n+\t\tif (opts.will_track) {\n+\t\t\topts.will_track = xstrdup(opts.will_track);\n+\t\t\tif (strncmp(opts.will_track, \"refs/remotes/\", 13)) {\n+\t\t\t\topts.will_track = xrealloc(opts.will_track,\n+\t\t\t\t\tsizeof(char) * (strlen(opts.will_track) + 14));\n+\t\t\t\tmemmove(opts.will_track + 13, opts.will_track,\n+\t\t\t\t\tstrlen(opts.will_track) + 1);\n+\t\t\t\tmemcpy(opts.will_track, \"refs/remotes/\", 13);\n+\t\t\t}\n+\n+\t\t\topts.track = BRANCH_TRACK_FUTURE;\n+\t\t}\n \t}\n \n \tif (new.name && !new.commit) {\ndiff --git a/cache.h b/cache.h\nindex bf468e5..1dd7762 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -544,6 +544,7 @@ enum branch_track {\n \tBRANCH_TRACK_REMOTE,\n \tBRANCH_TRACK_ALWAYS,\n \tBRANCH_TRACK_EXPLICIT,\n+\tBRANCH_TRACK_FUTURE,\n };\n \n enum rebase_setup_type {\ndiff --git a/t/t3200-branch.sh b/t/t3200-branch.sh\nindex d59a9b4..67e769a 100755\n--- a/t/t3200-branch.sh\n+++ b/t/t3200-branch.sh\n@@ -137,6 +137,14 @@ test_expect_success 'test tracking setup via --track' \\\n      test $(git config branch.my1.remote) = local &&\n      test $(git config branch.my1.merge) = refs/heads/master'\n \n+test_expect_success 'test tracking setup via --will-track' \\\n+    'git config remote.local.url . &&\n+     git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+     (git show-ref -q refs/remotes/local/master || git fetch local) &&\n+     git branch --will-track local/my11 my11 local/master &&\n+     test $(git config branch.my11.remote) = local &&\n+     test $(git config branch.my11.merge) = refs/heads/my11'\n+\n test_expect_success 'test tracking setup (non-wildcard, matching)' \\\n     'git config remote.local.url . &&\n      git config remote.local.fetch refs/heads/master:refs/remotes/local/master &&\ndiff --git a/t/t7201-co.sh b/t/t7201-co.sh\nindex ebfd34d..803bcad 100755\n--- a/t/t7201-co.sh\n+++ b/t/t7201-co.sh\n@@ -330,6 +330,16 @@ test_expect_success \\\n     test \"$(git config branch.track2.merge)\"\n     git config branch.autosetupmerge false'\n \n+test_expect_success \\\n+    'checkout w/--will-track sets up tracking' '\n+    git config branch.autosetupmerge false &&\n+    git config remote.local.url . &&\n+    git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&\n+    git checkout master &&\n+    git checkout --will-track local/track3 -b track3 &&\n+    test \"$(git config branch.track3.remote)\" &&\n+    test \"$(git config branch.track3.merge)\"'\n+\n test_expect_success 'checkout w/--track from non-branch HEAD fails' '\n     git checkout master^0 &&\n     test_must_fail git symbolic-ref HEAD &&\n-- \n1.6.6.rc2.8.g5599df\n"},{"id":"130050","messageId":"7vaaxhdu1f.fsf@alter.siamese.dyndns.org","threadId":"21966","inReplyTo":"1260956399-13802-1-git-send-email-cxreg@pobox.com","subject":"Re: [RFC/PATCH] branch: new option --will-track","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-18T00:07:08Z","receivedAt":"2009-12-18T00:07:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dave Olszewski <cxreg@pobox.com> writes:\n\n> A common question from users creating branches in an environment where\n> they intend to push the branch to a shared bare repository, and then\n> later pull commits from upstream into the branch that they initially\n> created, is how do they create the branch with this tracking info\n> already set up.\n\nWe try reasonably hard not to force users to make a decision before it\ngets absolutely necessary [*1*].  This option seems to only help users who\ncan decide upfront upon \"git branch\" time if the branch is worth sharing\nwith others and if the name of the branch will be the final one, and\npeople who forget to give this new option when they ran \"git branch\", or\nthose who changed their mind as to what the newly created branch with this\noption should interact with, will still need to use \"git config\" to update\nthe settings.\n\nNot very nice, not because it solves only a part of the problem, but\nbecause it force users to decide early and not change their mind.\n\nInstead perhaps we would want to add an option to retarget an existing\nbranch any time the user wants, e.g. \"git branch --reconfigure\"?  Once we\nhave such an option, people who *can* decide upfront can use that feature\nwhen creating a new branch at the same time.\n\nAlso \"git pull --remember $there $this\" might be a good way to tell the\nconfiguration mechanism from the UI to remember that \"I always want to\nmerge $this branch from $there while on the branch I am currently on\", and\nits implementation may probably use \"git branch --reconfigure\" internally.\n\nHaving said all that, I am not very interested in topics on the mechanism\nthat updates or uses these variables, as I tend to avoid relying on them\nmyself, and instead teach people to spell them out (which seems to foster\nbetter understanding of what goes on, with reduced user confusion).\nHence, I wouldn't claim I have thought things through in this area, and\nthe above is just me thinking aloud [*2*].\n\n\n[Footnote]\n\n*1* There are ample examples, ranging from detached HEAD (you do not have\nto decide if the experiment you are going to do deserves a separate branch\nto store the result permanently) to the separation between commit and push\n(what you commit does not have to be perfect and you have a chance to tidy\nthem up before publishing).\n\n*2* IOW don't take my \"I am not interested\" as \"patches in this area have\nlittle chance of getting applied.\"\n"},{"id":"130063","messageId":"20091218061851.GA10221@inner.home.ulmdo.de","threadId":"21966","inReplyTo":"7vaaxhdu1f.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] branch: new option --will-track","fromName":"Andreas Krey","fromEmail":"a.krey@gmx.de","sentAt":"2009-12-18T06:18:51Z","receivedAt":"2009-12-18T06:18:51Z","isPatch":true,"sender":{"key":"a.krey@gmx.de","avatar":"https://avatars.githubusercontent.com/u/37810?v=4"},"body":"On Thu, 17 Dec 2009 16:07:08 +0000, Junio C Hamano wrote:\n...\n> Also \"git pull --remember $there $this\" might be a good way to tell the\n> configuration mechanism from the UI to remember that \"I always want to\n> merge $this branch from $there while on the branch I am currently on\", and\n> its implementation may probably use \"git branch --reconfigure\" internally.\n\nActually my favorite would be 'git push --track $there', pushing\nthe current local branch to $there and setting up tracking. That\nway the tracking decision need not be made before the remote\nbranch actually exists.\n\nAndreas\n"},{"id":"130064","messageId":"7vd42c4ur9.fsf@alter.siamese.dyndns.org","threadId":"21966","inReplyTo":"20091218061851.GA10221@inner.home.ulmdo.de","subject":"Re: [RFC/PATCH] branch: new option --will-track","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-12-18T07:16:26Z","receivedAt":"2009-12-18T07:16:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Andreas Krey <a.krey@gmx.de> writes:\n\n> On Thu, 17 Dec 2009 16:07:08 +0000, Junio C Hamano wrote:\n> ...\n>> Also \"git pull --remember $there $this\" might be a good way to tell the\n>> configuration mechanism from the UI to remember that \"I always want to\n>> merge $this branch from $there while on the branch I am currently on\", and\n>> its implementation may probably use \"git branch --reconfigure\" internally.\n>\n> Actually my favorite would be 'git push --track $there', pushing\n> the current local branch to $there and setting up tracking. That\n> way the tracking decision need not be made before the remote\n> branch actually exists.\n\nYeah, it may be useful, but that belongs to the same \"in addition to the\nmost flexible form, we might want to _also_ do so\" category, as the one\nthat makes \"git pull\" remember.\n\nThe advantage of remembering upon the first pull is that the request to\nremember doesn't involve any \"push is reverse of pull\" indirection.\nInstead, it is exactly what the user actually has done once: \"I'm doing\nthis once, remember it for me\".  Compared to it, I think it is less\nobvious to make the first push remember its reverse [*1*].\n\nAnother issue that you need to think about is how you will allow users to\nset up \"integrate with merge or rebase\" when making \"push\" remember.\n\nAn option with \"pull\" would make it much more obvious what is going on, as\nthe user would say \"git pull --rebase --remember $there $this\" if rebasing\nis desired, and that is what is going to be remembered; again that is\nthanks to the \"I'm doing this once, remember it for me\" semantics.\n\n\n[Footnote]\n\n*1* I am not saying \"if you have 'pull --remember' you don't need 'push\n--remember'\" or vice versa.  As long as each (judged individually) makes\nsense we could have both.\n"},{"id":"130869","messageId":"20100106073818.6117@nanako3.lavabit.com","threadId":"21966","inReplyTo":"7vaaxhdu1f.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] branch: new option --will-track","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2010-01-05T22:38:18Z","receivedAt":"2010-01-05T22:38:18Z","isPatch":true,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Junio, could you tell us what happened to this thread?\n\nAfter \"--will-track\" was discussed and agreed not to be the best\nsolution, and \"pull --remember\" and \"branch --configure\" were\nsuggested, nothing happened.\n"}]}