Skip to content

Commit 533e8af

Browse files
committed
Merge branch 'il/push-set-upstream'
* il/push-set-upstream: Add push --set-upstream Conflicts: transport.c
2 parents 0877510 + e9fcd1e commit 533e8af

File tree

5 files changed

+136
-1
lines changed

5 files changed

+136
-1
lines changed

Documentation/git-push.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SYNOPSIS
1010
--------
1111
[verse]
1212
'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
13-
[--repo=<repository>] [-f | --force] [-v | --verbose]
13+
[--repo=<repository>] [-f | --force] [-v | --verbose] [-u | --set-upstream]
1414
[<repository> <refspec>...]
1515

1616
DESCRIPTION
@@ -122,6 +122,13 @@ nor in any Push line of the corresponding remotes file---see below).
122122
the name "origin" is used. For this latter case, this option
123123
can be used to override the name "origin". In other words,
124124
the difference between these two commands
125+
126+
-u::
127+
--set-upstream::
128+
For every branch that is up to date or successfully pushed, add
129+
upstream (tracking) reference, used by argument-less
130+
linkgit:git-pull[1] and other commands. For more information,
131+
see 'branch.<name>.merge' in linkgit:git-config[1].
125132
+
126133
--------------------------
127134
git push public #1

builtin-push.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
218218
OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
219219
OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
220220
OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
221+
OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
222+
TRANSPORT_PUSH_SET_UPSTREAM),
221223
OPT_END()
222224
};
223225

t/t5523-push-upstream.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/sh
2+
3+
test_description='push with --set-upstream'
4+
. ./test-lib.sh
5+
6+
test_expect_success 'setup bare parent' '
7+
git init --bare parent &&
8+
git remote add upstream parent
9+
'
10+
11+
test_expect_success 'setup local commit' '
12+
echo content >file &&
13+
git add file &&
14+
git commit -m one
15+
'
16+
17+
check_config() {
18+
(echo $2; echo $3) >expect.$1
19+
(git config branch.$1.remote
20+
git config branch.$1.merge) >actual.$1
21+
test_cmp expect.$1 actual.$1
22+
}
23+
24+
test_expect_success 'push -u master:master' '
25+
git push -u upstream master:master &&
26+
check_config master upstream refs/heads/master
27+
'
28+
29+
test_expect_success 'push -u master:other' '
30+
git push -u upstream master:other &&
31+
check_config master upstream refs/heads/other
32+
'
33+
34+
test_expect_success 'push -u --dry-run master:otherX' '
35+
git push -u --dry-run upstream master:otherX &&
36+
check_config master upstream refs/heads/other
37+
'
38+
39+
test_expect_success 'push -u master2:master2' '
40+
git branch master2 &&
41+
git push -u upstream master2:master2 &&
42+
check_config master2 upstream refs/heads/master2
43+
'
44+
45+
test_expect_success 'push -u master2:other2' '
46+
git push -u upstream master2:other2 &&
47+
check_config master2 upstream refs/heads/other2
48+
'
49+
50+
test_expect_success 'push -u :master2' '
51+
git push -u upstream :master2 &&
52+
check_config master2 upstream refs/heads/other2
53+
'
54+
55+
test_expect_success 'push -u --all' '
56+
git branch all1 &&
57+
git branch all2 &&
58+
git push -u --all &&
59+
check_config all1 upstream refs/heads/all1 &&
60+
check_config all2 upstream refs/heads/all2
61+
'
62+
63+
test_expect_success 'push -u HEAD' '
64+
git checkout -b headbranch &&
65+
git push -u upstream HEAD &&
66+
check_config headbranch upstream refs/heads/headbranch
67+
'
68+
69+
test_done

transport.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "bundle.h"
99
#include "dir.h"
1010
#include "refs.h"
11+
#include "branch.h"
1112

1213
/* rsync support */
1314

@@ -135,6 +136,53 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
135136
}
136137
}
137138

139+
static void set_upstreams(struct transport *transport, struct ref *refs,
140+
int pretend)
141+
{
142+
struct ref *ref;
143+
for (ref = refs; ref; ref = ref->next) {
144+
const char *localname;
145+
const char *tmp;
146+
const char *remotename;
147+
unsigned char sha[20];
148+
int flag = 0;
149+
/*
150+
* Check suitability for tracking. Must be successful /
151+
* already up-to-date ref create/modify (not delete).
152+
*/
153+
if (ref->status != REF_STATUS_OK &&
154+
ref->status != REF_STATUS_UPTODATE)
155+
continue;
156+
if (!ref->peer_ref)
157+
continue;
158+
if (!ref->new_sha1 || is_null_sha1(ref->new_sha1))
159+
continue;
160+
161+
/* Follow symbolic refs (mainly for HEAD). */
162+
localname = ref->peer_ref->name;
163+
remotename = ref->name;
164+
tmp = resolve_ref(localname, sha, 1, &flag);
165+
if (tmp && flag & REF_ISSYMREF &&
166+
!prefixcmp(tmp, "refs/heads/"))
167+
localname = tmp;
168+
169+
/* Both source and destination must be local branches. */
170+
if (!localname || prefixcmp(localname, "refs/heads/"))
171+
continue;
172+
if (!remotename || prefixcmp(remotename, "refs/heads/"))
173+
continue;
174+
175+
if (!pretend)
176+
install_branch_config(BRANCH_CONFIG_VERBOSE,
177+
localname + 11, transport->remote->name,
178+
remotename);
179+
else
180+
printf("Would set upstream of '%s' to '%s' of '%s'\n",
181+
localname + 11, remotename + 11,
182+
transport->remote->name);
183+
}
184+
}
185+
138186
static const char *rsync_url(const char *url)
139187
{
140188
return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
@@ -974,6 +1022,10 @@ int transport_push(struct transport *transport,
9741022
verify_remote_names(refspec_nr, refspec);
9751023

9761024
if (transport->push) {
1025+
/* Maybe FIXME. But no important transport uses this case. */
1026+
if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
1027+
die("This transport does not support using --set-upstream");
1028+
9771029
return transport->push(transport, refspec_nr, refspec, flags);
9781030
} else if (transport->push_refs) {
9791031
struct ref *remote_refs =
@@ -983,6 +1035,7 @@ int transport_push(struct transport *transport,
9831035
int verbose = flags & TRANSPORT_PUSH_VERBOSE;
9841036
int quiet = flags & TRANSPORT_PUSH_QUIET;
9851037
int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
1038+
int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
9861039
int ret, err;
9871040

9881041
if (flags & TRANSPORT_PUSH_ALL)
@@ -1009,6 +1062,9 @@ int transport_push(struct transport *transport,
10091062
verbose | porcelain, porcelain,
10101063
nonfastforward);
10111064

1065+
if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
1066+
set_upstreams(transport, remote_refs, pretend);
1067+
10121068
if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
10131069
struct ref *ref;
10141070
for (ref = remote_refs; ref; ref = ref->next)

transport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ struct transport {
9191
#define TRANSPORT_PUSH_VERBOSE 16
9292
#define TRANSPORT_PUSH_PORCELAIN 32
9393
#define TRANSPORT_PUSH_QUIET 64
94+
#define TRANSPORT_PUSH_SET_UPSTREAM 128
9495

9596
/* Returns a transport suitable for the url */
9697
struct transport *transport_get(struct remote *, const char *);

0 commit comments

Comments
 (0)