{"thread":{"id":"33491","subject":"[RFC/PATCH] push: introduce implicit push","startedAt":"2013-04-12T15:33:55Z","lastAt":"2013-04-16T02:13:16Z","messageCount":21,"participants":["Ramkumar Ramachandra","Junio C Hamano","Jakub Narębski","Johannes Sixt","John Keeping","Felipe Contreras","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"214062","messageId":"1365780835-2853-1-git-send-email-artagnon@gmail.com","threadId":"33491","inReplyTo":null,"subject":"[RFC/PATCH] push: introduce implicit push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-04-12T15:33:55Z","receivedAt":"2013-04-12T15:33:55Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Currently, there is no way to invoke 'git push' without explicitly\nspecifying the destination to push to as the first argument.  When\npushing several branches, this information is often available in\nbranch.<name>.pushremote, falling back to branch.<name>.remote.  So,\nwe can use this information to create a more pleasant push experience.\nYou can now do:\n\n    $ git push master next pu\n\nIf the branches master, next, and pu have different remotes, do_push()\nwill be executed three times on the three different remotes.\n\nNOTE:\n\nPushing a non-branch ref still uses the current branch's\nconfiguration, and this is wrong.  We need to find a way to fix\nremote_get_1() without breaking existing features.\n\nSigned-off-by: Ramkumar Ramachandra <artagnon@gmail.com>\n---\n This is a very rough patch, meant to illustrate how to build our\n implicit push feature.  I think it's a really good idea, and will\n polish the patch after I get feedback.\n\n builtin/push.c | 56 ++++++++++++++++++++++++++++++++++--\n remote.c       | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n remote.h       |  9 ++++++\n 3 files changed, 152 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 909c34d..e8b667c 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -26,6 +26,12 @@ static int refspec_nr;\n static int refspec_alloc;\n static int default_matching_used;\n \n+static void reset_refspecs()\n+{\n+\trefspec_nr = 0;\n+\trefspec_alloc = 0;\n+}\n+\n static void add_refspec(const char *ref)\n {\n \trefspec_nr++;\n@@ -277,6 +283,11 @@ static void advise_ref_needs_force(void)\n \tadvise(_(message_advice_ref_needs_force));\n }\n \n+static int is_possible_refspec(const char *name) {\n+\t/* TODO: check that name looks like a refspec */\n+\treturn !is_configured_remote(name) && !strstr(name, \"://\");\n+}\n+\n static int push_with_options(struct transport *transport, int flags)\n {\n \tint err;\n@@ -319,10 +330,9 @@ static int push_with_options(struct transport *transport, int flags)\n \treturn 1;\n }\n \n-static int do_push(const char *repo, int flags)\n+static int do_push(const char *repo, struct remote *remote, int flags)\n {\n \tint i, errs;\n-\tstruct remote *remote = pushremote_get(repo);\n \tconst char **url;\n \tint url_nr;\n \n@@ -414,6 +424,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \tint tags = 0;\n \tint rc;\n \tconst char *repo = NULL;\t/* default repository */\n+\tstruct remote *remote;\n+\n \tstruct option options[] = {\n \t\tOPT__VERBOSITY(&verbosity),\n \t\tOPT_STRING( 0 , \"repo\", &repo, N_(\"repository\"), N_(\"repository\")),\n@@ -455,11 +467,49 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\tadd_refspec(\"refs/tags/*\");\n \n \tif (argc > 0) {\n+\t\tif (!strcmp(argv[0], \"--\") || is_possible_refspec(argv[0])) {\n+\t\t\tstruct refspec_with_remote *refspec_remotes;\n+\t\t\tint i, pushtimes;\n+\n+\t\t\t/* Attempt to fetch remotes for each refspec */\n+\t\t\tif (!strcmp(argv[0], \"--\"))\n+\t\t\t\tset_refspecs(argv + 1, argc - 1);\n+\t\t\telse\n+\t\t\t\tset_refspecs(argv, argc);\n+\t\t\trefspec_remotes = pushremote_get_for_refspec(refspec_nr,\n+\t\t\t\t\t\t\t\trefspec);\n+\t\t\tif (!refspec_remotes)\n+\t\t\t\tdie(_(\"internal error: refspec_remotes() returned NULL\"));\n+\n+\t\t\t/* TODO: collect the refspecs for each\n+\t\t\t * remote and batch the do_push() for\n+\t\t\t * each remote\n+\t\t\t */\n+\t\t\tfor (i = 0, pushtimes = refspec_nr; i < pushtimes; i++) {\n+\t\t\t\tstruct strbuf sb = STRBUF_INIT;\n+\n+\t\t\t\t/* TODO: clean up this nonsense */\n+\t\t\t\tif (refspec_remotes[i].refspec->dst)\n+\t\t\t\t\tstrbuf_addf(&sb, \"%s:%s\",\n+\t\t\t\t\t\trefspec_remotes[i].refspec->src,\n+\t\t\t\t\t\trefspec_remotes[i].refspec->dst);\n+\t\t\t\telse\n+\t\t\t\t\tstrbuf_addf(&sb, \"%s\",\n+\t\t\t\t\t\trefspec_remotes[i].refspec->src);\n+\t\t\t\treset_refspecs();\n+\t\t\t\tset_refspecs((const char **) &sb.buf, 1);\n+\t\t\t\trc = do_push(NULL, refspec_remotes[i].remote, flags);\n+\t\t\t\tif (rc == -1)\n+\t\t\t\t\tusage_with_options(push_usage, options);\n+\t\t\t}\n+\t\t\treturn rc;\n+\t\t}\n \t\trepo = argv[0];\n+\t\tremote = pushremote_get(repo);\n \t\tset_refspecs(argv + 1, argc - 1);\n \t}\n \n-\trc = do_push(repo, flags);\n+\trc = do_push(repo, remote, flags);\n \tif (rc == -1)\n \t\tusage_with_options(push_usage, options);\n \telse\ndiff --git a/remote.c b/remote.c\nindex 68eb99b..b51ac9b 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_for_branch;\n static int explicit_default_remote_name;\n \n static struct rewrites rewrites;\n@@ -345,6 +346,36 @@ static void read_branches_file(struct remote *remote)\n \tremote->fetch_tags = 1; /* always auto-follow */\n }\n \n+static int branch_config(const char *key, const char *value, void *data)\n+{\n+\tconst char *name;\n+\tconst char *subkey;\n+\tstruct branch *branch;\n+\tstruct branch *this_branch;\n+\n+\tif (!data)\n+\t\treturn -1;\n+\tthis_branch = (struct branch *) data;\n+\n+\tif (!prefixcmp(key, \"branch.\")) {\n+\t\tname = key + 7;\n+\t\tsubkey = strrchr(name, '.');\n+\t\tif (!subkey)\n+\t\t\treturn 0;\n+\t\tbranch = make_branch(name, subkey - name);\n+\t\tif (!strcmp(subkey, \".remote\")) {\n+\t\t\tif (branch == this_branch &&\n+\t\t\t\tgit_config_string(&pushremote_for_branch, key, value))\n+\t\t\t\treturn -1;\n+\t\t} else if (!strcmp(subkey, \".pushremote\")) {\n+\t\t\tif (branch == this_branch &&\n+\t\t\t\tgit_config_string(&pushremote_for_branch, key, value))\n+\t\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n static int handle_config(const char *key, const char *value, void *cb)\n {\n \tconst char *name;\n@@ -682,6 +713,12 @@ static int valid_remote_nick(const char *name)\n \treturn !strchr(name, '/'); /* no slash */\n }\n \n+int is_configured_remote(const char *name)\n+{\n+\tread_config();\n+\treturn valid_remote(make_remote(name, 0));\n+}\n+\n static struct remote *remote_get_1(const char *name, const char *pushremote_name)\n {\n \tstruct remote *ret;\n@@ -727,6 +764,59 @@ struct remote *pushremote_get(const char *name)\n \treturn remote_get_1(name, pushremote_name);\n }\n \n+struct refspec_with_remote *pushremote_get_for_refspec(int refspec_nr,\n+\t\t\t\t\t\tconst char **refspec)\n+{\n+\tstruct refspec_with_remote *ret;\n+\tstruct refspec *refspecs;\n+\tunsigned char sha1[20];\n+\tint i;\n+\n+\tread_config();\n+\tret = xcalloc(sizeof(struct refspec_with_remote), refspec_nr);\n+\trefspecs = parse_push_refspec(refspec_nr, refspec);\n+\n+\tfor (i = 0; i < refspec_nr; i++) {\n+\t\tconst char *src, *dst;\n+\t\tstruct remote *remote;\n+\n+\t\tsrc = resolve_ref_unsafe(refspecs[i].src, sha1, 0, NULL);\n+\t\tif (prefixcmp(src, \"refs/\"))\n+\t\t\tsrc = resolve_ref_unsafe(mkpath(\"refs/heads/%s\", src),\n+\t\t\t\t\t\tsha1, 1, NULL);\n+\t\tif (refspecs[i].dst) {\n+\t\t\tdst = resolve_ref_unsafe(refspecs[i].dst, sha1, 1, NULL);\n+\t\t\tif (prefixcmp(dst, \"refs/\"))\n+\t\t\t\tdst = resolve_ref_unsafe(mkpath(\"refs/heads/%s\", dst),\n+\t\t\t\t\t\t\tsha1, 1, NULL);\n+\t\t}\n+\t\tif (!src || (refspecs[i].dst && !dst)) {\n+\t\t\tremote = pushremote_get(NULL);\n+\t\t} else {\n+\t\t\tstruct branch *branch;\n+\n+\t\t\tbranch = make_branch(src + strlen(\"refs/heads/\"), 0);\n+\t\t\tgit_config(branch_config, branch);\n+\t\t\tif (!pushremote_for_branch)\n+\t\t\t\tdie(_(\"Branch %s does not have a valid configured \"\n+\t\t\t\t\t\t\"pushremote or remote\"), branch->name);\n+\n+\t\t\t/* Prepare the remote */\n+\t\t\tremote = make_remote(pushremote_for_branch, 0);\n+\t\t\tif (!valid_remote(remote))\n+\t\t\t\tdie(_(\"Branch %s has an invalid remote configured: %s\"),\n+\t\t\t\t\tbranch->name, remote->name);\n+\t\t\tremote->fetch = parse_fetch_refspec(remote->fetch_refspec_nr,\n+\t\t\t\t\t\t\tremote->fetch_refspec);\n+\t\t\tremote->push = parse_push_refspec(remote->push_refspec_nr,\n+\t\t\t\t\t\t\tremote->push_refspec);\n+\t\t}\n+\t\tret[i].refspec = &refspecs[i];\n+\t\tret[i].remote = remote;\n+\t}\n+\treturn ret;\n+}\n+\n int remote_is_configured(const char *name)\n {\n \tint i;\ndiff --git a/remote.h b/remote.h\nindex cf56724..e39cf1b 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -52,12 +52,15 @@ struct remote {\n \n struct remote *remote_get(const char *name);\n struct remote *pushremote_get(const char *name);\n+struct refspec_with_remote *pushremote_get_for_refspec(int nr_refspec,\n+\t\t\t\t\t\tconst char **refspec);\n int remote_is_configured(const char *name);\n \n typedef int each_remote_fn(struct remote *remote, void *priv);\n int for_each_remote(each_remote_fn fn, void *priv);\n \n int remote_has_url(struct remote *remote, const char *url);\n+int is_configured_remote(const char *name);\n \n struct refspec {\n \tunsigned force : 1;\n@@ -69,6 +72,12 @@ struct refspec {\n \tchar *dst;\n };\n \n+struct refspec_with_remote {\n+\tstruct refspec *refspec;\n+\tstruct remote *remote;\n+\tint collected:1;\n+};\n+\n extern const struct refspec *tag_refspec;\n \n struct ref *alloc_ref(const char *name);\n-- \n1.8.2.1.340.g945b0ee.dirty\n"},{"id":"214108","messageId":"7v38uvcrjl.fsf@alter.siamese.dyndns.org","threadId":"33491","inReplyTo":"1365780835-2853-1-git-send-email-artagnon@gmail.com","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-12T22:28:30Z","receivedAt":"2013-04-12T22:28:30Z","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> Currently, there is no way to invoke 'git push' without explicitly\n> specifying the destination to push to as the first argument.  When\n> pushing several branches, this information is often available in\n> branch.<name>.pushremote, falling back to branch.<name>.remote.  So,\n> we can use this information to create a more pleasant push experience.\n> You can now do:\n>\n>     $ git push master next pu\n>\n> If the branches master, next, and pu have different remotes, do_push()\n> will be executed three times on the three different remotes.\n\nI am lukewarm on this one, slightly more close to negative than\npositive, for a couple of reasons.\n\nThe primary reason is the confusion factor Jeff mentioned in the\nthread that inspired this patch.  People would realize it is very\nnatural to decide where to push to based on what branch is being\npushed, but only after they think it long and hard enough [*1*].  I\nsuspect that it is an equally natural expectation for casual users\nthat the destination is chosen based on the current branch, if only\nbecause that is what they are used to seeing when they say \"git\npush\" without any argument.\n\nEven though I personally am in favor of this \"destination is tied to\nwhat is pushed out\", not \"destination is chosen based on the current\nbranch\", I can understand why some people would prefer the latter,\nand why they find it simpler and easier to explain.\n\nThe second reason is purely on the differences between what the\nabove clean-nice explanation says and what the patch actually does.\n\nI think \"is-possible-refspec\" and \"pushremote-get-for-refspec\" are\nboth way over-engineered, even for people who agree with me and the\nabove introduction for this change to favor \"destination depends on\nwhat branch is pushed out\".  If is-possible-refspec is replaced with\na much simpler to understand logic, \"Is this a local branch name?\",\npossibly combined with \"There is no such path on the filesystem\" and\n\"It's not a defined remote\" (iow, reject \"git push master:next\" and\nanything more complex) [*2*], I suspect it would be a bit more\nsellable.\n\n\n[Footnote]\n\n*1* I've explained in a separate message why basing the destination\non what is being pushed is logical and internally consistent.\n\n*2* This is in the same spirit (not implementation or design) as\nrevname vs pathspec disambiguation.\n"},{"id":"214122","messageId":"CALkWK0=-GcOF17Q-y-Aqj0ThX5pPQFrriDqoJ2qsr=CS+wUNGA@mail.gmail.com","threadId":"33491","inReplyTo":"7v38uvcrjl.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-04-13T04:49:20Z","receivedAt":"2013-04-13T04:49:20Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Junio C Hamano wrote:\n> The primary reason is the confusion factor Jeff mentioned in the\n> thread that inspired this patch.  People would realize it is very\n> natural to decide where to push to based on what branch is being\n> pushed, but only after they think it long and hard enough [*1*].  I\n> suspect that it is an equally natural expectation for casual users\n> that the destination is chosen based on the current branch, if only\n> because that is what they are used to seeing when they say \"git\n> push\" without any argument.\n\nI agree with you largely, but I would still argue that choosing a\ndestination based on the current branch is a historical mistake made\nby \"matching\".  We don't have to be stuck with this historical\nmistake, because this is a new syntax: when users read about it in the\ndocumentation/ What's New in git.git type email, they will also learn\nthat it chooses the destination based on the refspec.\n\n> Even though I personally am in favor of this \"destination is tied to\n> what is pushed out\", not \"destination is chosen based on the current\n> branch\", I can understand why some people would prefer the latter,\n> and why they find it simpler and easier to explain.\n\nAgreed.  This is a consequence of not introducing triangular workflows\nearlier, and getting our users used to distributed workflows.  With\nthis patch, users must mandatorily know about remote.pushdefault and\nbranch.<name>.pushremote, if they want to work in multiple-remote\nscenarios.  My argument for that is that multiple-remote workflows\nhave always been a hack until now, and users of that setup will thank\nus for fixing this.\n\n> The second reason is purely on the differences between what the\n> above clean-nice explanation says and what the patch actually does.\n>\n> I think \"is-possible-refspec\" and \"pushremote-get-for-refspec\" are\n> both way over-engineered, even for people who agree with me and the\n> above introduction for this change to favor \"destination depends on\n> what branch is pushed out\".  If is-possible-refspec is replaced with\n> a much simpler to understand logic, \"Is this a local branch name?\",\n> possibly combined with \"There is no such path on the filesystem\" and\n> \"It's not a defined remote\" (iow, reject \"git push master:next\" and\n> anything more complex) [*2*], I suspect it would be a bit more\n> sellable.\n\nI don't feel strongly either way, as I just want a simple 'git push\nmaster next +pu' to DTRT.  I rarely, if ever, specify the :<dst> part\nof the refpsec.  Just so we're clear, we want:\n\n- In git push master, master is verified not to be a path on the\nfilesystem, not a remote, and finally a local branch.\n\n- In git push master:next, master:next is interpreted as a destination.\n\n- In git push master next:pu, master is verified as usual, and next:pu\nis pushed to the remote specified by next.  My patch currently does\nthis (checks that <src> and <dst> are branches).\n\n- In git push master next:refs/tags/v3.1 and git push master\nv3.1:refs/heads/next, master is verified as usual and the refspec is\npushed to the remote specified by remote.pushdefault, falling back to\norigin (since the <dst> is not a branch).  My patch currently pushes\nit to the current branch's configuration, and I've already marked it\nas a TODO.\n"},{"id":"214154","messageId":"7vehed7ilu.fsf@alter.siamese.dyndns.org","threadId":"33491","inReplyTo":"CALkWK0=-GcOF17Q-y-Aqj0ThX5pPQFrriDqoJ2qsr=CS+wUNGA@mail.gmail.com","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-14T04:42:51Z","receivedAt":"2013-04-14T04:42:51Z","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> I agree with you largely, but I would still argue that choosing a\n> destination based on the current branch is a historical mistake made\n> by \"matching\".\n\n\"matching\" is not necessarily a good default for everybody, and we\nare fixing that historical mistake in Git 2.0.\n\nStep back and think again. \"matching\" has never been about where the\npush goes.  It is about what are pushed out, once you decide where\nto push.\n\nIf a user often wants to push out a branch as soon as he made a\ncommit on it (even when other branches that go to the same\npublishing point should not be pushed out yet), an instructoin \"Ok,\nI'll push to that repository\" that pushes all matching branches will\nnot work well, because it will publish uncooked other branches, too.\n\nThat is the historical mistake of making \"matching\" the unconfigured\ndefault. The historical mistake of \"matching\" does not have anything\nto do with the choice of \"where to push\". It is only about \"what to\npush\".\n\nIf you re-read your three-remote example involving \"upstream\" (me),\n\"ram\" (your wip publishing point) and \"peff\":\n\n  Cf. http://thread.gmane.org/gmane.comp.version-control.git/220769/focus=220933\n\nyou'll see that the only reason why you thought you need the hack to\nset pushremote to null was because you did _not_ use matching. It\nillustrates one reason why blaming matching for selection of\ndestination misses the point.\n\nIn any case, dispelling a misplaced blame on \"matching\" is not the\nmain point of this message.\n\n> With this patch, users must mandatorily know about\n> remote.pushdefault and branch.<name>.pushremote, if they want to\n> work in multiple-remote scenarios.\n\nI am afraid that it is neither sufficient nor a good solution.\n\nI do not necessarily think that the best course is to devise an\nunintuitive (to unsuspecting users) set of rules and force users to\nunderstand it. That is where my secondary unhappiness comes from,\nand that was why I said that limiting the magic only to a very\nsimple and easy to understand case might make it more sellable.\n\n\"git push\" that pays attention to \"branch.*.remote\" was the original\nsin.\n\nTo casual users with push.default=current/upstream, the two branches\n(my current branch?  the branch I am pushing out?) have always been\nthe same when branch.*.remote is used.  These users don't even have\nto think about the distinction between the two [*1*].  But the\ndistinction starts mattering once you start wishing to omit saying\n_where_ to push, because at that point, _what_ to push is the only\nthing the user would give us, but the end users are not used to see\nthe destination chosen based on what is being pushed out.\n\nThe new branch.*.pushremote does not alleviate this confusion. It\ngives the same \"when on this branch, we push out to that remote\"\n(and not \"when pushing this branch out, it goes there\" impression.\n\nThe new remote.pushdefault _is_ a definite improvement: \"If I do not\nsay where to push, this is where things go\". It makes a very clear\nstatement, and does not have that confusion.\n\n> - In git push master, master is verified not to be a path on the\n> filesystem, not a remote, and finally a local branch.\n\nYes.\n\n> - In git push master:next, master:next is interpreted as a destination.\n\nIdeally it should notice and diagnose it as a syntax error and error\nout (of course an attempt to locate master: URL handler will fail,\nbut that is less nice).\n\n> - In git push master next:pu, master is verified as usual, and next:pu\n> is pushed to the remote specified by next.  My patch currently does\n> this (checks that <src> and <dst> are branches).\n\nI am not sure what you mean by \"and next:pu is...\".  If \"git push\nnext:pu master\" should error out without mistaking \"next:pu\" as\ndestination, so should \"git push master next:pu\", I think.\n\nThe last one is also the same.  The \"guess destination\" magic should\nkick in only when we can verify _all_ the refs we are pushing out\nare simple ones (branch names, and possibly tag names), and the\nbehaviour should not depend on the order. Anything more complex is\ntoo confusing.\n\nI personally think it is much more sellable to use an even simpler\nrule than what Jeff suggested, to make\n\n\tgit push -- <refspec>\n\ngo to the remote.pushdefault (falling back to remote.default that is\n\"origin\"), without even paying attention to what branch you are on,\nand ignoring branch.*.remote/pushremote configuration.\n\nThat is sufficient to support the triangular, the publish-to-mine,\nand the centralized workflows, no?  In any of these cases, the\nrepository you push out to is _one_, even though it may be a\ndifferent one from where you pull from.  If you have a very special\nbranch that goes to a different place than all the other branches,\nyou can always push out while on that branch without any refspec,\nanyway.\n\n\n[Footnote]\n\n*1* If you really think about what branch.*.remote is _for_, it says\n\"I want this branch to integrate with that branch at this remote\".\nIf the user were to push the branch out using the configuration, it\nis more logical to think of it as \"When pushing this branch out, it\ngoes there\", and not as \"When I am on this branch and say 'git\npush', 'git push' pushes there\".\n\nBut that is clear and logical _only_ to Git-heads who have thought\nabout this hard enough.\n"},{"id":"214159","messageId":"516A69E3.2090805@gmail.com","threadId":"33491","inReplyTo":"7vehed7ilu.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2013-04-14T08:33:39Z","receivedAt":"2013-04-14T08:33:39Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 14.04.2013 06:42, Junio C Hamano pisze:\n\n> I personally think it is much more sellable to use an even simpler\n> rule than what Jeff suggested, to make\n> \n> \tgit push -- <refspec>\n> \n> go to the remote.pushdefault (falling back to remote.default that is\n> \"origin\"), without even paying attention to what branch you are on,\n> and ignoring branch.*.remote/pushremote configuration.\n> \n> That is sufficient to support the triangular, the publish-to-mine,\n> and the centralized workflows, no?  In any of these cases, the\n> repository you push out to is _one_, even though it may be a\n> different one from where you pull from.  If you have a very special\n> branch that goes to a different place than all the other branches,\n> you can always push out while on that branch without any refspec,\n> anyway.\n\nI think it also supports users of 'matching' that have push default\ncorrectly configured.  Currently they can use \"git push\" in all cases\nbut first push of a branch, where they had to use \"git push origin\nbranch\", or \"git push pushremote branch\", and with those changes can\nnow simply use \"git push -- branch\".\n\nNice.\n\nHere I think simpler is better, especially that diferent users\nhave different expectations: push to remote based on current branch or\npush to remote or remotes based on branch or branches being pushed.\n-- \nJakub Narębski\n"},{"id":"214208","messageId":"CALkWK0k6bmjFxTSMAutgu2EjWRZ_cyTU9jZ3Er-aaV78T16RtQ@mail.gmail.com","threadId":"33491","inReplyTo":"7vehed7ilu.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-04-14T13:29:06Z","receivedAt":"2013-04-14T13:29:06Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Junio C Hamano wrote:\n> [...]\n> In any case, dispelling a misplaced blame on \"matching\" is not the\n> main point of this message.\n\nI _thought_ \"matching\" was a good scapegoat to blame current user\nexpectations on.  However, it's okay if you think that we're\nmisplacing the blame.  As long as we can agree that user expectations\nare aligned with \"choosing the remote based on the current branch\",\nwe're good.  Let's not waste time attempting to dissect the reason for\nthis.\n\n> I do not necessarily think that the best course is to devise an\n> unintuitive (to unsuspecting users) set of rules and force users to\n> understand it. That is where my secondary unhappiness comes from,\n> and that was why I said that limiting the magic only to a very\n> simple and easy to understand case might make it more sellable.\n\nNote that I'm not married to the interface I'm proposing: we can\nalways have a git branch --set-destination-to, corresponding to git\nbranch --set-upstream-to.  I'm not sure what interface to come up for\ntweaking remote.pushdefault though (since we have deemed that a\nremote.default counterpart is unnecessary, we've never really thought\nabout the problem).\n\n> The new branch.*.pushremote does not alleviate this confusion. It\n> gives the same \"when on this branch, we push out to that remote\"\n> (and not \"when pushing this branch out, it goes there\" impression.\n\nbranch.*.pushremote is a very new feature, and I doubt it's even\navailable to users yet (distribution package); therefore there is no\nmeaning set-in-stone that we cannot change quickly.  If you think\nabout it, it's completely illogical for branch.* options to depend on\nthe state of the worktree; I really think we should push for them to\nbe inherent branch properties: we can update the documentation\naccordingly, if we agree on this.\n\nI think the main point of disagreement is that I'm in favor of\nrespecting logic, while you're in favor of respecting user\nexpectations set by (what we acknowledge now as) historical mistakes.\n I'm not saying that we should _not_ respect user expectations, but\nrather that we should find some way to mould our users' expectations\nto align with the logical choice without causing unpleasantness.\n\n> The last one is also the same.  The \"guess destination\" magic should\n> kick in only when we can verify _all_ the refs we are pushing out\n> are simple ones (branch names, and possibly tag names), and the\n> behaviour should not depend on the order. Anything more complex is\n> too confusing.\n\nOkay, no problem.  Just so we're clear: the \"guess destination magic\"\nwill only kick in when all the refspecs specified are either tags or\nbranches, and are missing the :<dst> counterpart.  So, git push master\n+implicit-push should work just fine.\n\n> I personally think it is much more sellable to use an even simpler\n> rule than what Jeff suggested, to make\n>\n>         git push -- <refspec>\n>\n> go to the remote.pushdefault (falling back to remote.default that is\n> \"origin\"), without even paying attention to what branch you are on,\n> and ignoring branch.*.remote/pushremote configuration.\n>\n> That is sufficient to support the triangular, the publish-to-mine,\n> and the centralized workflows, no?  In any of these cases, the\n> repository you push out to is _one_, even though it may be a\n> different one from where you pull from.  If you have a very special\n> branch that goes to a different place than all the other branches,\n> you can always push out while on that branch without any refspec,\n> anyway.\n\nThis is logically incorrect: you're essentially making branches and\ntags equivalent, while this is clearly not the case.  Will I ever\ncreate \"throwaway tags\" just on my local machine for ease of working,\nthat I desire not to publish anywhere?  Now, replace \"tags\" with\n\"branches\" in that sentence, and you have a completely different\nanswer.  Will I ever want to send certain specific \"tags\" to a special\ndestination (for review, for instance)?  Again, \"branches\" gives you a\ndifferent answer.  Can I attach properties to tags?  Are there tag.*\nvariables that I can set?  Why, then, do branches have these\nvariables?  Because they're not tags!  The way we work with branches\nis completely different from the way we work with tags.\n\nLet me try to drive this point in even harder:\n\nMy local clone is never one repository, but a \"composite repository\"\ncontaining object stores from multiple remotes mixed in.  The\nfantastic thing about git is that I can use the same worktree/ index/\nlocal refs to work with this composite, as if it were a single\nrepository.  However, I need a way to sort through this mixed object\nstore/ multiple remotes madness: and for this, I have different remote\nrefs, and local branch specific configuration variables.  Again, I\ndon't think of my repository as a whole, but rather as a collection of\nrelated branches that each have a specific source and destination.  I\ndo _not_ have one global source, or one global destination: that's\njust the two-remote case, and git allows me to have N remotes in the\ngeneral case.  What I meant by \"triangular workflows\" was not the\nreduced case of a repository-wide triangle, but about many little\ntriangles associated with every branch.\n\nWhat is the practical application for all this?  What if I always want\nto send some specific branches to a different destination (say Gerrit\nreview, or my friend's \"integration server\")?  What if I never want to\npublish some branches (say they contain sensitive information such as\nprivate keys)?  What if my upstream gave me write access to some\nspecific branches (in which case, I don't want to push those branches\nto my usual \"fork destination\")?  Why are you proposing to\nartificially limit the implicit-push topic to not support these cases?\n They're not special or fringe cases, but the general case that git\nwas always designed for.\n\nMoreover, in your attempt to design a compromise, you're inventing a\ndifferent precedence order!  Wait a minute: why should we compromise\nin the first place?  We're not an old enterprise trying to satisfy a\nmyopic client specification for a living; developing git is our\nfull-time hobby (today is a Sunday, by the way), and we should not\nbuild something that we're less-than-elated with.  In my proposal, the\nprecedence order branch.<name>.pushremote, remote.pushdefault,\nbranch.<name>.remote, remote.default, origin, remains the same: we\njust want to change which branch that <name> refers to.  In my\nopinion, it is a much more subtle change than the entirely new\nprecedence order that you're inventing.\n"},{"id":"214262","messageId":"7vppxw335o.fsf@alter.siamese.dyndns.org","threadId":"33491","inReplyTo":"CALkWK0k6bmjFxTSMAutgu2EjWRZ_cyTU9jZ3Er-aaV78T16RtQ@mail.gmail.com","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-15T03:04:35Z","receivedAt":"2013-04-15T03:04:35Z","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> ...  In my proposal, the\n> precedence order branch.<name>.pushremote, remote.pushdefault,\n> branch.<name>.remote, remote.default, origin, remains the same: we\n> just want to change which branch that <name> refers to.\n\nThat \"changing the meaning of <name>\" in the middle, and doing so\nwill be confusing to the users, is exactly the issue, isn't it?\n\n> In my\n> opinion, it is a much more subtle change than the entirely new\n> precedence order that you're inventing.\n\nAdding \"--\" has never been my itch. I just brought it up out of thin\nair as a possible alternative that is less confusing.\n\nIf it does not work well, we do not have to add it, but it is\ndubious that we would want to add something that is even more\nconfusing.\n\nJust like Peff, I am sympathetic to people who want to omit \"where\nto\" and have Git automatically make a guess, and would be happy if\nwe can find a reasonable solution to that problem.\n\nBut I am not convinced what we discussed in these threads are good\nsolutions. At least not yet.\n"},{"id":"214267","messageId":"516BA732.4080405@viscovery.net","threadId":"33491","inReplyTo":"7vppxw335o.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2013-04-15T07:07:30Z","receivedAt":"2013-04-15T07:07:30Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 4/15/2013 5:04, schrieb Junio C Hamano:\n> Ramkumar Ramachandra <artagnon@gmail.com> writes:\n> \n>> ...  In my proposal, the\n>> precedence order branch.<name>.pushremote, remote.pushdefault,\n>> branch.<name>.remote, remote.default, origin, remains the same: we\n>> just want to change which branch that <name> refers to.\n> \n> That \"changing the meaning of <name>\" in the middle, and doing so\n> will be confusing to the users, is exactly the issue, isn't it?\n> \n>> In my\n>> opinion, it is a much more subtle change than the entirely new\n>> precedence order that you're inventing.\n> \n> Adding \"--\" has never been my itch. I just brought it up out of thin\n> air as a possible alternative that is less confusing.\n\nUser says:\n\n   git push -- master docs release\n\nThen git pushes the three branches to three different upstreams. You find\nthat confusing. Do I understanding correctly so far?\n\nIf I were a push.default=(simple|upstream) type, then I would be totally\naware that there are three different upstreams involved because I had had\nto configure them manually and explicitly (correct?), and I would be\ncompletely surprised if the push would *not* go to three different upstreams.\n\nJust my 2 cents. (But I'm a traditional \"matching\" type, so take this with\na grain of salt. Or I may be missing the point of this thread, as I\nhaven't followed closely.)\n\n-- Hannes\n"},{"id":"214268","messageId":"7vzjx01cqn.fsf@alter.siamese.dyndns.org","threadId":"33491","inReplyTo":"516BA732.4080405@viscovery.net","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-15T07:20:32Z","receivedAt":"2013-04-15T07:20:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j.sixt@viscovery.net> writes:\n\n> User says:\n>\n>    git push -- master docs release\n>\n> Then git pushes the three branches to three different upstreams. You find\n> that confusing. Do I understanding correctly so far?\n\nIt is far more subtle than that.  User says that while on 'next'\nbranch.\n\nThe user has been trained to think \"branch.master.remote\" takes\neffect while he has \"master\" branch checked out.\n\nThat is where the possible confusion comes from. As I said number of\ntimes, you may be able to declare that the confusion is unfounded\nonce you think it through.\n\n> Just my 2 cents. (But I'm a traditional \"matching\" type, so take this with\n> a grain of salt. Or I may be missing the point of this thread, as I\n> haven't followed closely.)\n\nFor exmaple, see\n\ncf. http://thread.gmane.org/gmane.comp.version-control.git/218429/focus=220707\n\nwhere I say \"branch.next.remote\" should not come into play when I\nsay \"git push --master docs release\" while on the next branch and\nPeff gives a counter-viewpoint.\n"},{"id":"214275","messageId":"20130415083558.GB2278@serenity.lan","threadId":"33491","inReplyTo":"7vzjx01cqn.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-04-15T08:35:59Z","receivedAt":"2013-04-15T08:35:59Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Apr 15, 2013 at 12:20:32AM -0700, Junio C Hamano wrote:\n> Johannes Sixt <j.sixt@viscovery.net> writes:\n> \n> > User says:\n> >\n> >    git push -- master docs release\n> >\n> > Then git pushes the three branches to three different upstreams. You find\n> > that confusing. Do I understanding correctly so far?\n> \n> It is far more subtle than that.  User says that while on 'next'\n> branch.\n> \n> The user has been trained to think \"branch.master.remote\" takes\n> effect while he has \"master\" branch checked out.\n> \n> That is where the possible confusion comes from. As I said number of\n> times, you may be able to declare that the confusion is unfounded\n> once you think it through.\n\nI may be an atypical user, but my expectation currently is that\nbranch.<name>.remote is what is used when I run \"git push\" with no\nadditional arguments.\n\nThis is probably because whenever I add additional arguments (currently)\nI have to specify where I am pushing to.\n\nSo I think breaking user expectations is a red herring here because the\ncurrent behaviour means that users cannot have any expectation of what\nwill happen in this case.  Either you don't say anything and \"git push\"\nDTRT for your current branch or you must specify precisely what you want\nto happen (or at least the remote to use if you have push.default =\nmatching or remote.<name>.mirror set).\n\nPersonally I'd vote for \"git push -- master\" pushing to\nremote.pushdefault, but I really don't know how you handle \"git push --\"\nwith the naïve implementation of that - is it the same as \"git push\" or\n\"git push $(git config remote.pushdefault)\"?\n\nOn the other hand, I'm really not sure how often I'd use this feature.\nNormally I just use \"git push\" and if I'm giving any more arguments than\nthat then it's for something that I don't do often enough for it to be\nworth setting up configuration.\n"},{"id":"214278","messageId":"CALkWK0kzpgucLbe5TtwbZ0st51+9ZW2hkML4=yHV4y--USfynA@mail.gmail.com","threadId":"33491","inReplyTo":"20130415083558.GB2278@serenity.lan","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-04-15T09:17:35Z","receivedAt":"2013-04-15T09:17:35Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"John Keeping wrote:\n> I may be an atypical user, but my expectation currently is that\n> branch.<name>.remote is what is used when I run \"git push\" with no\n> additional arguments.\n>\n> This is probably because whenever I add additional arguments (currently)\n> I have to specify where I am pushing to.\n>\n> So I think breaking user expectations is a red herring here because the\n> current behaviour means that users cannot have any expectation of what\n> will happen in this case.  Either you don't say anything and \"git push\"\n> DTRT for your current branch or you must specify precisely what you want\n> to happen (or at least the remote to use if you have push.default =\n> matching or remote.<name>.mirror set).\n>\n> Personally I'd vote for \"git push -- master\" pushing to\n> remote.pushdefault, but I really don't know how you handle \"git push --\"\n> with the naïve implementation of that - is it the same as \"git push\" or\n> \"git push $(git config remote.pushdefault)\"?\n\nWe're not changing, or even discussing, what a plain git push without\ndestination or refspecs specified should do (yes, that means git push\n-- too); it depends on push.default, which already exists.  My\nproposal does not aim to change the current behavior of _any_ current\ninvocation (that means git push, git push origin master, git push next\nmaster v1.2, and so on). It aims to make the new syntax git push\nmaster +next behave logically.  I think we can all agree that the\nlogical solution (leaving aside founded/ unfounded user expectations)\nis to pick destinations for each of the branches specified\nindividually.  As I explained in my last email, using\nremote.pushdefault is Wrong because it treats branches like tags, and\ninvents a new precedence.  Voting without a basis is useless: do you\nhave a counter-argument for the points I raised as to why it is Wrong?\n"},{"id":"214281","messageId":"7vk3o416rq.fsf@alter.siamese.dyndns.org","threadId":"33491","inReplyTo":"20130415083558.GB2278@serenity.lan","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-15T09:29:29Z","receivedAt":"2013-04-15T09:29:29Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> I may be an atypical user, but my expectation currently is that\n> branch.<name>.remote is what is used when I run \"git push\" with no\n> additional arguments.\n>\n> This is probably because whenever I add additional arguments (currently)\n> I have to specify where I am pushing to.\n>\n> So I think breaking user expectations is a red herring here because the\n> current behaviour means that users cannot have any expectation of what\n> will happen in this case.\n\nThe thing is, people _want_ to reuse the knowledge they have already\nlearned to a situation it does not directly apply to, by finding a\nconsequence, natural extension of that knowledge, applied to a new\nsituation.\n\n - Your \"branch.*.remote only kicks in when I do not say either what\n   to push or where to push to, so 'git push -- master' won't be\n   affected\" could be one valid natural extension to your knowledge\n   \"the config only kicks in when I do not say either\".\n\n - Peff's \"'git push' chooses to push to branch.next.remote when I\n   am on 'next', so 'git push -- master' run in the same state\n   should also push to that place\" is another equally valid natural\n   extension to his knowledge that \"'git push' chooses to push to\n   branch.next.remote when I am on 'next'\".\n\n - Ram's and my \"branch.master.remote is about what remote my master\n   branch integrates with, so no matter where I am, 'git push' that\n   does not say where-to should push out my master to that remote\"\n   is yet another equally valid natural extension to our knowledge\n   that \"\"branch.master.remote is about what remote my master branch\n   integrates with\".\n\nI do not think it is a red-herring at all. It is not about\n\"breaking\", but \"there will be multiple, conflicting and equally\nplausible expectations\" that makes me worry about unnecessary\nconfusion.\n"},{"id":"214282","messageId":"CALkWK0nNn_dGgr8F-kcQZm9UfkZAKwBd0bPSW9yCex4L9F+4Qw@mail.gmail.com","threadId":"33491","inReplyTo":"7vppxw335o.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-04-15T09:35:17Z","receivedAt":"2013-04-15T09:35:17Z","isPatch":true,"sender":{"key":"r@artagnon.com","avatar":"https://avatars.githubusercontent.com/u/37226?v=4"},"body":"Junio C Hamano wrote:\n> That \"changing the meaning of <name>\" in the middle, and doing so\n> will be confusing to the users, is exactly the issue, isn't it?\n\nYes, but we have to change _something_ if we don't want to hit a WTF\nlike 'git push master next' pushing master and next to\nbranch.<HEAD>.pushremote.  In my opinion, this seems to be the less\nevil (or disruptive) change.  After all, we're not proposing to change\nthe current behavior of any current git invocations: a plain git push\ncan still consider branch.<HEAD>.pushremote, and it's not a problem in\nmy opinion.  After all, a git fetch also considers\nbranch.<HEAD>.remote, and we all agree that this is fine.\n\n1. We are changing the meaning of branch.<name>.remote, but this is\nnot inconsistent with the current behavior of push.default at all\n(even push.default=matching).  We just have to improve the\npush.default documentation.\n\n2. We are not changing the meaning of _any_ existing git push\ninvocations.  Pushing \"unrelated branches\" to the \"corresponding\nremote\" has not been possible until now (unless you check out each of\nthe branches, set push.default=current, and git push), and we're\ninventing a new syntax that makes this possible.  I see no problem\nwith changing the meaning of branch.<name>.remote/pushremote for this\npurpose.\n\n> Just like Peff, I am sympathetic to people who want to omit \"where\n> to\" and have Git automatically make a guess, and would be happy if\n> we can find a reasonable solution to that problem.\n>\n> But I am not convinced what we discussed in these threads are good\n> solutions. At least not yet.\n\nThere are only so many possibilities, Junio*.  You either decide that\nthe logical alternative that I proposed is too confusing and drop the\nidea, or think about how to move forward minimizing friction.\n\n* If you think there are other possibilities, I'd be glad to hear them.\n"},{"id":"214284","messageId":"CALkWK0=aU1e1jh5kbemde8PEbmbUOpAH0jzGZ=0m6c7L3Wz8bg@mail.gmail.com","threadId":"33491","inReplyTo":"7vk3o416rq.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Ramkumar Ramachandra","fromEmail":"artagnon@gmail.com","sentAt":"2013-04-15T09:44:44Z","receivedAt":"2013-04-15T09:44:44Z","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 think it is a red-herring at all. It is not about\n> \"breaking\", but \"there will be multiple, conflicting and equally\n> plausible expectations\" that makes me worry about unnecessary\n> confusion.\n\nWell put.\n\nMy solution to the problem is to take one of the three alternatives,\nand show how it plugs into the larger workflow picture; in this case,\nhow my proposal fits into the larger picture of a local clone being a\ncollection of branches, each having little triangles.\n"},{"id":"214286","messageId":"20130415094605.GD2278@serenity.lan","threadId":"33491","inReplyTo":"CALkWK0kzpgucLbe5TtwbZ0st51+9ZW2hkML4=yHV4y--USfynA@mail.gmail.com","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-04-15T09:46:05Z","receivedAt":"2013-04-15T09:46:05Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Apr 15, 2013 at 02:47:35PM +0530, Ramkumar Ramachandra wrote:\n> John Keeping wrote:\n> > I may be an atypical user, but my expectation currently is that\n> > branch.<name>.remote is what is used when I run \"git push\" with no\n> > additional arguments.\n> >\n> > This is probably because whenever I add additional arguments (currently)\n> > I have to specify where I am pushing to.\n> >\n> > So I think breaking user expectations is a red herring here because the\n> > current behaviour means that users cannot have any expectation of what\n> > will happen in this case.  Either you don't say anything and \"git push\"\n> > DTRT for your current branch or you must specify precisely what you want\n> > to happen (or at least the remote to use if you have push.default =\n> > matching or remote.<name>.mirror set).\n> >\n> > Personally I'd vote for \"git push -- master\" pushing to\n> > remote.pushdefault, but I really don't know how you handle \"git push --\"\n> > with the naïve implementation of that - is it the same as \"git push\" or\n> > \"git push $(git config remote.pushdefault)\"?\n> \n> We're not changing, or even discussing, what a plain git push without\n> destination or refspecs specified should do (yes, that means git push\n> -- too); it depends on push.default, which already exists.  My\n> proposal does not aim to change the current behavior of _any_ current\n> invocation (that means git push, git push origin master, git push next\n> master v1.2, and so on). It aims to make the new syntax git push\n> master +next behave logically.  I think we can all agree that the\n> logical solution (leaving aside founded/ unfounded user expectations)\n> is to pick destinations for each of the branches specified\n> individually.  As I explained in my last email, using\n> remote.pushdefault is Wrong because it treats branches like tags, and\n> invents a new precedence.  Voting without a basis is useless: do you\n> have a counter-argument for the points I raised as to why it is Wrong?\n\nAs Junio says in his parallel message, there are different opinions\nhere, my suggestions was to effectively replace \"--\" with the value of\nremote.pushdefault.  I don't think your solution is not logical, but I\ndon't think it is the unique logical solution.\n\nThe problem is that people have different opinions of what the current\nsituation means, resulting in different expectations of what push\nwithout a remote should do.  Whatever behaviour we choose /will/ be\nsurprising to some users, even though it is completely logical.  That\nmuch is clear from the differing opinions in this thread.\n"},{"id":"214291","messageId":"20130415095920.GE2278@serenity.lan","threadId":"33491","inReplyTo":"7vk3o416rq.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-04-15T09:59:20Z","receivedAt":"2013-04-15T09:59:20Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Apr 15, 2013 at 02:29:29AM -0700, Junio C Hamano wrote:\n>  - Your \"branch.*.remote only kicks in when I do not say either what\n>    to push or where to push to, so 'git push -- master' won't be\n>    affected\" could be one valid natural extension to your knowledge\n>    \"the config only kicks in when I do not say either\".\n> \n>  - Peff's \"'git push' chooses to push to branch.next.remote when I\n>    am on 'next', so 'git push -- master' run in the same state\n>    should also push to that place\" is another equally valid natural\n>    extension to his knowledge that \"'git push' chooses to push to\n>    branch.next.remote when I am on 'next'\".\n> \n>  - Ram's and my \"branch.master.remote is about what remote my master\n>    branch integrates with, so no matter where I am, 'git push' that\n>    does not say where-to should push out my master to that remote\"\n>    is yet another equally valid natural extension to our knowledge\n>    that \"\"branch.master.remote is about what remote my master branch\n>    integrates with\".\n> \n> I do not think it is a red-herring at all. It is not about\n> \"breaking\", but \"there will be multiple, conflicting and equally\n> plausible expectations\" that makes me worry about unnecessary\n> confusion.\n\nOkay, I think it's a red herring from my point of view that \"this is\nsomething new that is very different from the current functionality\",\nbut as you point out, \"no arguments vs. some arguments\" is only one\npotential internal model of the current behaviour.\n\nSo the question is \"what is the natural extension of the current\nbehaviour?\", and the answer for me is \"it's completely new\", but others\nhave different (and conflicting) internal models that give different\nanswers.\n"},{"id":"214323","messageId":"CAMP44s0u3=FEuifS8KaGy3Y_mjtjeuL1PfChSUco_0TdOXp-jg@mail.gmail.com","threadId":"33491","inReplyTo":"20130415095920.GE2278@serenity.lan","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-04-15T16:39:40Z","receivedAt":"2013-04-15T16:39:40Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Mon, Apr 15, 2013 at 4:59 AM, John Keeping <john@keeping.me.uk> wrote:\n\n> So the question is \"what is the natural extension of the current\n> behaviour?\", and the answer for me is \"it's completely new\", but others\n> have different (and conflicting) internal models that give different\n> answers.\n\nI don't think this does anybody any service. If the current behavior\nis wrong, and if users all over the Internet is any indication, it is;\nwe do not want to continue such bad behavior. If the new\nfunctionality has a different behavior, it only makes sense to change\nthe old behavior to make it consistent.\n\nPerpetuating bad behavior choices only hurt the users, we need to\nstart thinking how to make git more user friendly, not worry too much\nabout keep doing what we did five years ago.\n\nSure, we should not break user expectations from one day to the next,\nbut that doesn't mean we can't change anything ever.\n\n-- \nFelipe Contreras\n"},{"id":"214329","messageId":"20130415171348.GI2278@serenity.lan","threadId":"33491","inReplyTo":"CAMP44s0u3=FEuifS8KaGy3Y_mjtjeuL1PfChSUco_0TdOXp-jg@mail.gmail.com","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2013-04-15T17:13:48Z","receivedAt":"2013-04-15T17:13:48Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Apr 15, 2013 at 11:39:40AM -0500, Felipe Contreras wrote:\n> On Mon, Apr 15, 2013 at 4:59 AM, John Keeping <john@keeping.me.uk> wrote:\n> \n> > So the question is \"what is the natural extension of the current\n> > behaviour?\", and the answer for me is \"it's completely new\", but others\n> > have different (and conflicting) internal models that give different\n> > answers.\n> \n> I don't think this does anybody any service. If the current behavior\n> is wrong, and if users all over the Internet is any indication, it is;\n> we do not want to continue such bad behavior. If the new\n> functionality has a different behavior, it only makes sense to change\n> the old behavior to make it consistent.\n\nThe current \"push.default = matching\" behaviour may be wrong, but I\nhaven't seen anyone say that the fundamental \"'git push' does something\ndepending on push.default\" and \"'git push there ref...' specifies\nexactly what to do\" is broken.\n"},{"id":"214330","messageId":"CAMP44s3J=+U5sM69ZMd3-joG=PHOxyebdvxcCOiqfd4yz2pygA@mail.gmail.com","threadId":"33491","inReplyTo":"20130415171348.GI2278@serenity.lan","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-04-15T17:18:30Z","receivedAt":"2013-04-15T17:18:30Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Mon, Apr 15, 2013 at 12:13 PM, John Keeping <john@keeping.me.uk> wrote:\n> On Mon, Apr 15, 2013 at 11:39:40AM -0500, Felipe Contreras wrote:\n>> On Mon, Apr 15, 2013 at 4:59 AM, John Keeping <john@keeping.me.uk> wrote:\n>>\n>> > So the question is \"what is the natural extension of the current\n>> > behaviour?\", and the answer for me is \"it's completely new\", but others\n>> > have different (and conflicting) internal models that give different\n>> > answers.\n>>\n>> I don't think this does anybody any service. If the current behavior\n>> is wrong, and if users all over the Internet is any indication, it is;\n>> we do not want to continue such bad behavior. If the new\n>> functionality has a different behavior, it only makes sense to change\n>> the old behavior to make it consistent.\n>\n> The current \"push.default = matching\" behaviour may be wrong, but I\n> haven't seen anyone say that the fundamental \"'git push' does something\n> depending on push.default\" and \"'git push there ref...' specifies\n> exactly what to do\" is broken.\n\nMaybe not, but that doesn't mean that the new behavior should be\nlimited by the old one. If there's an ideal new behavior, the old one\nshould eventually be updated to accommodate the new one.\n\n-- \nFelipe Contreras\n"},{"id":"214415","messageId":"20130416020515.GE3262@elie.Belkin","threadId":"33491","inReplyTo":"CALkWK0nNn_dGgr8F-kcQZm9UfkZAKwBd0bPSW9yCex4L9F+4Qw@mail.gmail.com","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-04-16T02:05:15Z","receivedAt":"2013-04-16T02:05:15Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Ramkumar Ramachandra wrote:\n> Junio C Hamano wrote:\n\n>> That \"changing the meaning of <name>\" in the middle, and doing so\n>> will be confusing to the users, is exactly the issue, isn't it?\n>\n> Yes, but we have to change _something_ if we don't want to hit a WTF\n> like 'git push master next' pushing master and next to\n> branch.<HEAD>.pushremote.\n\nYep.  In the usual case, all relevant remotes are \"origin\" anyway, so\nthere's no confusion.  In the confusing cases it would be safer to\nerror out and give the user a hint about how to make the configuration\nless confusing.\n\nThe manual could say:\n\n\tIn olden times, each [branch \"<name>\"] section would often have\n\tits own remote and pushRemote settings.  Ordinary branch creation\n\teven created such a configuration.  Nowadays that is\n\tdiscouraged: we have found that it is less confusing in\n\tpractice to:\n\n\t A) Typically fetch from one remote \"[remote] default = origin\"\n\t    and push to another \"[remote] pushDefault = personal\".\n\n\t B) In atypical cases, explicitly name the remote being used\n\t    on the command line.\n\nThinking more, I suspect there is an asymmetry between \"fetch\" and\n\"push\" here that we missed.  The manual could say:\n\n\tIn typical usage, a person ordinarily pushes to a single\n\tpreferred publication point.  You can set your publication\n\tpoint using the \"[remote] pushDefault\" setting:\n\n\t\t[remote]\n\t\t\tpushDefault = myserver.example.com:/path/to/repo.git\n\n\tTo push a collection of branches to that remote repository,\n\tpass a list of branch names to \"git push\" with a\n\tdisambiguating \"--\" to ensure the first branch name is not\n\ttreated as a remote name:\n\n\t\tgit push -- master next pu\n\n\tFor historical reasons, if \"[remote] pushDefault\" is not set,\n\tit defaults to the remote that the branch being pushed is set\n\tto pull from (its \"upstream\").  If pushDefault is unset and\n\tmultiple branches being pushed have different upstream\n\trepositories, Git will error out to allow you to disambiguate.\n\n\tTo push to a different remote repository, just name it\n\texplicitly on the command line.\n\n\t\tgit push korg -- master next pu\n\nThe asymmetry is because a command like \"git fetch -- master next pu\"\ndoesn't make much sense, since you have to know what remote you\nfetched from to act on the fetch result.\n\nAs you hinted before, this would involve reverting the introduction\nof \"branch.<name>.pushremote\", with the explanation that it was a\nmistake inspired by that false symmetry, that you noticed and were\nuncomfortable with but the rest of us were blind too.\n\nDoes that make sense?\n\nJonathan\n"},{"id":"214416","messageId":"20130416021316.GF3262@elie.Belkin","threadId":"33491","inReplyTo":"20130416020515.GE3262@elie.Belkin","subject":"Re: [RFC/PATCH] push: introduce implicit push","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2013-04-16T02:13:16Z","receivedAt":"2013-04-16T02:13:16Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Jonathan Nieder wrote:\n\n> As you hinted before, this would involve reverting the introduction\n> of \"branch.<name>.pushremote\", with the explanation that it was a\n> mistake inspired by that false symmetry, that you noticed and were\n> uncomfortable with but the rest of us were blind too.\n\ns/too/to/\n\nFor the curious, here is the motivation for the weird syntax I\nsuggested:\n\n\tgit push foo bar -- baz qux\n\nSure, I want \"git push master\" to work since it might reduce the\nvolume of questions on #git.  But selfishly, more important to me\nwas that it would simplify my life as I frequently do\n\n\tgit push repo wagner vasks -- debian-experimental +candidate+patches\n\nin three steps, and I'd rather do it in one.  I think of repo.or.cz,\nwagner.debian.org, and vasks.debian.org as three different remotes and\nlike maintaining separate remote-tracking branches for them, so a\nsingle remote/multiple urls setup didn't work as well when I tried it.\n\nI should warn you that the sketch of a design I am replying to is\nincomplete.  It doesn't say what should happen if you try\n\n\tgit push -- master:theirmaster next:theirnext\n\nThanks,\nJonathan\n"}]}