From: Johan Herland Date: Mon, 24 Jun 2013 15:23:58 GMT Subject: Re: [PATCH 6/6] push: honor branch.*.push Message-ID: In-Reply-To: On Mon, Jun 24, 2013 at 4:19 PM, Ramkumar Ramachandra wrote: > Junio C Hamano wrote: >>> # on branch master, derived from origin >>> $ git push ram >>> >>> And branch.master.push is set to next? Will you let her shoot herself >>> in the foot like this? >> >> It is not shooting in the foot, if branch.master.push is explicitly >> set to update next. I do not see any issue in that part. > > The question does not pertain to master being mapped to next; it > pertains to central-workflow versus triangular-workflow: origin versus > ram. If the user has set push.default to upstream, she _expects_ > triangular pushes to always be denied, and this is the first violation > of that rule. I'm tilting towards building a dependency between > branch..push and push.default. I haven't followed this topic closely, and the concern described below is probably a consequence of that. Please ignore if my worries are unfounded. It seems to me like we're adding (or have already added) quite a bit of config variables and command-line options for specifying (at varying levels of specificity and overridability) either the remote to push to ($remote), or what ref to push into on the remote ($remote_ref). It worries me that we allow $remote and $remote_ref to be set _separately_ and at separate levels of specificity. I wonder if this too easily allows users to shoot themselves in the foot by specifying $remote in one place (e.g. on the command line), then (in their mind - unrelated) specifying $remote_ref in another place (e.g. branch.foo.push), and then being negatively surprised when the two conspire to push into the "wrong" $remote and/or $remote_ref. I haven't yet dug deep enough to figure out an obvious failure mode (and I probably should not have sent this email until I'd found one), but I wonder if we'd be better off forcing the $remote and $remote_ref configuration for a given branch to appear as more of a single unit. What if, when setting up tracking for a given branch, we immediately specified its complete pull and push targets? For example, when in a centralized workflow (e.g. push.default = upstream) and we're checking out local branch foo from origin's foo, we could set up the following configuration [1]: [branch "foo"] pull = origin/foo push = origin/foo In a triangular workflow (assuming we had configuration to specify such, and also a default push remote), we could then instead set up the following config: [branch "foo"] pull = origin/foo push = my_public/foo This leaves no ambiguity for even the most novice user as to the pull and push targets for a given branch, and it's also easy to change it, either by editing the config file directly, or by using hypothetical commands: git branch foo --pulls-from=origin/bar git branch foo --pushes-to=other_repo/foo Any "git pull" without arguments will fail if branch..pull is unset or invalid. Likewise any "git push" without arguments will fail if branch..push is unset or invalid. Obviously, specifying the remote and/or refspec on the command-line would still override, as it does today, but for the argument-less forms of "git pull" and "git push", the hierarchy of options and defaults being consulted to figure out $remote and $remote_ref would be small and easily understandable. ...Johan [1]: I do realize that I'm abusing the "foo/bar" notation to mean "$remote/$ref", and that this does not work in the general case where both remote names and ref names may contain slashes, or when remote names don't correspond to eponymous ref namespaces... -- Johan Herland, www.herland.net