Skip to content

Commit ed2b182

Browse files
artagnongitster
authored andcommitted
push: change simple to accommodate triangular workflows
When remote.pushdefault or branch.<name>.pushremote is set to a remote that is different from where you usually fetch from (i.e. a triangular workflow), master@{u} != origin, and push.default is set to `upstream` or `simple` would fail with this error: $ git push fatal: You are pushing to remote 'origin', which is not the upstream of your current branch 'master', without telling me what to push to update which remote branch. The very name of "upstream" indicates that it is only suitable for use in central workflows; let us not even attempt to give it a new meaning in triangular workflows, and error out as before. However, the `simple` does not have to share this error. It is poised to be the default for Git 2.0, and we would like it to do something sensible in triangular workflows. Redefine "simple" as "safer upstream" for centralized workflow as before, but work as "current" for triangular workflow. We may want to make it "safer current", but that is a separate issue. Reported-by: Leandro Lucarella <[email protected]> Signed-off-by: Ramkumar Ramachandra <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 87a70e4 commit ed2b182

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

Documentation/config.txt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,9 +1848,13 @@ push.default::
18481848
pushing to the same repository you would normally pull from
18491849
(i.e. central workflow).
18501850

1851-
* `simple` - like `upstream`, but refuses to push if the upstream
1852-
branch's name is different from the local one. This is the safest
1853-
option and is well-suited for beginners.
1851+
* `simple` - in centralized workflow, work like `upstream` with an
1852+
added safety to refuse to push if the upstream branch's name is
1853+
different from the local one.
1854+
+
1855+
When pushing to a remote that is different from the remote you normally
1856+
pull from, work as `current`. This is the safest option and is suited
1857+
for beginners.
18541858
+
18551859
This mode will become the default in Git 2.0.
18561860

builtin/push.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,11 @@ static const char message_detached_head_die[] =
120120
"\n"
121121
" git push %s HEAD:<name-of-remote-branch>\n");
122122

123-
static void setup_push_upstream(struct remote *remote, int simple)
123+
static void setup_push_upstream(struct remote *remote, struct branch *branch,
124+
int triangular)
124125
{
125126
struct strbuf refspec = STRBUF_INIT;
126-
struct branch *branch = branch_get(NULL);
127+
127128
if (!branch)
128129
die(_(message_detached_head_die), remote->name);
129130
if (!branch->merge_nr || !branch->merge || !branch->remote_name)
@@ -137,18 +138,29 @@ static void setup_push_upstream(struct remote *remote, int simple)
137138
if (branch->merge_nr != 1)
138139
die(_("The current branch %s has multiple upstream branches, "
139140
"refusing to push."), branch->name);
140-
if (strcmp(branch->remote_name, remote->name))
141+
if (triangular)
141142
die(_("You are pushing to remote '%s', which is not the upstream of\n"
142143
"your current branch '%s', without telling me what to push\n"
143144
"to update which remote branch."),
144145
remote->name, branch->name);
145-
if (simple && strcmp(branch->refname, branch->merge[0]->src))
146-
die_push_simple(branch, remote);
146+
147+
if (push_default == PUSH_DEFAULT_SIMPLE) {
148+
/* Additional safety */
149+
if (strcmp(branch->refname, branch->merge[0]->src))
150+
die_push_simple(branch, remote);
151+
}
147152

148153
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
149154
add_refspec(refspec.buf);
150155
}
151156

157+
static void setup_push_current(struct remote *remote, struct branch *branch)
158+
{
159+
if (!branch)
160+
die(_(message_detached_head_die), remote->name);
161+
add_refspec(branch->name);
162+
}
163+
152164
static char warn_unspecified_push_default_msg[] =
153165
N_("push.default is unset; its implicit value is changing in\n"
154166
"Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -173,9 +185,16 @@ static void warn_unspecified_push_default_configuration(void)
173185
warning("%s\n", _(warn_unspecified_push_default_msg));
174186
}
175187

188+
static int is_workflow_triangular(struct remote *remote)
189+
{
190+
struct remote *fetch_remote = remote_get(NULL);
191+
return (fetch_remote && fetch_remote != remote);
192+
}
193+
176194
static void setup_default_push_refspecs(struct remote *remote)
177195
{
178-
struct branch *branch;
196+
struct branch *branch = branch_get(NULL);
197+
int triangular = is_workflow_triangular(remote);
179198

180199
switch (push_default) {
181200
default:
@@ -188,18 +207,18 @@ static void setup_default_push_refspecs(struct remote *remote)
188207
break;
189208

190209
case PUSH_DEFAULT_SIMPLE:
191-
setup_push_upstream(remote, 1);
210+
if (triangular)
211+
setup_push_current(remote, branch);
212+
else
213+
setup_push_upstream(remote, branch, triangular);
192214
break;
193215

194216
case PUSH_DEFAULT_UPSTREAM:
195-
setup_push_upstream(remote, 0);
217+
setup_push_upstream(remote, branch, triangular);
196218
break;
197219

198220
case PUSH_DEFAULT_CURRENT:
199-
branch = branch_get(NULL);
200-
if (!branch)
201-
die(_(message_detached_head_die), remote->name);
202-
add_refspec(branch->name);
221+
setup_push_current(remote, branch);
203222
break;
204223

205224
case PUSH_DEFAULT_NOTHING:

0 commit comments

Comments
 (0)