]> git.ipfire.org Git - thirdparty/git.git/blame - branch.c
Eighth batch for 2.8
[thirdparty/git.git] / branch.c
CommitLineData
303d1d0b 1#include "git-compat-util.h"
e496c003
DB
2#include "cache.h"
3#include "branch.h"
4#include "refs.h"
5#include "remote.h"
6#include "commit.h"
ac6c561b 7#include "worktree.h"
e496c003
DB
8
9struct tracking {
10 struct refspec spec;
11 char *src;
12 const char *remote;
13 int matches;
14};
15
16static int find_tracked_branch(struct remote *remote, void *priv)
17{
18 struct tracking *tracking = priv;
19
20 if (!remote_find_tracking(remote, &tracking->spec)) {
21 if (++tracking->matches == 1) {
22 tracking->src = tracking->spec.src;
23 tracking->remote = remote->name;
24 } else {
25 free(tracking->spec.src);
26 if (tracking->src) {
27 free(tracking->src);
28 tracking->src = NULL;
29 }
30 }
31 tracking->spec.src = NULL;
32 }
33
34 return 0;
35}
36
a9f2c136 37static int should_setup_rebase(const char *origin)
c998ae9b
DS
38{
39 switch (autorebase) {
40 case AUTOREBASE_NEVER:
41 return 0;
42 case AUTOREBASE_LOCAL:
a9f2c136 43 return origin == NULL;
c998ae9b 44 case AUTOREBASE_REMOTE:
a9f2c136 45 return origin != NULL;
c998ae9b
DS
46 case AUTOREBASE_ALWAYS:
47 return 1;
48 }
49 return 0;
50}
51
a9f2c136
JH
52void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
53{
cf4fff57 54 const char *shortname = NULL;
a9f2c136
JH
55 struct strbuf key = STRBUF_INIT;
56 int rebasing = should_setup_rebase(origin);
57
cf4fff57 58 if (skip_prefix(remote, "refs/heads/", &shortname)
85e2233f
MM
59 && !strcmp(local, shortname)
60 && !origin) {
bc554df8 61 warning(_("Not setting branch %s as its own upstream."),
85e2233f
MM
62 local);
63 return;
64 }
65
a9f2c136
JH
66 strbuf_addf(&key, "branch.%s.remote", local);
67 git_config_set(key.buf, origin ? origin : ".");
68
69 strbuf_reset(&key);
70 strbuf_addf(&key, "branch.%s.merge", local);
71 git_config_set(key.buf, remote);
72
73 if (rebasing) {
74 strbuf_reset(&key);
75 strbuf_addf(&key, "branch.%s.rebase", local);
76 git_config_set(key.buf, "true");
77 }
d53a3503 78 strbuf_release(&key);
a9f2c136 79
72f60083 80 if (flag & BRANCH_CONFIG_VERBOSE) {
1d9aaed2 81 if (shortname) {
9fe0cf3a
A
82 if (origin)
83 printf_ln(rebasing ?
84 _("Branch %s set up to track remote branch %s from %s by rebasing.") :
85 _("Branch %s set up to track remote branch %s from %s."),
86 local, shortname, origin);
87 else
88 printf_ln(rebasing ?
89 _("Branch %s set up to track local branch %s by rebasing.") :
90 _("Branch %s set up to track local branch %s."),
91 local, shortname);
92 } else {
93 if (origin)
94 printf_ln(rebasing ?
95 _("Branch %s set up to track remote ref %s by rebasing.") :
96 _("Branch %s set up to track remote ref %s."),
97 local, remote);
98 else
99 printf_ln(rebasing ?
100 _("Branch %s set up to track local ref %s by rebasing.") :
101 _("Branch %s set up to track local ref %s."),
102 local, remote);
103 }
72f60083 104 }
a9f2c136
JH
105}
106
e496c003
DB
107/*
108 * This is called when new_ref is branched off of orig_ref, and tries
109 * to infer the settings for branch.<new_ref>.{remote,merge} from the
110 * config.
111 */
9ed36cfa 112static int setup_tracking(const char *new_ref, const char *orig_ref,
f9a482e6 113 enum branch_track track, int quiet)
e496c003 114{
e496c003 115 struct tracking tracking;
f9a482e6 116 int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
e496c003 117
e496c003
DB
118 memset(&tracking, 0, sizeof(tracking));
119 tracking.spec.dst = (char *)orig_ref;
9ed36cfa 120 if (for_each_remote(find_tracked_branch, &tracking))
e496c003
DB
121 return 1;
122
9ed36cfa
JS
123 if (!tracking.matches)
124 switch (track) {
125 case BRANCH_TRACK_ALWAYS:
126 case BRANCH_TRACK_EXPLICIT:
4fc50066 127 case BRANCH_TRACK_OVERRIDE:
9ed36cfa
JS
128 break;
129 default:
130 return 1;
131 }
132
e496c003 133 if (tracking.matches > 1)
bc554df8 134 return error(_("Not tracking: ambiguous information for ref %s"),
e496c003
DB
135 orig_ref);
136
f9a482e6 137 install_branch_config(config_flags, new_ref, tracking.remote,
a9f2c136 138 tracking.src ? tracking.src : orig_ref);
e496c003 139
a9f2c136 140 free(tracking.src);
e496c003
DB
141 return 0;
142}
143
6f9a3321
JH
144int read_branch_desc(struct strbuf *buf, const char *branch_name)
145{
540b0f49 146 char *v = NULL;
6f9a3321
JH
147 struct strbuf name = STRBUF_INIT;
148 strbuf_addf(&name, "branch.%s.description", branch_name);
540b0f49
TA
149 if (git_config_get_string(name.buf, &v)) {
150 strbuf_release(&name);
151 return -1;
152 }
153 strbuf_addstr(buf, v);
154 free(v);
6f9a3321
JH
155 strbuf_release(&name);
156 return 0;
157}
158
fa799376
JH
159int validate_new_branchname(const char *name, struct strbuf *ref,
160 int force, int attr_only)
55c4a673 161{
55c4a673 162 if (strbuf_check_branch_ref(ref, name))
bc554df8 163 die(_("'%s' is not a valid branch name."), name);
55c4a673
CI
164
165 if (!ref_exists(ref->buf))
166 return 0;
fa799376 167 else if (!force && !attr_only)
bc554df8 168 die(_("A branch named '%s' already exists."), ref->buf + strlen("refs/heads/"));
55c4a673 169
fa799376
JH
170 if (!attr_only) {
171 const char *head;
172 unsigned char sha1[20];
55c4a673 173
7695d118 174 head = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
fa799376 175 if (!is_bare_repository() && head && !strcmp(head, ref->buf))
bc554df8 176 die(_("Cannot force update the current branch."));
fa799376 177 }
55c4a673
CI
178 return 1;
179}
180
41c21f22
JH
181static int check_tracking_branch(struct remote *remote, void *cb_data)
182{
183 char *tracking_branch = cb_data;
184 struct refspec query;
185 memset(&query, 0, sizeof(struct refspec));
186 query.dst = tracking_branch;
1d7358c5 187 return !remote_find_tracking(remote, &query);
41c21f22
JH
188}
189
190static int validate_remote_tracking_branch(char *ref)
191{
192 return !for_each_remote(check_tracking_branch, ref);
193}
194
e2b6aa5f 195static const char upstream_not_branch[] =
1a15d00b 196N_("Cannot setup tracking information; starting point '%s' is not a branch.");
a5e91c72 197static const char upstream_missing[] =
caa2036b
JK
198N_("the requested upstream branch '%s' does not exist");
199static const char upstream_advice[] =
200N_("\n"
201"If you are planning on basing your work on an upstream\n"
202"branch that already exists at the remote, you may need to\n"
203"run \"git fetch\" to retrieve it.\n"
204"\n"
205"If you are planning to push out a new local branch that\n"
206"will track its remote counterpart, you may want to use\n"
207"\"git push -u\" to set the upstream config as you push.");
e2b6aa5f 208
e496c003
DB
209void create_branch(const char *head,
210 const char *name, const char *start_name,
39bd6f72 211 int force, int reflog, int clobber_head,
f9a482e6 212 int quiet, enum branch_track track)
e496c003 213{
e496c003
DB
214 struct commit *commit;
215 unsigned char sha1[20];
8415d5c7
JH
216 char *real_ref, msg[PATH_MAX + 20];
217 struct strbuf ref = STRBUF_INIT;
e496c003 218 int forcing = 0;
4fc50066
IL
219 int dont_change_ref = 0;
220 int explicit_tracking = 0;
221
222 if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
223 explicit_tracking = 1;
e496c003 224
fa799376 225 if (validate_new_branchname(name, &ref, force,
39bd6f72
JN
226 track == BRANCH_TRACK_OVERRIDE ||
227 clobber_head)) {
55c4a673 228 if (!force)
4fc50066 229 dont_change_ref = 1;
55c4a673
CI
230 else
231 forcing = 1;
e496c003
DB
232 }
233
234 real_ref = NULL;
a5e91c72 235 if (get_sha1(start_name, sha1)) {
caa2036b
JK
236 if (explicit_tracking) {
237 if (advice_set_upstream_failure) {
238 error(_(upstream_missing), start_name);
239 advise(_(upstream_advice));
240 exit(1);
241 }
1a15d00b 242 die(_(upstream_missing), start_name);
caa2036b 243 }
bc554df8 244 die(_("Not a valid object name: '%s'."), start_name);
a5e91c72 245 }
e496c003
DB
246
247 switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
248 case 0:
249 /* Not branching from any existing branch */
4fc50066 250 if (explicit_tracking)
1a15d00b 251 die(_(upstream_not_branch), start_name);
e496c003
DB
252 break;
253 case 1:
21b5b1e8 254 /* Unique completion -- good, only if it is a real branch */
59556548 255 if (!starts_with(real_ref, "refs/heads/") &&
41c21f22 256 validate_remote_tracking_branch(real_ref)) {
21b5b1e8 257 if (explicit_tracking)
1a15d00b 258 die(_(upstream_not_branch), start_name);
21b5b1e8
JH
259 else
260 real_ref = NULL;
261 }
e496c003
DB
262 break;
263 default:
bc554df8 264 die(_("Ambiguous object name: '%s'."), start_name);
e496c003
DB
265 break;
266 }
267
268 if ((commit = lookup_commit_reference(sha1)) == NULL)
bc554df8 269 die(_("Not a valid branch point: '%s'."), start_name);
ed1c9977 270 hashcpy(sha1, commit->object.oid.hash);
e496c003 271
e496c003 272 if (forcing)
da288e25 273 snprintf(msg, sizeof msg, "branch: Reset to %s",
e496c003 274 start_name);
4fc50066 275 else if (!dont_change_ref)
e496c003
DB
276 snprintf(msg, sizeof msg, "branch: Created from %s",
277 start_name);
278
d43f990f
RS
279 if (reflog)
280 log_all_ref_updates = 1;
281
282 if (!dont_change_ref) {
283 struct ref_transaction *transaction;
284 struct strbuf err = STRBUF_INIT;
285
286 transaction = ref_transaction_begin(&err);
287 if (!transaction ||
1d147bdf
MH
288 ref_transaction_update(transaction, ref.buf,
289 sha1, forcing ? NULL : null_sha1,
290 0, msg, &err) ||
db7516ab 291 ref_transaction_commit(transaction, &err))
d43f990f
RS
292 die("%s", err.buf);
293 ref_transaction_free(transaction);
294 strbuf_release(&err);
295 }
296
e496c003 297 if (real_ref && track)
82a0672f 298 setup_tracking(ref.buf + 11, real_ref, track, quiet);
e496c003 299
8415d5c7 300 strbuf_release(&ref);
9ed36cfa 301 free(real_ref);
e496c003 302}
c369e7b8
DB
303
304void remove_branch_state(void)
305{
f932729c
JK
306 unlink(git_path_cherry_pick_head());
307 unlink(git_path_revert_head());
308 unlink(git_path_merge_head());
309 unlink(git_path_merge_rr());
310 unlink(git_path_merge_msg());
311 unlink(git_path_merge_mode());
312 unlink(git_path_squash_msg());
c369e7b8 313}
ed89f84b 314
41af6565
DT
315void die_if_checked_out(const char *branch)
316{
317 char *existing;
318
319 existing = find_shared_symref("HEAD", branch);
320 if (existing) {
321 skip_prefix(branch, "refs/heads/", &branch);
322 die(_("'%s' is already checked out at '%s'"), branch, existing);
323 }
ed89f84b 324}