@matheusbsbs / matheus-bagliano / commits / e9fcd1e212
Fork 0

Add push --set-upstream

Frequent complaint is lack of easy way to set up upstream (tracking) references for git pull to work as part of push command. So add switch --set-upstream (-u) to do just that. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ilari Liusvaara committed Jan 16, 2010 at 23:45 UTC e9fcd1e2121100d43d2d212eb6c6f1fc82aade1d
5 files changed +136 -1
Documentation/git-push.txt
+8 -1
@@ -10,7 +10,7 @@ SYNOPSIS
10 --------
11 [verse]
12 '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]
14 [<repository> <refspec>...]
15
16 DESCRIPTION
@@ -122,6 +122,13 @@ nor in any Push line of the corresponding remotes file---see below).
122 the name "origin" is used. For this latter case, this option
123 can be used to override the name "origin". In other words,
124 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].
132 +
133 --------------------------
134 git push public #1
builtin-push.c
+2
@@ -218,6 +218,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
218 OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
219 OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
220 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),
223 OPT_END()
224 };
225
t/t5523-push-upstream.sh new
+69
@@ -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
+56
@@ -8,6 +8,7 @@
8 #include "bundle.h"
9 #include "dir.h"
10 #include "refs.h"
11 +#include "branch.h"
12
13 /* rsync support */
14
@@ -135,6 +136,53 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
136 }
137 }
138
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 +
186 static const char *rsync_url(const char *url)
187 {
188 return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
@@ -974,6 +1022,10 @@ int transport_push(struct transport *transport,
1022 verify_remote_names(refspec_nr, refspec);
1023
1024 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 +
1029 return transport->push(transport, refspec_nr, refspec, flags);
1030 } else if (transport->push_refs) {
1031 struct ref *remote_refs =
@@ -983,6 +1035,7 @@ int transport_push(struct transport *transport,
1035 int verbose = flags & TRANSPORT_PUSH_VERBOSE;
1036 int quiet = flags & TRANSPORT_PUSH_QUIET;
1037 int porcelain = flags & TRANSPORT_PUSH_PORCELAIN;
1038 + int pretend = flags & TRANSPORT_PUSH_DRY_RUN;
1039 int ret;
1040
1041 if (flags & TRANSPORT_PUSH_ALL)
@@ -1002,6 +1055,9 @@ int transport_push(struct transport *transport,
1055 verbose | porcelain, porcelain,
1056 nonfastforward);
1057
1058 + if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
1059 + set_upstreams(transport, remote_refs, pretend);
1060 +
1061 if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
1062 struct ref *ref;
1063 for (ref = remote_refs; ref; ref = ref->next)
transport.h
+1
@@ -91,6 +91,7 @@ struct transport {
91 #define TRANSPORT_PUSH_VERBOSE 16
92 #define TRANSPORT_PUSH_PORCELAIN 32
93 #define TRANSPORT_PUSH_QUIET 64
94 +#define TRANSPORT_PUSH_SET_UPSTREAM 128
95
96 /* Returns a transport suitable for the url */
97 struct transport *transport_get(struct remote *, const char *);