path: root/builtin/push.c
diff options
authorJunio C Hamano <>2012-03-30 23:07:12 (GMT)
committerJunio C Hamano <>2012-04-05 20:35:57 (GMT)
commit135dadef712f0c4cf884940e751024c831937904 (patch)
tree84572dd70ab3621c74df5a172b332469c2c77c1a /builtin/push.c
parentd365a432271d2f6384cda9c37fb2fe463bdc2850 (diff)
push: error out when the "upstream" semantics does not make sense
The user can say "git push" without specifying any refspec. When using the "upstream" semantics via the push.default configuration, the user wants to update the "upstream" branch of the current branch, which is the branch at a remote repository the current branch is set to integrate with, with this command. However, there are cases that such a "git push" that uses the "upstream" semantics does not make sense: - The current branch does not have branch.$name.remote configured. By definition, "git push" that does not name where to push to will not know where to push to. The user may explicitly say "git push $there", but again, by definition, no branch at repository $there is set to integrate with the current branch in this case and we wouldn't know which remote branch to update. - The current branch does have branch.$name.remote configured, but it does not specify branch.$name.merge that names what branch at the remote this branch integrates with. "git push" knows where to push in this case (or the user may explicitly say "git push $remote" to tell us where to push), but we do not know which remote branch to update. - The current branch does have its remote and upstream branch configured, but the user said "git push $there", where $there is not the remote named by "branch.$name.remote". By definition, no branch at repository $there is set to integrate with the current branch in this case, and this push is not meant to update any branch at the remote repository $there. The first two cases were already checked correctly, but the third case was not checked and we ended up updating the branch named branch.$name.merge at repository $there, which was totally bogus. Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'builtin/push.c')
1 files changed, 18 insertions, 8 deletions
diff --git a/builtin/push.c b/builtin/push.c
index d315475..b6c0fee 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -65,6 +65,16 @@ static void set_refspecs(const char **refs, int nr)
+static int push_url_of_remote(struct remote *remote, const char ***url_p)
+ if (remote->pushurl_nr) {
+ *url_p = remote->pushurl;
+ return remote->pushurl_nr;
+ }
+ *url_p = remote->url;
+ return remote->url_nr;
static void setup_push_upstream(struct remote *remote)
struct strbuf refspec = STRBUF_INIT;
@@ -76,7 +86,7 @@ static void setup_push_upstream(struct remote *remote)
" git push %s HEAD:<name-of-remote-branch>\n"),
- if (!branch->merge_nr || !branch->merge)
+ if (!branch->merge_nr || !branch->merge || !branch->remote_name)
die(_("The current branch %s has no upstream branch.\n"
"To push the current branch and set the remote as upstream, use\n"
@@ -87,6 +97,12 @@ static void setup_push_upstream(struct remote *remote)
if (branch->merge_nr != 1)
die(_("The current branch %s has multiple upstream branches, "
"refusing to push."), branch->name);
+ if (strcmp(branch->remote_name, remote->name))
+ die(_("You are pushing to remote '%s', which is not the upstream of\n"
+ "your current branch '%s', without telling me what to push\n"
+ "to update which remote branch."),
+ remote->name, branch->name);
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
@@ -196,13 +212,7 @@ static int do_push(const char *repo, int flags)
errs = 0;
- if (remote->pushurl_nr) {
- url = remote->pushurl;
- url_nr = remote->pushurl_nr;
- } else {
- url = remote->url;
- url_nr = remote->url_nr;
- }
+ url_nr = push_url_of_remote(remote, &url);
if (url_nr) {
for (i = 0; i < url_nr; i++) {
struct transport *transport =