{"thread":{"id":"35623","subject":"[RFC/PATCH] format-patch: introduce branch.*.forkedFrom","startedAt":"2014-01-07T20:29:48Z","lastAt":"2014-02-18T19:52:55Z","messageCount":37,"participants":["Ramkumar Ramachandra","Junio C Hamano","Jeff King","Philip Oakley","Johan Herland"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"232844","messageId":"1389126588-3663-1-git-send-email-artagnon@gmail.com","threadId":"35623","inReplyTo":null,"subject":"[RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-07T20:29:48Z","receivedAt":"2014-01-07T20:29:48Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"A very common workflow for preparing patches involves working off a\ntopic branch and generating patches against 'master' to send off to the\nmaintainer. However, a plain\n\n  $ git format-patch -o outgoing\n\nis a no-op on a topic branch, and the user has to remember to specify\n'master' explicitly everytime. This problem is not unique to\nformat-patch; even a\n\n  $ git rebase -i\n\nis a no-op because the branch to rebase against isn't specified.\n\nTo tackle this problem, introduce branch.*.forkedFrom which can specify\nthe parent branch of a topic branch. Future patches will build\nfunctionality around this new configuration variable.\n\nCc: Jeff King <peff@peff.net>\nCc: Junio C Hamano <gister@pobox.com>\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n Since -M, -C, -D are left in the argc, checking argc < 2 isn't\n sufficient.\n\n I wanted to get an early reaction before wiring up checkout and\n rebase.\n\n But I wanted to discuss the overall idea of the patch.\n builtin/log.c           | 21 +++++++++++++++++++++\n t/t4014-format-patch.sh | 20 ++++++++++++++++++++\n 2 files changed, 41 insertions(+)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex b97373d..525e696 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -674,6 +674,7 @@ static int thread;\n static int do_signoff;\n static const char *signature = git_version_string;\n static int config_cover_letter;\n+static const char *config_base_branch;\n \n enum {\n \tCOVER_UNSET,\n@@ -750,6 +751,22 @@ static int git_format_config(const char *var, const char *value, void *cb)\n \t\tconfig_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;\n \t\treturn 0;\n \t}\n+\tif (starts_with(var, \"branch.\")) {\n+\t\tconst char *name = var + 7;\n+\t\tconst char *subkey = strrchr(name, '.');\n+\t\tstruct strbuf buf = STRBUF_INIT;\n+\n+\t\tif (!subkey)\n+\t\t\treturn 0;\n+\t\tstrbuf_add(&buf, name, subkey - name);\n+\t\tif (branch_get(buf.buf) != branch_get(NULL))\n+\t\t\treturn 0;\n+\t\tstrbuf_release(&buf);\n+\t\tif (!strcmp(subkey, \".forkedfrom\")) {\n+\t\t\tif (git_config_string(&config_base_branch, var, value))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n \n \treturn git_log_config(var, value, cb);\n }\n@@ -1324,6 +1341,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n \t\tdie (_(\"--subject-prefix and -k are mutually exclusive.\"));\n \trev.preserve_subject = keep_subject;\n \n+\tif (argc < 2 && config_base_branch) {\n+\t\targv[1] = config_base_branch;\n+\t\targc++;\n+\t}\n \targc = setup_revisions(argc, argv, &rev, &s_r_opt);\n \tif (argc > 1)\n \t\tdie (_(\"unrecognized argument: %s\"), argv[1]);\ndiff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\nindex 73194b2..2ea94af 100755\n--- a/t/t4014-format-patch.sh\n+++ b/t/t4014-format-patch.sh\n@@ -1370,4 +1370,24 @@ test_expect_success 'cover letter auto user override' '\n \ttest_line_count = 2 list\n '\n \n+test_expect_success 'branch.*.forkedFrom matches' '\n+\tmkdir -p tmp &&\n+\ttest_when_finished \"rm -rf tmp;\n+\t\tgit config --unset branch.rebuild-1.forkedFrom\" &&\n+\n+\tgit config branch.rebuild-1.forkedFrom master &&\n+\tgit format-patch -o tmp >list &&\n+\ttest_line_count = 2 list\n+'\n+\n+test_expect_success 'branch.*.forkedFrom does not match' '\n+\tmkdir -p tmp &&\n+\ttest_when_finished \"rm -rf tmp;\n+\t\tgit config --unset branch.foo.forkedFrom\" &&\n+\n+\tgit config branch.foo.forkedFrom master &&\n+\tgit format-patch -o tmp >list &&\n+\ttest_line_count = 0 list\n+'\n+\n test_done\n-- \n1.8.5.2.234.gba2dde8.dirty\n"},{"id":"232845","messageId":"CALkWK0=g5-9r05vTkys8Tk7iv7PqPZJvMvkYsAOnN_F90Mtgxg@mail.gmail.com","threadId":"35623","inReplyTo":"1389126588-3663-1-git-send-email-artagnon@gmail.com","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-07T20:30:44Z","receivedAt":"2014-01-07T20:30:44Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"[Fixed typo in Junio's address]\n\nOn Wed, Jan 8, 2014 at 1:59 AM, Ramkumar Ramachandra <artagnon@gmail.com> wrote:\n> A very common workflow for preparing patches involves working off a\n> topic branch and generating patches against 'master' to send off to the\n> maintainer. However, a plain\n>\n>   $ git format-patch -o outgoing\n>\n> is a no-op on a topic branch, and the user has to remember to specify\n> 'master' explicitly everytime. This problem is not unique to\n> format-patch; even a\n>\n>   $ git rebase -i\n>\n> is a no-op because the branch to rebase against isn't specified.\n>\n> To tackle this problem, introduce branch.*.forkedFrom which can specify\n> the parent branch of a topic branch. Future patches will build\n> functionality around this new configuration variable.\n>\n> Cc: Jeff King <peff@peff.net>\n> Cc: Junio C Hamano <gister@pobox.com>\n> Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n> ---\n>  Since -M, -C, -D are left in the argc, checking argc < 2 isn't\n>  sufficient.\n>\n>  I wanted to get an early reaction before wiring up checkout and\n>  rebase.\n>\n>  But I wanted to discuss the overall idea of the patch.\n>  builtin/log.c           | 21 +++++++++++++++++++++\n>  t/t4014-format-patch.sh | 20 ++++++++++++++++++++\n>  2 files changed, 41 insertions(+)\n>\n> diff --git a/builtin/log.c b/builtin/log.c\n> index b97373d..525e696 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -674,6 +674,7 @@ static int thread;\n>  static int do_signoff;\n>  static const char *signature = git_version_string;\n>  static int config_cover_letter;\n> +static const char *config_base_branch;\n>\n>  enum {\n>         COVER_UNSET,\n> @@ -750,6 +751,22 @@ static int git_format_config(const char *var, const char *value, void *cb)\n>                 config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;\n>                 return 0;\n>         }\n> +       if (starts_with(var, \"branch.\")) {\n> +               const char *name = var + 7;\n> +               const char *subkey = strrchr(name, '.');\n> +               struct strbuf buf = STRBUF_INIT;\n> +\n> +               if (!subkey)\n> +                       return 0;\n> +               strbuf_add(&buf, name, subkey - name);\n> +               if (branch_get(buf.buf) != branch_get(NULL))\n> +                       return 0;\n> +               strbuf_release(&buf);\n> +               if (!strcmp(subkey, \".forkedfrom\")) {\n> +                       if (git_config_string(&config_base_branch, var, value))\n> +                               return -1;\n> +               }\n> +       }\n>\n>         return git_log_config(var, value, cb);\n>  }\n> @@ -1324,6 +1341,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n>                 die (_(\"--subject-prefix and -k are mutually exclusive.\"));\n>         rev.preserve_subject = keep_subject;\n>\n> +       if (argc < 2 && config_base_branch) {\n> +               argv[1] = config_base_branch;\n> +               argc++;\n> +       }\n>         argc = setup_revisions(argc, argv, &rev, &s_r_opt);\n>         if (argc > 1)\n>                 die (_(\"unrecognized argument: %s\"), argv[1]);\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> index 73194b2..2ea94af 100755\n> --- a/t/t4014-format-patch.sh\n> +++ b/t/t4014-format-patch.sh\n> @@ -1370,4 +1370,24 @@ test_expect_success 'cover letter auto user override' '\n>         test_line_count = 2 list\n>  '\n>\n> +test_expect_success 'branch.*.forkedFrom matches' '\n> +       mkdir -p tmp &&\n> +       test_when_finished \"rm -rf tmp;\n> +               git config --unset branch.rebuild-1.forkedFrom\" &&\n> +\n> +       git config branch.rebuild-1.forkedFrom master &&\n> +       git format-patch -o tmp >list &&\n> +       test_line_count = 2 list\n> +'\n> +\n> +test_expect_success 'branch.*.forkedFrom does not match' '\n> +       mkdir -p tmp &&\n> +       test_when_finished \"rm -rf tmp;\n> +               git config --unset branch.foo.forkedFrom\" &&\n> +\n> +       git config branch.foo.forkedFrom master &&\n> +       git format-patch -o tmp >list &&\n> +       test_line_count = 0 list\n> +'\n> +\n>  test_done\n> --\n> 1.8.5.2.234.gba2dde8.dirty\n>\n"},{"id":"232847","messageId":"xmqq8uurcyw2.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"1389126588-3663-1-git-send-email-artagnon@gmail.com","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-07T20:36:45Z","receivedAt":"2014-01-07T20:36:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ramkumar Ramachandra <artagnon@gmail.com> writes:\n\n> A very common workflow for preparing patches involves working off a\n> topic branch and generating patches against 'master' to send off to the\n> maintainer. However, a plain\n>\n>   $ git format-patch -o outgoing\n>\n> is a no-op on a topic branch, and the user has to remember to specify\n> 'master' explicitly everytime. This problem is not unique to\n> format-patch; even a\n>\n>   $ git rebase -i\n>\n> is a no-op because the branch to rebase against isn't specified.\n>\n> To tackle this problem, introduce branch.*.forkedFrom which can specify\n> the parent branch of a topic branch. Future patches will build\n> functionality around this new configuration variable.\n>\n\nI do not mind allowing laziness by defaulting to something, but I am\nnot enthused by an approach that adds the new variable whose value\nis questionable.  The description does not justify at all why\n@{upstream} is not a good default (unless the workflow is screwed up\nand @{upstream} is set to point at somewhere that is _not_ a true\nupstream, that is).\n\n> Cc: Jeff King <peff@peff.net>\n> Cc: Junio C Hamano <gister@pobox.com>\n> Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n> ---\n>  Since -M, -C, -D are left in the argc, checking argc < 2 isn't\n>  sufficient.\n>\n>  I wanted to get an early reaction before wiring up checkout and\n>  rebase.\n>\n>  But I wanted to discuss the overall idea of the patch.\n>  builtin/log.c           | 21 +++++++++++++++++++++\n>  t/t4014-format-patch.sh | 20 ++++++++++++++++++++\n>  2 files changed, 41 insertions(+)\n>\n> diff --git a/builtin/log.c b/builtin/log.c\n> index b97373d..525e696 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -674,6 +674,7 @@ static int thread;\n>  static int do_signoff;\n>  static const char *signature = git_version_string;\n>  static int config_cover_letter;\n> +static const char *config_base_branch;\n>  \n>  enum {\n>  \tCOVER_UNSET,\n> @@ -750,6 +751,22 @@ static int git_format_config(const char *var, const char *value, void *cb)\n>  \t\tconfig_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;\n>  \t\treturn 0;\n>  \t}\n> +\tif (starts_with(var, \"branch.\")) {\n> +\t\tconst char *name = var + 7;\n> +\t\tconst char *subkey = strrchr(name, '.');\n> +\t\tstruct strbuf buf = STRBUF_INIT;\n> +\n> +\t\tif (!subkey)\n> +\t\t\treturn 0;\n> +\t\tstrbuf_add(&buf, name, subkey - name);\n> +\t\tif (branch_get(buf.buf) != branch_get(NULL))\n> +\t\t\treturn 0;\n> +\t\tstrbuf_release(&buf);\n> +\t\tif (!strcmp(subkey, \".forkedfrom\")) {\n> +\t\t\tif (git_config_string(&config_base_branch, var, value))\n> +\t\t\t\treturn -1;\n> +\t\t}\n> +\t}\n>  \n>  \treturn git_log_config(var, value, cb);\n>  }\n> @@ -1324,6 +1341,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)\n>  \t\tdie (_(\"--subject-prefix and -k are mutually exclusive.\"));\n>  \trev.preserve_subject = keep_subject;\n>  \n> +\tif (argc < 2 && config_base_branch) {\n> +\t\targv[1] = config_base_branch;\n> +\t\targc++;\n> +\t}\n>  \targc = setup_revisions(argc, argv, &rev, &s_r_opt);\n>  \tif (argc > 1)\n>  \t\tdie (_(\"unrecognized argument: %s\"), argv[1]);\n> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh\n> index 73194b2..2ea94af 100755\n> --- a/t/t4014-format-patch.sh\n> +++ b/t/t4014-format-patch.sh\n> @@ -1370,4 +1370,24 @@ test_expect_success 'cover letter auto user override' '\n>  \ttest_line_count = 2 list\n>  '\n>  \n> +test_expect_success 'branch.*.forkedFrom matches' '\n> +\tmkdir -p tmp &&\n> +\ttest_when_finished \"rm -rf tmp;\n> +\t\tgit config --unset branch.rebuild-1.forkedFrom\" &&\n> +\n> +\tgit config branch.rebuild-1.forkedFrom master &&\n> +\tgit format-patch -o tmp >list &&\n> +\ttest_line_count = 2 list\n> +'\n> +\n> +test_expect_success 'branch.*.forkedFrom does not match' '\n> +\tmkdir -p tmp &&\n> +\ttest_when_finished \"rm -rf tmp;\n> +\t\tgit config --unset branch.foo.forkedFrom\" &&\n> +\n> +\tgit config branch.foo.forkedFrom master &&\n> +\tgit format-patch -o tmp >list &&\n> +\ttest_line_count = 0 list\n> +'\n> +\n>  test_done\n"},{"id":"232848","messageId":"20140107204035.GA27932@sigill.intra.peff.net","threadId":"35623","inReplyTo":"CALkWK0=g5-9r05vTkys8Tk7iv7PqPZJvMvkYsAOnN_F90Mtgxg@mail.gmail.com","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-07T20:40:35Z","receivedAt":"2014-01-07T20:40:35Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 08, 2014 at 02:00:44AM +0530, Ramkumar Ramachandra wrote:\n\n> On Wed, Jan 8, 2014 at 1:59 AM, Ramkumar Ramachandra <artagnon@gmail.com> wrote:\n> > A very common workflow for preparing patches involves working off a\n> > topic branch and generating patches against 'master' to send off to the\n> > maintainer. However, a plain\n> >\n> >   $ git format-patch -o outgoing\n> >\n> > is a no-op on a topic branch, and the user has to remember to specify\n> > 'master' explicitly everytime. This problem is not unique to\n> > format-patch; even a\n> >\n> >   $ git rebase -i\n> >\n> > is a no-op because the branch to rebase against isn't specified.\n> >\n> > To tackle this problem, introduce branch.*.forkedFrom which can specify\n> > the parent branch of a topic branch. Future patches will build\n> > functionality around this new configuration variable.\n> >\n> > Cc: Jeff King <peff@peff.net>\n> > Cc: Junio C Hamano <gister@pobox.com>\n> > Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n\nI have not carefully read some of the later bits of the discussion from\nlast night / this morning, so maybe I am missing something, but this\nseems backwards to me from what Junio and I were discussing earlier.\n\nThe point was that the meaning of \"@{upstream}\" (and \"branch.*.merge\")\nis _already_ \"forked-from\", and \"push -u\" and \"push.default=upstream\"\nare the odd men out. If we are going to add an option to distinguish the\ntwo branch relationships:\n\n  1. Where you forked from\n\n  2. Where you push to\n\nwe should leave @{upstream} as (1), and add a new option to represent\n(2). Not the other way around.\n\nAm I missing something?\n\n-Peff\n"},{"id":"232849","messageId":"CALkWK0=vXGiHbd__ZNfp42fRS_gK5MNmYx13=uzDfc0m==V5Fw@mail.gmail.com","threadId":"35623","inReplyTo":"xmqq8uurcyw2.fsf@gitster.dls.corp.google.com","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-07T20:40:45Z","receivedAt":"2014-01-07T20:40:45Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Junio C Hamano wrote:\n> I do not mind allowing laziness by defaulting to something, but I am\n> not enthused by an approach that adds the new variable whose value\n> is questionable.  The description does not justify at all why\n> @{upstream} is not a good default (unless the workflow is screwed up\n> and @{upstream} is set to point at somewhere that is _not_ a true\n> upstream, that is).\n\nDid you find the explanation I gave in\nhttp://article.gmane.org/gmane.comp.version-control.git/240077\nreasonable? I don't know why label the respin-workflow as being\n\"screwed up\".\n"},{"id":"232850","messageId":"xmqq4n5fcym7.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"CALkWK0=vXGiHbd__ZNfp42fRS_gK5MNmYx13=uzDfc0m==V5Fw@mail.gmail.com","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-07T20:42:40Z","receivedAt":"2014-01-07T20:42:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ramkumar Ramachandra <artagnon@gmail.com> writes:\n\n> Junio C Hamano wrote:\n>> I do not mind allowing laziness by defaulting to something, but I am\n>> not enthused by an approach that adds the new variable whose value\n>> is questionable.  The description does not justify at all why\n>> @{upstream} is not a good default (unless the workflow is screwed up\n>> and @{upstream} is set to point at somewhere that is _not_ a true\n>> upstream, that is).\n>\n> Did you find the explanation I gave in\n> http://article.gmane.org/gmane.comp.version-control.git/240077\n> reasonable?\n\nNo.\n"},{"id":"232851","messageId":"xmqqzjn7bjre.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"20140107204035.GA27932@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-07T20:48:53Z","receivedAt":"2014-01-07T20:48:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> The point was that the meaning of \"@{upstream}\" (and \"branch.*.merge\")\n> is _already_ \"forked-from\", and \"push -u\" and \"push.default=upstream\"\n> are the odd men out. If we are going to add an option to distinguish the\n> two branch relationships:\n>\n>   1. Where you forked from\n>\n>   2. Where you push to\n>\n> we should leave @{upstream} as (1), and add a new option to represent\n> (2). Not the other way around.\n\nThat matches my feeling as well.\n\nI am not sure if \"push -u\" is truly odd man out, though.  It was an\ninvention back in the \"you fetch from and push to the same place and\nthere is no other workflow support\" days, and in that context, the\n\"upstream\" meant just that: the place you fetch from, which happens\nto be the same as where you are pushing to right now.  If \"push -u\"\nsuddenly stopped setting the configuration to merge back from where\nit is pushing, that would regress for centralized folks, so I am not\nsure how it could be extended to also support triangular folks, but\nI do think @{upstream} should mean \"this is where I sync with to\nstay abreast with others\".\n"},{"id":"232853","messageId":"CALkWK0mGPhU-8vVg+xY-MGWNstxoXSU9MGQiNzyFN+-Q6Bw28A@mail.gmail.com","threadId":"35623","inReplyTo":"20140107204035.GA27932@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-07T21:02:10Z","receivedAt":"2014-01-07T21:02:10Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n> I have not carefully read some of the later bits of the discussion from\n> last night / this morning, so maybe I am missing something, but this\n> seems backwards to me from what Junio and I were discussing earlier.\n>\n> The point was that the meaning of \"@{upstream}\" (and \"branch.*.merge\")\n> is _already_ \"forked-from\", and \"push -u\" and \"push.default=upstream\"\n> are the odd men out. If we are going to add an option to distinguish the\n> two branch relationships:\n>\n>   1. Where you forked from\n>\n>   2. Where you push to\n>\n> we should leave @{upstream} as (1), and add a new option to represent\n> (2). Not the other way around.\n\nI have a local branch 'forkedfrom' that has two \"sources\": 'master'\nand 'ram/forkedfrom'. 'ram/forkedfrom' isn't a \"dumb\" publish-point:\nthe relationship information I get between 'forkedfrom' and\n'ram/forkedfrom' is very useful; it's what helps me tell how my\nre-roll is doing with respect to the original series; I'd often want\nto cherry-pick commits/ messages from my original series to prepare\nthe re-roll, so interaction with this source is quite high. On the\nother hand, the relationship information I get between 'forkedfrom'\nand 'master' is practically useless: 'forkedfrom' is always ahead of\n'master', and a divergence indicates that I need to rebase; I'll never\nreally need to interact with this source.\n\nI'm only thinking in terms of what infrastructure we've already built:\nif @{u} is set to 'ram/forkedfrom', we get a lot of information for\nfree _now_. If @{u} is set to 'master', the current git-status is\nunhelpful.\n"},{"id":"232856","messageId":"20140107211645.GC28102@sigill.intra.peff.net","threadId":"35623","inReplyTo":"CALkWK0mGPhU-8vVg+xY-MGWNstxoXSU9MGQiNzyFN+-Q6Bw28A@mail.gmail.com","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-07T21:16:45Z","receivedAt":"2014-01-07T21:16:45Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 08, 2014 at 02:32:10AM +0530, Ramkumar Ramachandra wrote:\n\n> > we should leave @{upstream} as (1), and add a new option to represent\n> > (2). Not the other way around.\n> \n> I have a local branch 'forkedfrom' that has two \"sources\": 'master'\n> and 'ram/forkedfrom'. 'ram/forkedfrom' isn't a \"dumb\" publish-point:\n> the relationship information I get between 'forkedfrom' and\n> 'ram/forkedfrom' is very useful; it's what helps me tell how my\n> re-roll is doing with respect to the original series; I'd often want\n> to cherry-pick commits/ messages from my original series to prepare\n> the re-roll, so interaction with this source is quite high. On the\n> other hand, the relationship information I get between 'forkedfrom'\n> and 'master' is practically useless: 'forkedfrom' is always ahead of\n> 'master', and a divergence indicates that I need to rebase; I'll never\n> really need to interact with this source.\n\nThanks for a concrete example.\n\nI definitely respect the desire to reuse the existing tooling we have\nfor @{u}. At the same time, I think you are warping the meaning of\n@{u} somewhat. It is _not_ your upstream here, but rather another\nversion of the branch that has useful changes in it. That might be\nsplitting hairs a bit, but I think you will find that the differences\nleak through in inconvenient spots (like format-patch, where you really\n_do_ want to default to the true upstream).\n\nIf we add \"@{publish}\" (and \"@{pu}\"), then it becomes very convenient to\nrefer to the ram/ version of your branch. That seems like an obvious\nfirst step to me. We don't have to add new config, because\n\"branch.*.pushremote\" already handles this.\n\nNow you can do \"git rebase @{pu}\" which is nice, but not _quite_ as nice\nas \"git rebase\", which defaults to \"@{u}\". That first step might be\nenough, and I'd hold off there and try it out for a few days or weeks\nfirst. But if you find in your workflow that you are having to specify\n\"@{pu}\" a lot, then maybe it is worth adding an option to default rebase\nto \"@{pu}\" instead of \"@{u}\".\n\nYou end up in the same place (\"git rebase\" without options does what you\nwant), but I think the underlying data more accurately represents what\nis going on (and there is no need to teach \"format-patch\" anything\nspecial).\n\n-Peff\n"},{"id":"232863","messageId":"CALkWK0=UkWEGhU6D8CQctdgTvZUUj276LSuNhSmRUMZ5mwZTeA@mail.gmail.com","threadId":"35623","inReplyTo":"20140107211645.GC28102@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] format-patch: introduce branch.*.forkedFrom","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-07T21:35:48Z","receivedAt":"2014-01-07T21:35:48Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n> I definitely respect the desire to reuse the existing tooling we have\n> for @{u}. At the same time, I think you are warping the meaning of\n> @{u} somewhat. It is _not_ your upstream here, but rather another\n> version of the branch that has useful changes in it. That might be\n> splitting hairs a bit, but I think you will find that the differences\n> leak through in inconvenient spots (like format-patch, where you really\n> _do_ want to default to the true upstream).\n\nThanks for the clear reasoning.\n\n> If we add \"@{publish}\" (and \"@{pu}\"), then it becomes very convenient to\n> refer to the ram/ version of your branch. That seems like an obvious\n> first step to me. We don't have to add new config, because\n> \"branch.*.pushremote\" already handles this.\n\nAgreed. I'll start working on @{publish}. It's going to take quite a\nbit of effort, because I won't actually start using it until my prompt\nis @{publish}-aware.\n\n> Now you can do \"git rebase @{pu}\" which is nice, but not _quite_ as nice\n> as \"git rebase\", which defaults to \"@{u}\". That first step might be\n> enough, and I'd hold off there and try it out for a few days or weeks\n> first. But if you find in your workflow that you are having to specify\n> \"@{pu}\" a lot, then maybe it is worth adding an option to default rebase\n> to \"@{pu}\" instead of \"@{u}\".\n\nActually, I'm not sure I'd use \"git rebase @{pu}\"; for me @{pu} is\nmainly a source of information for taking apart to build a new series.\n"},{"id":"232898","messageId":"20140108093338.GA15659@sigill.intra.peff.net","threadId":"35623","inReplyTo":"CALkWK0=UkWEGhU6D8CQctdgTvZUUj276LSuNhSmRUMZ5mwZTeA@mail.gmail.com","subject":"[RFC/PATCH 0/5] <branch>@{publish} shorthand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T09:33:38Z","receivedAt":"2014-01-08T09:33:38Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 08, 2014 at 03:05:48AM +0530, Ramkumar Ramachandra wrote:\n\n> Agreed. I'll start working on @{publish}. It's going to take quite a\n> bit of effort, because I won't actually start using it until my prompt\n> is @{publish}-aware.\n\nThere's a fair bit of refactoring involved. I took a stab at it and came\nup with the series below. No docs or tests, and some of the refactoring\nin remote.c feels a little weird. I can't help but feel more of the\nlogic from \"git push\" should be shared here.\n\nBut it at least works with my rudimentary examples. I'm hoping it will\nmake a good starting point for you to build on. Otherwise, I may get to\nit eventually, but it's not a high priority for me right now.\n\n> Actually, I'm not sure I'd use \"git rebase @{pu}\"; for me @{pu} is\n> mainly a source of information for taking apart to build a new series.\n\nAh, that's how I'd probably use it, too. :)\n\n  [1/5]: sha1_name: refactor upstream_mark\n  [2/5]: interpret_branch_name: factor out upstream handling\n  [3/5]: branch_get: return early on error\n  [4/5]: branch_get: provide per-branch pushremote pointers\n  [5/5]: implement @{publish} shorthand\n\n-Peff\n"},{"id":"232899","messageId":"20140108093424.GA15720@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108093338.GA15659@sigill.intra.peff.net","subject":"[PATCH 1/5] sha1_name: refactor upstream_mark","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T09:34:24Z","receivedAt":"2014-01-08T09:34:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"We will be adding new mark types in the future, so separate\nthe suffix data from the logic.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n sha1_name.c | 12 +++++++++---\n 1 file changed, 9 insertions(+), 3 deletions(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex b1873d8..0c50801 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -415,12 +415,12 @@ static int ambiguous_path(const char *path, int len)\n \treturn slash;\n }\n \n-static inline int upstream_mark(const char *string, int len)\n+static inline int at_mark(const char *string, int len,\n+\t\t\t  const char **suffix, int nr)\n {\n-\tconst char *suffix[] = { \"@{upstream}\", \"@{u}\" };\n \tint i;\n \n-\tfor (i = 0; i < ARRAY_SIZE(suffix); i++) {\n+\tfor (i = 0; i < nr; i++) {\n \t\tint suffix_len = strlen(suffix[i]);\n \t\tif (suffix_len <= len\n \t\t    && !memcmp(string, suffix[i], suffix_len))\n@@ -429,6 +429,12 @@ static inline int upstream_mark(const char *string, int len)\n \treturn 0;\n }\n \n+static inline int upstream_mark(const char *string, int len)\n+{\n+\tconst char *suffix[] = { \"@{upstream}\", \"@{u}\" };\n+\treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n+}\n+\n static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);\n static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);\n \n-- \n1.8.5.2.500.g8060133\n"},{"id":"232900","messageId":"20140108093450.GB15720@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108093338.GA15659@sigill.intra.peff.net","subject":"[PATCH 2/5] interpret_branch_name: factor out upstream handling","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T09:34:51Z","receivedAt":"2014-01-08T09:34:51Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"This function checks a few different @{}-constructs. The\nearly part checks for and dispatches us to helpers for each\nconstruct, but the code for handling @{upstream} is inline.\n\nLet's factor this out into its own function. This makes\ninterpret_branch_name more readable, and will make it much\nsimpler to add more constructs in future patches.\n\nWhile we're at it, let's also break apart the refactored\ncode into a few helper functions. These will be useful when\nwe implement similar @{upstream}-like constructs.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n sha1_name.c | 83 ++++++++++++++++++++++++++++++++++++++-----------------------\n 1 file changed, 52 insertions(+), 31 deletions(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 0c50801..50df5d4 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1052,6 +1052,54 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu\n \treturn ret - used + len;\n }\n \n+static void set_shortened_ref(struct strbuf *buf, const char *ref)\n+{\n+\tchar *s = shorten_unambiguous_ref(ref, 0);\n+\tstrbuf_reset(buf);\n+\tstrbuf_addstr(buf, s);\n+\tfree(s);\n+}\n+\n+static const char *get_upstream_branch(const char *branch_buf, int len)\n+{\n+\tchar *branch = xstrndup(branch_buf, len);\n+\tstruct branch *upstream = branch_get(*branch ? branch : NULL);\n+\n+\t/*\n+\t * Upstream can be NULL only if branch refers to HEAD and HEAD\n+\t * points to something different than a branch.\n+\t */\n+\tif (!upstream)\n+\t\tdie(_(\"HEAD does not point to a branch\"));\n+\tif (!upstream->merge || !upstream->merge[0]->dst) {\n+\t\tif (!ref_exists(upstream->refname))\n+\t\t\tdie(_(\"No such branch: '%s'\"), branch);\n+\t\tif (!upstream->merge) {\n+\t\t\tdie(_(\"No upstream configured for branch '%s'\"),\n+\t\t\t\tupstream->name);\n+\t\t}\n+\t\tdie(\n+\t\t\t_(\"Upstream branch '%s' not stored as a remote-tracking branch\"),\n+\t\t\tupstream->merge[0]->src);\n+\t}\n+\tfree(branch);\n+\n+\treturn upstream->merge[0]->dst;\n+}\n+\n+static int interpret_upstream_mark(const char *name, int namelen,\n+\t\t\t\t   int at, struct strbuf *buf)\n+{\n+\tint len;\n+\n+\tlen = upstream_mark(name + at, namelen - at);\n+\tif (!len)\n+\t\treturn -1;\n+\n+\tset_shortened_ref(buf, get_upstream_branch(name, at));\n+\treturn len + at;\n+}\n+\n /*\n  * This reads short-hand syntax that not only evaluates to a commit\n  * object name, but also can act as if the end user spelled the name\n@@ -1076,9 +1124,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu\n int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n {\n \tchar *cp;\n-\tstruct branch *upstream;\n \tint len = interpret_nth_prior_checkout(name, buf);\n-\tint tmp_len;\n \n \tif (!namelen)\n \t\tnamelen = strlen(name);\n@@ -1100,36 +1146,11 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n \tif (len > 0)\n \t\treturn reinterpret(name, namelen, len, buf);\n \n-\ttmp_len = upstream_mark(cp, namelen - (cp - name));\n-\tif (!tmp_len)\n-\t\treturn -1;\n+\tlen = interpret_upstream_mark(name, namelen, cp - name, buf);\n+\tif (len > 0)\n+\t\treturn len;\n \n-\tlen = cp + tmp_len - name;\n-\tcp = xstrndup(name, cp - name);\n-\tupstream = branch_get(*cp ? cp : NULL);\n-\t/*\n-\t * Upstream can be NULL only if cp refers to HEAD and HEAD\n-\t * points to something different than a branch.\n-\t */\n-\tif (!upstream)\n-\t\tdie(_(\"HEAD does not point to a branch\"));\n-\tif (!upstream->merge || !upstream->merge[0]->dst) {\n-\t\tif (!ref_exists(upstream->refname))\n-\t\t\tdie(_(\"No such branch: '%s'\"), cp);\n-\t\tif (!upstream->merge) {\n-\t\t\tdie(_(\"No upstream configured for branch '%s'\"),\n-\t\t\t\tupstream->name);\n-\t\t}\n-\t\tdie(\n-\t\t\t_(\"Upstream branch '%s' not stored as a remote-tracking branch\"),\n-\t\t\tupstream->merge[0]->src);\n-\t}\n-\tfree(cp);\n-\tcp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);\n-\tstrbuf_reset(buf);\n-\tstrbuf_addstr(buf, cp);\n-\tfree(cp);\n-\treturn len;\n+\treturn -1;\n }\n \n int strbuf_branchname(struct strbuf *sb, const char *name)\n-- \n1.8.5.2.500.g8060133\n"},{"id":"232901","messageId":"20140108093500.GC15720@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108093338.GA15659@sigill.intra.peff.net","subject":"[PATCH 3/5] branch_get: return early on error","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T09:35:00Z","receivedAt":"2014-01-08T09:35:00Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Right now we simply check if \"ret\" is valid before doing\nfurther processing. As we add more processing, this will\nbecome more and more cumbersome. Instead, let's just check\nwhether \"ret\" is invalid and return early with the error.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n remote.c | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/remote.c b/remote.c\nindex a89efab..a773004 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1543,7 +1543,10 @@ struct branch *branch_get(const char *name)\n \t\tret = current_branch;\n \telse\n \t\tret = make_branch(name, 0);\n-\tif (ret && ret->remote_name) {\n+\tif (!ret)\n+\t\treturn NULL;\n+\n+\tif (ret->remote_name) {\n \t\tret->remote = remote_get(ret->remote_name);\n \t\tif (ret->merge_nr) {\n \t\t\tint i;\n-- \n1.8.5.2.500.g8060133\n"},{"id":"232902","messageId":"20140108093531.GD15720@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108093338.GA15659@sigill.intra.peff.net","subject":"[PATCH 4/5] branch_get: provide per-branch pushremote pointers","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T09:35:31Z","receivedAt":"2014-01-08T09:35:31Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"When a caller uses branch_get to retrieve a \"struct branch\",\nthey get the per-branch remote name and a pointer to the\nremote struct. However, they have no way of knowing about\nthe per-branch pushremote from this interface.\n\nLet's expose that information via fields similar to\n\"remote\" and \"remote_name\".\n\nWe have to do a little refactoring around the configuration\nreading here. Instead of pushremote_name being its own\nallocated string, it instead becomes a pointer to one of:\n\n  1. The pushremote_name of the current branch, if\n     configured.\n\n  2. The globally configured remote.pushdefault, which we\n     store separately as pushremote_config_default.\n\nWe can then set the branch's \"pushremote\" field by doing the\nnormal sequence of config fallback.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n remote.c | 23 +++++++++++++++++++----\n remote.h |  2 ++\n 2 files changed, 21 insertions(+), 4 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex a773004..53e40e0 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -50,6 +50,7 @@ static int branches_nr;\n static struct branch *current_branch;\n static const char *default_remote_name;\n static const char *pushremote_name;\n+static const char *pushremote_config_default;\n static int explicit_default_remote_name;\n \n static struct rewrites rewrites;\n@@ -351,9 +352,10 @@ static int handle_config(const char *key, const char *value, void *cb)\n \t\t\t\texplicit_default_remote_name = 1;\n \t\t\t}\n \t\t} else if (!strcmp(subkey, \".pushremote\")) {\n+\t\t\tif (git_config_string(&branch->pushremote_name, key, value))\n+\t\t\t\treturn -1;\n \t\t\tif (branch == current_branch)\n-\t\t\t\tif (git_config_string(&pushremote_name, key, value))\n-\t\t\t\t\treturn -1;\n+\t\t\t\tpushremote_name = branch->pushremote_name;\n \t\t} else if (!strcmp(subkey, \".merge\")) {\n \t\t\tif (!value)\n \t\t\t\treturn config_error_nonbool(key);\n@@ -385,8 +387,11 @@ static int handle_config(const char *key, const char *value, void *cb)\n \tname = key + 7;\n \n \t/* Handle remote.* variables */\n-\tif (!strcmp(name, \"pushdefault\"))\n-\t\treturn git_config_string(&pushremote_name, key, value);\n+\tif (!strcmp(name, \"pushdefault\")) {\n+\t\tif (git_config_string(&pushremote_config_default, key, value) < 0)\n+\t\t\treturn -1;\n+\t\tpushremote_name = pushremote_config_default;\n+\t}\n \n \t/* Handle remote.<name>.* variables */\n \tif (*name == '/') {\n@@ -1560,6 +1565,16 @@ struct branch *branch_get(const char *name)\n \t\t\t}\n \t\t}\n \t}\n+\n+\tif (ret->pushremote_name)\n+\t\tret->pushremote = remote_get(ret->pushremote_name);\n+\telse if (pushremote_config_default)\n+\t\tret->pushremote = remote_get(pushremote_config_default);\n+\telse if (ret->remote_name)\n+\t\tret->pushremote = remote_get(ret->remote_name);\n+\telse\n+\t\tret->pushremote = remote_get(\"origin\");\n+\n \treturn ret;\n }\n \ndiff --git a/remote.h b/remote.h\nindex 00c6a76..e5beb30 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -200,6 +200,8 @@ struct branch {\n \n \tconst char *remote_name;\n \tstruct remote *remote;\n+\tconst char *pushremote_name;\n+\tstruct remote *pushremote;\n \n \tconst char **merge_name;\n \tstruct refspec **merge;\n-- \n1.8.5.2.500.g8060133\n"},{"id":"232903","messageId":"20140108093716.GE15720@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108093338.GA15659@sigill.intra.peff.net","subject":"[PATCH 5/5] implement @{publish} shorthand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T09:37:16Z","receivedAt":"2014-01-08T09:37:16Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"In a triangular workflow, you may have a distinct\n@{upstream} that you pull changes from, but publish by\ndefault (if you typed \"git push\") to a different remote (or\na different branch on the remote). It may sometimes be\nuseful to be able to quickly refer to that publishing point\n(e.g., to see which changes you have that have not yet been\npublished).\n\nThis patch introduces the <branch>@{publish} shorthand (or\n\"@{pu}\" to be even shorter). It refers to the tracking\nbranch of the remote branch to which you would push if you\nwere to push the named branch. That's a mouthful to explain,\nso here's an example:\n\n  $ git checkout -b foo origin/master\n  $ git config remote.pushdefault github\n  $ git push\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThe implementation feels weird, like the \"where do we push to\" code\nshould be factored out from somewhere else. I think what we're doing\nhere is not _wrong_, but I don't like repeating what \"git push\" is doing\nelsewhere. And I just punt on \"simple\" as a result. :)\n\n sha1_name.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 75 insertions(+), 1 deletion(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 50df5d4..59ffa93 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -435,6 +435,12 @@ static inline int upstream_mark(const char *string, int len)\n \treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n }\n \n+static inline int publish_mark(const char *string, int len)\n+{\n+\tconst char *suffix[] = { \"@{publish}\" };\n+\treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n+}\n+\n static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);\n static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);\n \n@@ -481,7 +487,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \t\t\t\t\tnth_prior = 1;\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n-\t\t\t\tif (!upstream_mark(str + at, len - at)) {\n+\t\t\t\tif (!upstream_mark(str + at, len - at) &&\n+\t\t\t\t    !publish_mark(str + at, len - at)) {\n \t\t\t\t\treflog_len = (len-1) - (at+2);\n \t\t\t\t\tlen = at;\n \t\t\t\t}\n@@ -1100,6 +1107,69 @@ static int interpret_upstream_mark(const char *name, int namelen,\n \treturn len + at;\n }\n \n+static const char *get_publish_branch(const char *name_buf, int len)\n+{\n+\tchar *name = xstrndup(name_buf, len);\n+\tstruct branch *b = branch_get(*name ? name : NULL);\n+\tstruct remote *remote = b->pushremote;\n+\tconst char *dst;\n+\tconst char *track;\n+\n+\tfree(name);\n+\n+\tif (!remote)\n+\t\tdie(_(\"branch '%s' has no remote for pushing\"), b->name);\n+\n+\t/* Figure out what we would call it on the remote side... */\n+\tif (remote->push_refspec_nr)\n+\t\tdst = apply_refspecs(remote->push, remote->push_refspec_nr,\n+\t\t\t\t     b->refname);\n+\telse\n+\t\tdst = b->refname;\n+\tif (!dst)\n+\t\tdie(_(\"unable to figure out how '%s' would be pushed\"),\n+\t\t    b->name);\n+\n+\t/* ...and then figure out what we would call that remote here */\n+\ttrack = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, dst);\n+\tif (!track)\n+\t\tdie(_(\"%s@{publish} has no tracking branch for '%s'\"),\n+\t\t    b->name, dst);\n+\n+\treturn track;\n+}\n+\n+static int interpret_publish_mark(const char *name, int namelen,\n+\t\t\t\t  int at, struct strbuf *buf)\n+{\n+\tint len;\n+\n+\tlen = publish_mark(name + at, namelen - at);\n+\tif (!len)\n+\t\treturn -1;\n+\n+\tswitch (push_default) {\n+\tcase PUSH_DEFAULT_NOTHING:\n+\t\tdie(_(\"cannot use @{publish} with push.default of 'nothing'\"));\n+\n+\tcase PUSH_DEFAULT_UNSPECIFIED:\n+\tcase PUSH_DEFAULT_MATCHING:\n+\tcase PUSH_DEFAULT_CURRENT:\n+\t\tset_shortened_ref(buf, get_publish_branch(name, at));\n+\t\tbreak;\n+\n+\tcase PUSH_DEFAULT_UPSTREAM:\n+\t\tset_shortened_ref(buf, get_upstream_branch(name, at));\n+\t\tbreak;\n+\n+\tcase PUSH_DEFAULT_SIMPLE:\n+\t\t/* ??? */\n+\t\tdie(\"@{publish} with simple unimplemented\");\n+\t}\n+\n+\treturn at + len;\n+}\n+\n /*\n  * This reads short-hand syntax that not only evaluates to a commit\n  * object name, but also can act as if the end user spelled the name\n@@ -1150,6 +1220,10 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n \tif (len > 0)\n \t\treturn len;\n \n+\tlen = interpret_publish_mark(name, namelen, cp - name, buf);\n+\tif (len > 0)\n+\t\treturn len;\n+\n \treturn -1;\n }\n \n-- \n1.8.5.2.500.g8060133\n"},{"id":"232905","messageId":"20140108102707.GA23145@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108093531.GD15720@sigill.intra.peff.net","subject":"Re: [PATCH 4/5] branch_get: provide per-branch pushremote pointers","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T10:27:07Z","receivedAt":"2014-01-08T10:27:07Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 08, 2014 at 04:35:31AM -0500, Jeff King wrote:\n\n> @@ -385,8 +387,11 @@ static int handle_config(const char *key, const char *value, void *cb)\n>  \tname = key + 7;\n>  \n>  \t/* Handle remote.* variables */\n> -\tif (!strcmp(name, \"pushdefault\"))\n> -\t\treturn git_config_string(&pushremote_name, key, value);\n> +\tif (!strcmp(name, \"pushdefault\")) {\n> +\t\tif (git_config_string(&pushremote_config_default, key, value) < 0)\n> +\t\t\treturn -1;\n> +\t\tpushremote_name = pushremote_config_default;\n> +\t}\n\nThis needs \"return 0\" squashed in at the end of the conditional, of\ncourse, to match the old behavior.\n\nThis patch passes the test suite by itself (with or without that fixup).\nBut oddly, it seems to fail t5531 when merged with 'next'. I can't\nfigure out why, though. It shouldn't affect any code that doesn't look\nat branch->pushremote.\n\n-Peff\n"},{"id":"232906","messageId":"20140108104756.GA32078@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108102707.GA23145@sigill.intra.peff.net","subject":"[PATCH] t5531: further \"matching\" fixups","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T10:47:56Z","receivedAt":"2014-01-08T10:47:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Commit 43eb920 switched one of the sub-repository in this\ntest to matching to prepare for a world where the default\nbecomes \"simple\". However, the main repository needs a\nsimilar change.\n\nWe did not notice any test failure when merged with b2ed944\n(push: switch default from \"matching\" to \"simple\", 2013-01-04)\nbecause t5531.6 is trying to provoke a failure of \"git push\"\ndue to a submodule check. When combined with b2ed944 the\npush still fails, but for the wrong reason (because our\nupstream setup does not exist, not because of the submodule).\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nOn Wed, Jan 08, 2014 at 05:27:07AM -0500, Jeff King wrote:\n\n> This patch passes the test suite by itself (with or without that fixup).\n> But oddly, it seems to fail t5531 when merged with 'next'. I can't\n> figure out why, though. It shouldn't affect any code that doesn't look\n> at branch->pushremote.\n\nI still don't understand the full reason for this interaction, but the\nfailing test is actually somewhat broken in 'next' already. This patch\nfixes it, and should be done regardless of the other series.\n\n t/t5531-deep-submodule-push.sh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh\nindex 8c16e04..445bb5f 100755\n--- a/t/t5531-deep-submodule-push.sh\n+++ b/t/t5531-deep-submodule-push.sh\n@@ -12,6 +12,7 @@ test_expect_success setup '\n \t(\n \t\tcd work &&\n \t\tgit init &&\n+\t\tgit config push.default matching &&\n \t\tmkdir -p gar/bage &&\n \t\t(\n \t\t\tcd gar/bage &&\n-- \n1.8.5.2.500.g8060133\n"},{"id":"232907","messageId":"20140108110919.GA3674@sigill.intra.peff.net","threadId":"35623","inReplyTo":"20140108102707.GA23145@sigill.intra.peff.net","subject":"Re: [PATCH 4/5] branch_get: provide per-branch pushremote pointers","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-08T11:09:19Z","receivedAt":"2014-01-08T11:09:19Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 08, 2014 at 05:27:07AM -0500, Jeff King wrote:\n\n> This patch passes the test suite by itself (with or without that fixup).\n> But oddly, it seems to fail t5531 when merged with 'next'. I can't\n> figure out why, though. It shouldn't affect any code that doesn't look\n> at branch->pushremote.\n\nOK, I figured it out. My patch calls:\n\n  remote_get(\"origin\")\n\nwhich creates an origin remote, even if one does not exist (it assumes\nit to be a URL \"origin\"). Later, when we want to decide if the push is\ntriangular or not, we ask for:\n\n  remote_get(NULL);\n\nwhich will internally look for a remote called \"origin\". Before my patch\nthere was not such a remote, and so the push could not be triangular.\nAfter my patch, it finds the bogus remote and says \"this thing exists,\nand is not what we are pushing to; therefore the push is triangular\".\n\nThe solution is that I should not be passing the term \"origin\" to\nremote_get, but rather passing NULL and relying on it to figure out the\ndefault remote correctly. I.e.:\n\ndiff --git a/remote.c b/remote.c\nindex 8724388..d214fa2 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1574,7 +1574,7 @@ struct branch *branch_get(const char *name)\n \telse if (ret->remote_name)\n \t\tret->pushremote = remote_get(ret->remote_name);\n \telse\n-\t\tret->pushremote = remote_get(\"origin\");\n+\t\tret->pushremote = remote_get(NULL);\n \n \treturn ret;\n }\n\n-Peff\n"},{"id":"232911","messageId":"CALkWK0=YQVSnip27-MbB0ASZ_9AMF-ZxuPzP73wWEhxwdZYqJg@mail.gmail.com","threadId":"35623","inReplyTo":"20140108093450.GB15720@sigill.intra.peff.net","subject":"Re: [PATCH 2/5] interpret_branch_name: factor out upstream handling","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-08T12:37:58Z","receivedAt":"2014-01-08T12:37:58Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n>  sha1_name.c | 83 ++++++++++++++++++++++++++++++++++++++-----------------------\n>  1 file changed, 52 insertions(+), 31 deletions(-)\n\nThanks. I applied this to my series as-it-is.\n"},{"id":"232912","messageId":"CALkWK0=akW-CwQC7hz4Jae5Y7Vtk282dtq_HsnQ=_SHU2iJhyQ@mail.gmail.com","threadId":"35623","inReplyTo":"20140108093338.GA15659@sigill.intra.peff.net","subject":"Re: [RFC/PATCH 0/5] <branch>@{publish} shorthand","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-08T12:40:09Z","receivedAt":"2014-01-08T12:40:09Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n> There's a fair bit of refactoring involved. I took a stab at it and came\n> up with the series below. No docs or tests, and some of the refactoring\n> in remote.c feels a little weird. I can't help but feel more of the\n> logic from \"git push\" should be shared here.\n>\n> But it at least works with my rudimentary examples. I'm hoping it will\n> make a good starting point for you to build on. Otherwise, I may get to\n> it eventually, but it's not a high priority for me right now.\n\nThanks; I'll see what I can do about getting it to share code with 'git push'.\n"},{"id":"232929","messageId":"xmqqeh4iavn2.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"20140108093716.GE15720@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-08T23:42:09Z","receivedAt":"2014-01-08T23:42:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> In a triangular workflow, you may have a distinct\n> @{upstream} that you pull changes from, but publish by\n> default (if you typed \"git push\") to a different remote (or\n> a different branch on the remote). It may sometimes be\n> useful to be able to quickly refer to that publishing point\n> (e.g., to see which changes you have that have not yet been\n> published).\n>\n> This patch introduces the <branch>@{publish} shorthand (or\n> \"@{pu}\" to be even shorter). It refers to the tracking\n\nIf @{u} can already be used for upstream, why not allow @{p} but\nrequire two letters @{pu}?  Just being curious---I am not advocating\nstrongly for a shorter short-hand.\n\nOr is @{p} already taken by something and my memory is not\nfunctioning well?\n\n> branch of the remote branch to which you would push if you\n> were to push the named branch. That's a mouthful to explain,\n> so here's an example:\n>\n>   $ git checkout -b foo origin/master\n>   $ git config remote.pushdefault github\n>   $ git push\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n> The implementation feels weird, like the \"where do we push to\" code\n> should be factored out from somewhere else. I think what we're doing\n> here is not _wrong_, but I don't like repeating what \"git push\" is doing\n> elsewhere. And I just punt on \"simple\" as a result. :)\n>\n>  sha1_name.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n>  1 file changed, 75 insertions(+), 1 deletion(-)\n>\n> diff --git a/sha1_name.c b/sha1_name.c\n> index 50df5d4..59ffa93 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -435,6 +435,12 @@ static inline int upstream_mark(const char *string, int len)\n>  \treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n>  }\n>  \n> +static inline int publish_mark(const char *string, int len)\n> +{\n> +\tconst char *suffix[] = { \"@{publish}\" };\n> +\treturn at_mark(string, len, suffix, ARRAY_SIZE(suffix));\n> +}\n> +\n>  static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);\n>  static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);\n>  \n> @@ -481,7 +487,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n>  \t\t\t\t\tnth_prior = 1;\n>  \t\t\t\t\tcontinue;\n>  \t\t\t\t}\n> -\t\t\t\tif (!upstream_mark(str + at, len - at)) {\n> +\t\t\t\tif (!upstream_mark(str + at, len - at) &&\n> +\t\t\t\t    !publish_mark(str + at, len - at)) {\n>  \t\t\t\t\treflog_len = (len-1) - (at+2);\n>  \t\t\t\t\tlen = at;\n>  \t\t\t\t}\n> @@ -1100,6 +1107,69 @@ static int interpret_upstream_mark(const char *name, int namelen,\n>  \treturn len + at;\n>  }\n>  \n> +static const char *get_publish_branch(const char *name_buf, int len)\n> +{\n> +\tchar *name = xstrndup(name_buf, len);\n> +\tstruct branch *b = branch_get(*name ? name : NULL);\n> +\tstruct remote *remote = b->pushremote;\n> +\tconst char *dst;\n> +\tconst char *track;\n> +\n> +\tfree(name);\n> +\n> +\tif (!remote)\n> +\t\tdie(_(\"branch '%s' has no remote for pushing\"), b->name);\n> +\n> +\t/* Figure out what we would call it on the remote side... */\n> +\tif (remote->push_refspec_nr)\n> +\t\tdst = apply_refspecs(remote->push, remote->push_refspec_nr,\n> +\t\t\t\t     b->refname);\n> +\telse\n> +\t\tdst = b->refname;\n> +\tif (!dst)\n> +\t\tdie(_(\"unable to figure out how '%s' would be pushed\"),\n> +\t\t    b->name);\n> +\n> +\t/* ...and then figure out what we would call that remote here */\n> +\ttrack = apply_refspecs(remote->fetch, remote->fetch_refspec_nr, dst);\n> +\tif (!track)\n> +\t\tdie(_(\"%s@{publish} has no tracking branch for '%s'\"),\n> +\t\t    b->name, dst);\n> +\n> +\treturn track;\n> +}\n> +\n> +static int interpret_publish_mark(const char *name, int namelen,\n> +\t\t\t\t  int at, struct strbuf *buf)\n> +{\n> +\tint len;\n> +\n> +\tlen = publish_mark(name + at, namelen - at);\n> +\tif (!len)\n> +\t\treturn -1;\n> +\n> +\tswitch (push_default) {\n> +\tcase PUSH_DEFAULT_NOTHING:\n> +\t\tdie(_(\"cannot use @{publish} with push.default of 'nothing'\"));\n> +\n> +\tcase PUSH_DEFAULT_UNSPECIFIED:\n> +\tcase PUSH_DEFAULT_MATCHING:\n> +\tcase PUSH_DEFAULT_CURRENT:\n> +\t\tset_shortened_ref(buf, get_publish_branch(name, at));\n> +\t\tbreak;\n> +\n> +\tcase PUSH_DEFAULT_UPSTREAM:\n> +\t\tset_shortened_ref(buf, get_upstream_branch(name, at));\n> +\t\tbreak;\n> +\n> +\tcase PUSH_DEFAULT_SIMPLE:\n> +\t\t/* ??? */\n> +\t\tdie(\"@{publish} with simple unimplemented\");\n> +\t}\n> +\n> +\treturn at + len;\n> +}\n> +\n>  /*\n>   * This reads short-hand syntax that not only evaluates to a commit\n>   * object name, but also can act as if the end user spelled the name\n> @@ -1150,6 +1220,10 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n>  \tif (len > 0)\n>  \t\treturn len;\n>  \n> +\tlen = interpret_publish_mark(name, namelen, cp - name, buf);\n> +\tif (len > 0)\n> +\t\treturn len;\n> +\n>  \treturn -1;\n>  }\n"},{"id":"232948","messageId":"02F63E901C46405BAAEEFBC48870A7C2@PhilipOakley","threadId":"35623","inReplyTo":"20140108093716.GE15720@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":null,"receivedAt":"2014-01-09T08:31:13Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"Jeff King\" <peff@peff.net>\nSent: Wednesday, January 08, 2014 9:37 AM\n> In a triangular workflow, you may have a distinct\n> @{upstream} that you pull changes from, but publish by\n> default (if you typed \"git push\") to a different remote (or\n> a different branch on the remote).\n\nOne of the broader issues is the lack of _documenation_ about what the \n'normal' naming convention is for the uspstream remote. Especially the \nimplicit convention used within our documentation (and workflow).\n\nThis is especially true for github users who will normally fork a repo \nof interest and then clone it from their own copy/fork. This means that \nthe 'origin' remote is _not_ the upstream. See \nhttps://help.github.com/articles/fork-a-repo In my case 'origin' is my \npublish repo (as suggested by Github) while 'junio' is the upstream (as \ndo some others). There are similar results from the likes of \nStackoverflow.\n\nMuch of the earlier discussion did appear to be as much a confusion over \nterminology as that of coding a suitable solution ro Ram's original \nforked-from issue.\n\nI know it's been an issue I've had for some while \nhttp://thread.gmane.org/gmane.comp.version-control.git/194175/focus=195385\n\nPhilip\n"},{"id":"232957","messageId":"20140109182024.GA30970@sigill.intra.peff.net","threadId":"35623","inReplyTo":"xmqqeh4iavn2.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-09T18:20:24Z","receivedAt":"2014-01-09T18:20:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jan 08, 2014 at 03:42:09PM -0800, Junio C Hamano wrote:\n\n> > This patch introduces the <branch>@{publish} shorthand (or\n> > \"@{pu}\" to be even shorter). It refers to the tracking\n> \n> If @{u} can already be used for upstream, why not allow @{p} but\n> require two letters @{pu}?  Just being curious---I am not advocating\n> strongly for a shorter short-hand.\n> \n> Or is @{p} already taken by something and my memory is not\n> functioning well?\n\nIt is my brain that was not functioning well. I somehow thought \"well,\n@{u} is already taken, so we must use \"@{pu}\". Which of course makes no\nsense, unless you are middle-endian. :)\n\nWe may want to be cautious about giving up a short-and-sweet\nsingle-letter, though, until the feature has proved itself. We could\nalso teach upstream_mark and friends to match unambiguous prefixes (so\n\"@{u}, \"@{up}\", \"@{upst}\", etc). That means \"@{p}\" would work\nimmediately, but scripts should use \"@{publish}\" for future-proofing.\n\n-Peff\n"},{"id":"232967","messageId":"xmqqob3kalwm.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"20140109182024.GA30970@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-09T21:24:41Z","receivedAt":"2014-01-09T21:24:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n>> Or is @{p} already taken by something and my memory is not\n>> functioning well?\n>\n> It is my brain that was not functioning well. I somehow thought \"well,\n> @{u} is already taken, so we must use \"@{pu}\". Which of course makes no\n> sense, unless you are middle-endian. :)\n>\n> We may want to be cautious about giving up a short-and-sweet\n> single-letter, though, until the feature has proved itself. We could\n> also teach upstream_mark and friends to match unambiguous prefixes (so\n> \"@{u}, \"@{up}\", \"@{upst}\", etc). That means \"@{p}\" would work\n> immediately, but scripts should use \"@{publish}\" for future-proofing.\n\nI recall we wanted to start only with \"@{upstream}\" without \"@{u}\";\njustification being \"if the concept is solid and useful enough, the\nlatter will come later as a natural user-desire\", during the\ndiscussion that ended up introducing them.\n\nI am OK with the \"unambigous prefix string\".\n\nThanks for sanity-checking.\n"},{"id":"232972","messageId":"20140109220351.GD32069@sigill.intra.peff.net","threadId":"35623","inReplyTo":"02F63E901C46405BAAEEFBC48870A7C2@PhilipOakley","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-09T22:03:51Z","receivedAt":"2014-01-09T22:03:51Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Jan 09, 2014 at 08:39:44AM -0000, Philip Oakley wrote:\n\n> From: \"Jeff King\" <peff@peff.net>\n> Sent: Wednesday, January 08, 2014 9:37 AM\n> >In a triangular workflow, you may have a distinct\n> >@{upstream} that you pull changes from, but publish by\n> >default (if you typed \"git push\") to a different remote (or\n> >a different branch on the remote).\n> \n> One of the broader issues is the lack of _documenation_ about what\n> the 'normal' naming convention is for the uspstream remote.\n> Especially the implicit convention used within our documentation (and\n> workflow).\n> \n> This is especially true for github users who will normally fork a\n> repo of interest and then clone it from their own copy/fork. This\n> means that the 'origin' remote is _not_ the upstream. See\n> https://help.github.com/articles/fork-a-repo In my case 'origin' is\n> my publish repo (as suggested by Github) while 'junio' is the\n> upstream (as do some others). There are similar results from the\n> likes of Stackoverflow.\n\nSure, and I have done the same thing (though I tend to clone from the\nother person as \"origin\", and only fork my own repo when I am ready to\npush). But it shouldn't matter, should it? The whole point of the\nupstream config is that \"git checkout -b topic junio/master\" does the\nright thing, without caring about your naming convention.\n\nSo I'm not sure what you think should be said (or where). Telling me in\npatch form is preferred. :)\n\n-Peff\n"},{"id":"232974","messageId":"xmqqbnzkaj5i.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"02F63E901C46405BAAEEFBC48870A7C2@PhilipOakley","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-09T22:24:09Z","receivedAt":"2014-01-09T22:24:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Philip Oakley\" <philipoakley@iee.org> writes:\n\n> From: \"Jeff King\" <peff@peff.net>\n> Sent: Wednesday, January 08, 2014 9:37 AM\n>> In a triangular workflow, you may have a distinct\n>> @{upstream} that you pull changes from, but publish by\n>> default (if you typed \"git push\") to a different remote (or\n>> a different branch on the remote).\n>\n> One of the broader issues is the lack of _documenation_ about what the\n> normal' naming convention is for the uspstream remote. Especially the\n> implicit convention used within our documentation (and workflow).\n\nSure, let's start trying to come up with what the eventual\ndocumentation patch may want to say.\n\n * The \"upstream\" is the place the updates by the project-as-a-whole\n   (including others' work but also your previous work) come from.\n   It is what you use \"git pull [--rebase]\" to integrate the work on\n   your current branch with in order to keep it in sync with the\n   outside world.  Such a repository (often called \"origin\", and\n   \"git clone\" sets it up for you) may be called \"upstream\n   repository\".\n\n   Each of your branch would often have a single branch in that\n   repository (e.g. \"master\", which you locally use the\n   \"origin/master\" remote-tracking branch to keep track of its most\n   recently observed state).  In the simplest case, you clone from\n   your \"origin\", you get your own \"master\" branch, which is set to\n   integrate with the \"master\" branch at the \"origin\".  Their\n   \"master\" (i.e. what you view as \"origin/master\") would be the\n   \"upstream branch\" for your \"master\" branch.\n\n   For a branch B, B@{upstream} names the remote-tracking branch\n   used for the upstream branch of B.  For example, to fork a new\n   branch 'foo' that has the same upstream branch as your branch\n   'master' does, \"git checkout -t -b foo master@{upstream}\" can be\n   used.\n\n * If you and others are using the same repository to advance the\n   project, the repository you cloned from, i.e. your \"upstream\n   repository\", is the same repository you push your changes back\n   to.  There is no other repository you have to worry about.\n\n   In such a \"centralized\" setting, it is likely that you may want\n   to update one of three possible branches at the upstream\n   repository when you push your changes back, if your local branch\n   is named differently from its upstream branch.  Either:\n\n   (1) You started working on a topic (e.g. your \"fix-bug-2431\"\n       branch) based on an integration branch (e.g. \"master\" at the\n       upstream, i.e. \"origin/master\" to you), and you want to\n       publish it so that others can take a look at it and help you\n       polish it while it is still not suitable for the integration\n       branch.  As long as you gave a name to that topic branch that\n       is descriptive and good enough for public consumption, you\n       would want it to go to the same name (e.g. you would want to\n       push to \"fix-bug-2431\" branch at the upstream repository from\n       your \"fix-bug-2431\" branch); or\n\n   (2) You are working on your copy (e.g. your \"master\" branch) of\n       an integration branch (e.g. \"origin/master\" to you), and you\n       want to update the \"master\" branch at the upstream\n       repository.\n\n   (3) There is another possibilty, in which you are working on a\n       topic forked from an integration branch (as in (1)), and are\n       done with the topic and want to push the result out directly\n       to the integration branch.  Your \"fix-bug-2431\" branch may\n       have started from \"origin/master\" and \"git pull [--rebase]\"\n       on the branch would integrate with \"master\" branch at the\n       upstream repository, and your \"git push\" on the\n       \"fix-bug-2431\" branch will update that \"master\" branch at the\n       upstream repository, which makes it look symmetric.\n\n    The default in Git 2.0 will allow you to do (2) without any\n    further set-up, and you can start living in the future by\n    setting push.default to \"simple\".  Your current branch, when you\n    run \"git push\", and its upstream branch must share the same\n    name.\n\n    If you want to do (1), you would want to set push.default to\n    \"current\".  Your current branch, when you run \"git push\" may not\n    have an explicit upstream branch (hence \"git pull\" without any\n    other argument may fail), but the work on your branch will be\n    pushed to the branch of the same name at the upstream\n    repository.\n\n    For (3), you would set push.default to \"upstream\".  Your current\n    branch, when you run \"git push\", must have an explicit upstream\n    branch specified and you must be pushing to the upstream\n    repository for this to work for obvious reasons.\n\n * If you originally clone from somewhere you cannot (or do not want\n   to even if you could) push to, you would want your \"git push\" to\n   go to a repository that is different from your \"upstream\".  In\n   such a \"triangular\" setting, the result of your work is published\n   to your own repository (we'd call it \"publish\"), and others\n   interested in your work would pull from there to integrate it to\n   their work.  Among these other people there may be somebody who\n   integrates work by all relevant people to the project mainline\n   and updates the repository that you and other project participant\n   all call their \"upstream\", and that is how you see your own work\n   back in your \"upstream\".\n\n   Set remote.pushdefault to name the repository that is your\n   \"publish\" repository if you are using such a triangular workflow\n   (you could use branch.*.pushremote to publish to different\n   repositories per branch).\n\n   Your local branch in such a triangular setting will have its\n   \"upstream\" (the repository your \"git pull\" goes to and one of its\n   branches it integrates with) and its \"publish\" (the repository\n   and one of its branches your \"git push\" updates).  Like the way\n   B@{upstream} can be used to refer to the former for your local\n   branch B, B@{publish} can be used to refer to the latter.\n\n   In such a \"triangular\" setting, it is likely that you may want to\n   update the branch of the same name in your \"publish\" repository.\n   If you have been working on your \"fix-bug-2431\" branch, you would\n   want the result to go to \"fix-bug-2431\" branch there.\n\n   The default in Git 2.0, when a triangular workflow is used by\n   setting remote.pushdefault (or branch.*.pushremote), will push\n   the current branch to the branch of the same name, so you do not\n   have to do anything further.  You can start living in the future\n   by setting push.default to \"simple\".\n\n   The \"upstream\" setting of push.default would not make any sense\n   in such a triangular workflow, so your \"git push\" will error out\n   when you push to a repository that is not your \"upstream\" while\n   the push.default is set to \"upstream\".\n\n * At the conceptual level, anybody who treats the work you publish\n   as his or her \"upstream\" is your downstream, but because you do\n   not control and keep track of who clones and pulls from you,\n   there is no such notation as @{downstream}.\n\nIt is unfortunate that GitHub worked aroud the lack of \"publish\"\nconcept not by adding it to Git, but by introducing \"fork\" at the\nserver side, which ends up twisting the concept of \"upstream\" that\nis sets up by \"git clone\".\n"},{"id":"233015","messageId":"xmqqzjn376n0.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"20140108104756.GA32078@sigill.intra.peff.net","subject":"Re: [PATCH] t5531: further \"matching\" fixups","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-10T23:34:59Z","receivedAt":"2014-01-10T23:34:59Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> ... but the\n> failing test is actually somewhat broken in 'next' already.\n\nHmph, in what way?  I haven't seen t5531 breakage on 'next', with or\nwithout your series...\n\n> fixes it, and should be done regardless of the other series.\n>\n>  t/t5531-deep-submodule-push.sh | 1 +\n>  1 file changed, 1 insertion(+)\n>\n> diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh\n> index 8c16e04..445bb5f 100755\n> --- a/t/t5531-deep-submodule-push.sh\n> +++ b/t/t5531-deep-submodule-push.sh\n> @@ -12,6 +12,7 @@ test_expect_success setup '\n>  \t(\n>  \t\tcd work &&\n>  \t\tgit init &&\n> +\t\tgit config push.default matching &&\n>  \t\tmkdir -p gar/bage &&\n>  \t\t(\n>  \t\t\tcd gar/bage &&\n"},{"id":"233020","messageId":"20140111042246.GA19556@sigill.intra.peff.net","threadId":"35623","inReplyTo":"xmqqzjn376n0.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH] t5531: further \"matching\" fixups","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-11T04:22:47Z","receivedAt":"2014-01-11T04:22:47Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 10, 2014 at 03:34:59PM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > ... but the\n> > failing test is actually somewhat broken in 'next' already.\n> \n> Hmph, in what way?  I haven't seen t5531 breakage on 'next', with or\n> without your series...\n\nThe test still passes, but it is not testing the right thing anymore.\n\nOn 'next', run t5531. Test 6 is \"push fails when commit on\nmultiple branches if one branch has no remote\" and ends with:\n\n  test_must_fail git push --recurse-submodules=check ../pub.git\n\nBut the output ends with:\n\n  warning: push.default is unset; its implicit value has changed in\n  Git 2.0 from 'matching' to 'simple'. To squelch this message\n  [...]\n\n  fatal: The current branch branch2 has no upstream branch.\n  To push the current branch and set the remote as upstream, use\n\n      git push --set-upstream ../pub.git branch2\n\nWhen not merged with b2ed944 (push: switch default from \"matching\" to\n\"simple\"), or with my patch to set push.default=matching explicitly, the\noutput is:\n\n  The following submodule paths contain changes that can\n  not be found on any remote:\n    gar/bage\n\n  Please try\n\n          git push --recurse-submodules=on-demand\n\n  or cd to the path and use\n\n          git push\n\n  to push them to a remote.\n\n  fatal: Aborting.\n\nwhich is what the test is actually trying to check. So the push fails,\nas we expect, but not for the right reason.\n\nMy other series for @{publish} had a bug that caused the push to\nsucceed. So that series was buggy (and I posted the fix already), but we\nonly noticed it because this test was not working (it should not care\nabout upstream/triangular config at all, but it accidentally did).\n\nDoes that clarify the situation?\n\n-Peff\n"},{"id":"233664","messageId":"xmqqob32s08p.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"20140108093716.GE15720@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-24T00:16:06Z","receivedAt":"2014-01-24T00:16:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> In a triangular workflow, you may have a distinct\n> @{upstream} that you pull changes from, but publish by\n> default (if you typed \"git push\") to a different remote (or\n> a different branch on the remote). It may sometimes be\n> useful to be able to quickly refer to that publishing point\n> (e.g., to see which changes you have that have not yet been\n> published).\n>\n> This patch introduces the <branch>@{publish} shorthand (or\n> \"@{pu}\" to be even shorter). It refers to the tracking\n> branch of the remote branch to which you would push if you\n> were to push the named branch. That's a mouthful to explain,\n> so here's an example:\n>\n>   $ git checkout -b foo origin/master\n>   $ git config remote.pushdefault github\n>   $ git push\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> ---\n\nAs there is no @{pu} in publish_mark() as far as I can see, and also\nI found it is a bit unclear what the example in the last paragraph\nwants to illustrate, I'll reword the above as the following before\nmerging it to 'next'.\n\n    This patch introduces the <branch>@{publish} shorthand that\n    refers to the tracking branch of the remote branch to which\n    you would push if you were to push the named branch.\n    \n    That's a mouthful to explain, so here's an example:\n    \n      $ git checkout -b foo origin/master\n      $ git config remote.pushdefault github\n      $ git push\n    \n    With this, foo@{upstream} and foo@{publish} would be origin/master\n    and github/foo, respectively (assuming that \"git fetch github\" is\n    configured to use refs/remotes/github/* remote-tracking branches).\n\n> The implementation feels weird, like the \"where do we push to\" code\n> should be factored out from somewhere else. I think what we're doing\n> here is not _wrong_, but I don't like repeating what \"git push\" is doing\n> elsewhere. And I just punt on \"simple\" as a result. :)\n\nI think we can polish that in-tree.\n\nThanks.\n"},{"id":"233726","messageId":"20140124213521.GA26602@sigill.intra.peff.net","threadId":"35623","inReplyTo":"xmqqob32s08p.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-01-24T21:35:21Z","receivedAt":"2014-01-24T21:35:21Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Jan 23, 2014 at 04:16:06PM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > In a triangular workflow, you may have a distinct\n> > @{upstream} that you pull changes from, but publish by\n> > default (if you typed \"git push\") to a different remote (or\n> > a different branch on the remote). It may sometimes be\n> > useful to be able to quickly refer to that publishing point\n> > (e.g., to see which changes you have that have not yet been\n> > published).\n> >\n> > This patch introduces the <branch>@{publish} shorthand (or\n> > \"@{pu}\" to be even shorter). It refers to the tracking\n> > branch of the remote branch to which you would push if you\n> > were to push the named branch. That's a mouthful to explain,\n> > so here's an example:\n> >\n> >   $ git checkout -b foo origin/master\n> >   $ git config remote.pushdefault github\n> >   $ git push\n> >\n> > Signed-off-by: Jeff King <peff@peff.net>\n> > ---\n> \n> As there is no @{pu} in publish_mark() as far as I can see, and also\n> I found it is a bit unclear what the example in the last paragraph\n> wants to illustrate, I'll reword the above as the following before\n> merging it to 'next'.\n\nYeah, I think the @{pu} was just a silly omission from the code, though\nI agree after our discussion that we should just stick with \"@{publish}\"\nfor now.\n\nI am not sure why I said \"git push\" at the end. I would have thought\nthat:\n\n  $ git rev-parse --symbolic-full-name @{publish}\n  refs/remotes/github/foo\n\nwould have been the right command to demonstrate. The text you suggested\nis fine, though I think you can simply drop the \"git push\", as it does\nnot add anything.\n\nAs far as merging it to 'next', I had not really intended it to go that\nfar. :) It was more for Ram to use as a base. I find some of the\nrefactoring questionable, including:\n\n  1. The meaning of branch->pushremote is subtly different from that of\n     branch->remote. Ram's followup refactoring did a better job of\n     that (but he is missing the patches on top to finish out the\n     feature).\n\n  2. We are duplicating the \"where to push\" logic here. That should\n     probably be factored out so that \"git push\" and \"@{publish}\" use\n     the same logic.\n\nAnd of course there are no tests or documentation. It might work,\nthough.\n\nI don't mind if you want to merge it and do more work in-tree, but I do\nnot think it should graduate as-is. And you may want check from Ram that\nhe is not in the middle of his own version based on the patches he sent\nearlier, as reworking them on top of mine would probably just be\nneedless extra work.\n\nAre you planning on having request-pull use @{publish} as a default? I\nsaw you cc'd me on that thread, but I didn't have any opinion besides\n\"sounds like you could use it here\".\n\n-Peff\n"},{"id":"233728","messageId":"CALkWK0mgGyYaTmSTLL5BRpr6cOWgx7VJuQTtuqDnmjCMbXhgqA@mail.gmail.com","threadId":"35623","inReplyTo":"20140124213521.GA26602@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2014-01-24T22:05:35Z","receivedAt":"2014-01-24T22:05:35Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Jeff King wrote:\n> As far as merging it to 'next', I had not really intended it to go that\n> far. :) It was more for Ram to use as a base.\n\nSorry about not having posted a follow-up yet; I'm adjusting to a new\ntimezone and environment.\n\n> I find some of the\n> refactoring questionable, including:\n>\n>   1. The meaning of branch->pushremote is subtly different from that of\n>      branch->remote. Ram's followup refactoring did a better job of\n>      that (but he is missing the patches on top to finish out the\n>      feature).\n>\n>   2. We are duplicating the \"where to push\" logic here. That should\n>      probably be factored out so that \"git push\" and \"@{publish}\" use\n>      the same logic.\n>\n> And of course there are no tests or documentation. It might work,\n> though.\n\nActually, task (2) is somewhat involved: I still haven't figured out\nhow to share code with 'git push'.\n\n> I don't mind if you want to merge it and do more work in-tree, but I do\n> not think it should graduate as-is. And you may want check from Ram that\n> he is not in the middle of his own version based on the patches he sent\n> earlier, as reworking them on top of mine would probably just be\n> needless extra work.\n\nOn that note, can you hold off graduating\njk/branch-at-publish-rebased, Junio? Hopefully, I'll come up with a\nreplacement over the weekend.\n\nThanks.\n"},{"id":"233733","messageId":"xmqq61p9q8jg.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"CALkWK0mgGyYaTmSTLL5BRpr6cOWgx7VJuQTtuqDnmjCMbXhgqA@mail.gmail.com","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-01-24T23:12:03Z","receivedAt":"2014-01-24T23:12:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ramkumar Ramachandra <artagnon@gmail.com> writes:\n\n> On that note, can you hold off graduating\n> jk/branch-at-publish-rebased, Junio? Hopefully, I'll come up with a\n> replacement over the weekend.\n\nSure.\n\nThis close to the feature freeze, I'd rather see all contributors,\nnot limited to you, not rush on new and shiny things, but instead\nspend time looking at bugs and fixes proposed for the upcoming\nrelease in the codepaths they were involved.\n\nThe send-email SSL issue $gmane/240479 is one of the things I'd like\nto see your sanity-checking ;-)\n"},{"id":"234851","messageId":"9D08338A41454F778D03FB2E9F4B7DD1@PhilipOakley","threadId":"35623","inReplyTo":"20140124213521.GA26602@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":null,"receivedAt":"2014-02-15T10:29:38Z","isPatch":true,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"Jeff King\" <peff@peff.net>\nSent: Friday, January 24, 2014 9:35 PM\n> On Thu, Jan 23, 2014 at 04:16:06PM -0800, Junio C Hamano wrote:\n>\n>> Jeff King <peff@peff.net> writes:\n>>\n>> > In a triangular workflow, you may have a distinct\n>> > @{upstream} that you pull changes from, but publish by\n>> > default (if you typed \"git push\") to a different remote (or\n>> > a different branch on the remote). It may sometimes be\n>> > useful to be able to quickly refer to that publishing point\n>> > (e.g., to see which changes you have that have not yet been\n>> > published).\n>> >\n>> > This patch introduces the <branch>@{publish} shorthand (or\n>> > \"@{pu}\" to be even shorter).\n\nJust to say that I'm not sure that \"publish\" is the best word for this \nconcept.\n\nTo my mind something is published when some form of editorial oversight \nhas been applied to the works. Such an understanding would better match \nthe 'upstream' concept (e.g. $gmane/240230 jch/9Jan14). This should be \ndistinguished from 'self-publishing', and again from \n'vanity-publishing'.\n\nIn terms of the triangular work-flow such a 'publish' repo is somewhere \nbetween a vanity publishing, and self publishing (depending on the level \nof code cleanliness;-)\n\nOne of the problems, just like the 'staging/index' discussions, is the\nlack of suitable word for the new working concepts that perfect\nreproduction has brought.\n\nAt best, I considered terms such as \"home\" repo, \"depository\" repo and \n\"self\" repo, and the many synonyms of publish, store, copy, duplicate, \netc. without much success.\n\nFinding a right term or phrase for the concept will be important to \nensure some clarity and distinction between the upstream and one's \n'home' repo. Perhaps \"self-storage\" might be borrowed from that \nnew(-ish) industry.\n\n>> >                                            It refers to the \n>> > tracking\n>> > branch of the remote branch to which you would push if you\n>> > were to push the named branch. That's a mouthful to explain,\n>> > so here's an example:\n>> >\n>> >   $ git checkout -b foo origin/master\n>> >   $ git config remote.pushdefault github\n>> >   $ git push\n>> >\n>> > Signed-off-by: Jeff King <peff@peff.net>\n>> > ---\n>>\n>> As there is no @{pu} in publish_mark() as far as I can see, and also\n>> I found it is a bit unclear what the example in the last paragraph\n>> wants to illustrate, I'll reword the above as the following before\n>> merging it to 'next'.\n>\n> Yeah, I think the @{pu} was just a silly omission from the code, \n> though\n> I agree after our discussion that we should just stick with \n> \"@{publish}\"\n> for now.\n>\n> I am not sure why I said \"git push\" at the end. I would have thought\n> that:\n>\n>  $ git rev-parse --symbolic-full-name @{publish}\n>  refs/remotes/github/foo\n>\n> would have been the right command to demonstrate. The text you \n> suggested\n> is fine, though I think you can simply drop the \"git push\", as it does\n> not add anything.\n>\n> As far as merging it to 'next', I had not really intended it to go \n> that\n> far. :) It was more for Ram to use as a base. I find some of the\n> refactoring questionable, including:\n>\n>  1. The meaning of branch->pushremote is subtly different from that of\n>     branch->remote. Ram's followup refactoring did a better job of\n>     that (but he is missing the patches on top to finish out the\n>     feature).\n>\n>  2. We are duplicating the \"where to push\" logic here. That should\n>     probably be factored out so that \"git push\" and \"@{publish}\" use\n>     the same logic.\n>\n> And of course there are no tests or documentation. It might work,\n> though.\n>\n> I don't mind if you want to merge it and do more work in-tree, but I \n> do\n> not think it should graduate as-is. And you may want check from Ram \n> that\n> he is not in the middle of his own version based on the patches he \n> sent\n> earlier, as reworking them on top of mine would probably just be\n> needless extra work.\n>\n> Are you planning on having request-pull use @{publish} as a default? I\n> saw you cc'd me on that thread, but I didn't have any opinion besides\n> \"sounds like you could use it here\".\n>\n> -Peff\n> --\nPhilip \n"},{"id":"234948","messageId":"20140218085224.GB2692@sigill.intra.peff.net","threadId":"35623","inReplyTo":"9D08338A41454F778D03FB2E9F4B7DD1@PhilipOakley","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-02-18T08:52:24Z","receivedAt":"2014-02-18T08:52:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Feb 15, 2014 at 11:50:10AM -0000, Philip Oakley wrote:\n\n> >>> This patch introduces the <branch>@{publish} shorthand (or\n> >>> \"@{pu}\" to be even shorter).\n> \n> Just to say that I'm not sure that \"publish\" is the best word for\n> this concept.\n> \n> To my mind something is published when some form of editorial\n> oversight has been applied to the works. Such an understanding would\n> better match the 'upstream' concept (e.g. $gmane/240230 jch/9Jan14).\n> This should be distinguished from 'self-publishing', and again from\n> 'vanity-publishing'.\n> \n> In terms of the triangular work-flow such a 'publish' repo is\n> somewhere between a vanity publishing, and self publishing (depending\n> on the level of code cleanliness;-)\n\nI would much rather have a name that describes what the thing _is_, then\nhow it is meant to be used. The concept of @{publish} is a shorthand for\n\"where would I push if I typed git push on this branch\". In a\nnon-triangular workflow, that means sharing your commits with others on\nthe main branch. In a triangular workflow, it means sharing your commits\nwith a publishing point so that others can see them. If your default\npush goes to a backup repo, it does not mean publishing at all, but\nrather syncing the backup.\n\nSo I do not think any one word can describe all of those use cases; they\nare orthogonal to each other, and it depends on your workflow.\n\nIn that sense, \"publish\" is not the best word, either, as it describes\nonly the first two, but not the third case (and those are just examples;\nthere may be other setups beyond that, even).\n\nPerhaps \"@{push}\" would be the most direct word.\n\n-Peff\n"},{"id":"234964","messageId":"CALKQrgeH+xOqjOv8Z0nnBrmE0=L8GMWn+ewiN+mWBkO5dOvtvA@mail.gmail.com","threadId":"35623","inReplyTo":"20140218085224.GB2692@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-02-18T13:10:32Z","receivedAt":"2014-02-18T13:10:32Z","isPatch":true,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Tue, Feb 18, 2014 at 9:52 AM, Jeff King <peff@peff.net> wrote:\n> On Sat, Feb 15, 2014 at 11:50:10AM -0000, Philip Oakley wrote:\n>> >>> This patch introduces the <branch>@{publish} shorthand (or\n>> >>> \"@{pu}\" to be even shorter).\n>>\n>> Just to say that I'm not sure that \"publish\" is the best word for\n>> this concept.\n>> [...]\n>\n> I would much rather have a name that describes what the thing _is_, then\n> how it is meant to be used. The concept of @{publish} is a shorthand for\n> \"where would I push if I typed git push on this branch\". In a\n> non-triangular workflow, that means sharing your commits with others on\n> the main branch. In a triangular workflow, it means sharing your commits\n> with a publishing point so that others can see them. If your default\n> push goes to a backup repo, it does not mean publishing at all, but\n> rather syncing the backup.\n>\n> So I do not think any one word can describe all of those use cases; they\n> are orthogonal to each other, and it depends on your workflow.\n>\n> In that sense, \"publish\" is not the best word, either, as it describes\n> only the first two, but not the third case (and those are just examples;\n> there may be other setups beyond that, even).\n>\n> Perhaps \"@{push}\" would be the most direct word.\n\nI agree that we want a more general (i.e. workflow-agnostic) term to\ndifferentiate between \"where we pull from\", and \"where we push to\". As\nsuch, \"@{push}\" should have a corresponding \"@{pull}\" (which I believe\nshould function as an alias of \"@{upstream}\"). [1]\n\n\n...Johan\n\n[1]: I don't think there is a reason not to reuse the \"push\"/\"pull\"\nterminology for these concepts, but if there is, I guess we could\ninstead call them \"@{source}\"/\"@{destination}\", \"@{src}/@{dst}\", or\n\"@{from}/@{to}\", or somesuch...\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"235011","messageId":"xmqqppmkdwq0.fsf@gitster.dls.corp.google.com","threadId":"35623","inReplyTo":"20140218085224.GB2692@sigill.intra.peff.net","subject":"Re: [PATCH 5/5] implement @{publish} shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-18T19:52:55Z","receivedAt":"2014-02-18T19:52:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> In that sense, \"publish\" is not the best word, either, as it describes\n> only the first two, but not the third case (and those are just examples;\n> there may be other setups beyond that, even).\n>\n> Perhaps \"@{push}\" would be the most direct word.\n\nHmph, then the other one would be @{pull}.\n\nWhich does not sound too bad, IMHO.\n"}]}