Skip to content

Commit 27da1cf

Browse files
committed
Merge branch 'jc/push-upstream-sanity'
Fix broken 'push to upstream' implementation. "git push $there" without refspec, when the current branch is set to push to a remote different from $there, used to push to $there using the upstream information to a remote unreleated to $there. * jc/push-upstream-sanity: push: error out when the "upstream" semantics does not make sense
2 parents bb52e7f + 135dade commit 27da1cf

File tree

2 files changed

+72
-8
lines changed

2 files changed

+72
-8
lines changed

builtin/push.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ static void set_refspecs(const char **refs, int nr)
6565
}
6666
}
6767

68+
static int push_url_of_remote(struct remote *remote, const char ***url_p)
69+
{
70+
if (remote->pushurl_nr) {
71+
*url_p = remote->pushurl;
72+
return remote->pushurl_nr;
73+
}
74+
*url_p = remote->url;
75+
return remote->url_nr;
76+
}
77+
6878
static void setup_push_upstream(struct remote *remote)
6979
{
7080
struct strbuf refspec = STRBUF_INIT;
@@ -76,7 +86,7 @@ static void setup_push_upstream(struct remote *remote)
7686
"\n"
7787
" git push %s HEAD:<name-of-remote-branch>\n"),
7888
remote->name);
79-
if (!branch->merge_nr || !branch->merge)
89+
if (!branch->merge_nr || !branch->merge || !branch->remote_name)
8090
die(_("The current branch %s has no upstream branch.\n"
8191
"To push the current branch and set the remote as upstream, use\n"
8292
"\n"
@@ -87,6 +97,12 @@ static void setup_push_upstream(struct remote *remote)
8797
if (branch->merge_nr != 1)
8898
die(_("The current branch %s has multiple upstream branches, "
8999
"refusing to push."), branch->name);
100+
if (strcmp(branch->remote_name, remote->name))
101+
die(_("You are pushing to remote '%s', which is not the upstream of\n"
102+
"your current branch '%s', without telling me what to push\n"
103+
"to update which remote branch."),
104+
remote->name, branch->name);
105+
90106
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
91107
add_refspec(refspec.buf);
92108
}
@@ -196,13 +212,7 @@ static int do_push(const char *repo, int flags)
196212
setup_default_push_refspecs(remote);
197213
}
198214
errs = 0;
199-
if (remote->pushurl_nr) {
200-
url = remote->pushurl;
201-
url_nr = remote->pushurl_nr;
202-
} else {
203-
url = remote->url;
204-
url_nr = remote->url_nr;
205-
}
215+
url_nr = push_url_of_remote(remote, &url);
206216
if (url_nr) {
207217
for (i = 0; i < url_nr; i++) {
208218
struct transport *transport =

t/t5528-push-default.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/bin/sh
2+
3+
test_description='check various push.default settings'
4+
. ./test-lib.sh
5+
6+
test_expect_success 'setup bare remotes' '
7+
git init --bare repo1 &&
8+
git remote add parent1 repo1 &&
9+
git init --bare repo2 &&
10+
git remote add parent2 repo2 &&
11+
test_commit one &&
12+
git push parent1 HEAD &&
13+
git push parent2 HEAD
14+
'
15+
16+
test_expect_success '"upstream" pushes to configured upstream' '
17+
git checkout master &&
18+
test_config branch.master.remote parent1 &&
19+
test_config branch.master.merge refs/heads/foo &&
20+
test_config push.default upstream &&
21+
test_commit two &&
22+
git push &&
23+
echo two >expect &&
24+
git --git-dir=repo1 log -1 --format=%s foo >actual &&
25+
test_cmp expect actual
26+
'
27+
28+
test_expect_success '"upstream" does not push on unconfigured remote' '
29+
git checkout master &&
30+
test_unconfig branch.master.remote &&
31+
test_config push.default upstream &&
32+
test_commit three &&
33+
test_must_fail git push
34+
'
35+
36+
test_expect_success '"upstream" does not push on unconfigured branch' '
37+
git checkout master &&
38+
test_config branch.master.remote parent1 &&
39+
test_unconfig branch.master.merge &&
40+
test_config push.default upstream
41+
test_commit four &&
42+
test_must_fail git push
43+
'
44+
45+
test_expect_success '"upstream" does not push when remotes do not match' '
46+
git checkout master &&
47+
test_config branch.master.remote parent1 &&
48+
test_config branch.master.merge refs/heads/foo &&
49+
test_config push.default upstream &&
50+
test_commit five &&
51+
test_must_fail git push parent2
52+
'
53+
54+
test_done

0 commit comments

Comments
 (0)