git

Форк
0
/
branch.c 
855 строк · 24.6 Кб
1
#define USE_THE_REPOSITORY_VARIABLE
2

3
#include "git-compat-util.h"
4
#include "advice.h"
5
#include "config.h"
6
#include "branch.h"
7
#include "environment.h"
8
#include "gettext.h"
9
#include "hex.h"
10
#include "object-name.h"
11
#include "path.h"
12
#include "refs.h"
13
#include "refspec.h"
14
#include "remote.h"
15
#include "repository.h"
16
#include "sequencer.h"
17
#include "commit.h"
18
#include "worktree.h"
19
#include "submodule-config.h"
20
#include "run-command.h"
21
#include "strmap.h"
22

23
struct tracking {
24
	struct refspec_item spec;
25
	struct string_list *srcs;
26
	const char *remote;
27
	int matches;
28
};
29

30
struct find_tracked_branch_cb {
31
	struct tracking *tracking;
32
	struct string_list ambiguous_remotes;
33
};
34

35
static int find_tracked_branch(struct remote *remote, void *priv)
36
{
37
	struct find_tracked_branch_cb *ftb = priv;
38
	struct tracking *tracking = ftb->tracking;
39

40
	if (!remote_find_tracking(remote, &tracking->spec)) {
41
		switch (++tracking->matches) {
42
		case 1:
43
			string_list_append_nodup(tracking->srcs, tracking->spec.src);
44
			tracking->remote = remote->name;
45
			break;
46
		case 2:
47
			/* there are at least two remotes; backfill the first one */
48
			string_list_append(&ftb->ambiguous_remotes, tracking->remote);
49
			/* fall through */
50
		default:
51
			string_list_append(&ftb->ambiguous_remotes, remote->name);
52
			free(tracking->spec.src);
53
			string_list_clear(tracking->srcs, 0);
54
		break;
55
		}
56
		/* remote_find_tracking() searches by src if present */
57
		tracking->spec.src = NULL;
58
	}
59
	return 0;
60
}
61

62
static int should_setup_rebase(const char *origin)
63
{
64
	switch (autorebase) {
65
	case AUTOREBASE_NEVER:
66
		return 0;
67
	case AUTOREBASE_LOCAL:
68
		return origin == NULL;
69
	case AUTOREBASE_REMOTE:
70
		return origin != NULL;
71
	case AUTOREBASE_ALWAYS:
72
		return 1;
73
	}
74
	return 0;
75
}
76

77
/**
78
 * Install upstream tracking configuration for a branch; specifically, add
79
 * `branch.<name>.remote` and `branch.<name>.merge` entries.
80
 *
81
 * `flag` contains integer flags for options; currently only
82
 * BRANCH_CONFIG_VERBOSE is checked.
83
 *
84
 * `local` is the name of the branch whose configuration we're installing.
85
 *
86
 * `origin` is the name of the remote owning the upstream branches. NULL means
87
 * the upstream branches are local to this repo.
88
 *
89
 * `remotes` is a list of refs that are upstream of local
90
 */
91
static int install_branch_config_multiple_remotes(int flag, const char *local,
92
		const char *origin, struct string_list *remotes)
93
{
94
	const char *shortname = NULL;
95
	struct strbuf key = STRBUF_INIT;
96
	struct string_list_item *item;
97
	int rebasing = should_setup_rebase(origin);
98

99
	if (!remotes->nr)
100
		BUG("must provide at least one remote for branch config");
101
	if (rebasing && remotes->nr > 1)
102
		die(_("cannot inherit upstream tracking configuration of "
103
		      "multiple refs when rebasing is requested"));
104

105
	/*
106
	 * If the new branch is trying to track itself, something has gone
107
	 * wrong. Warn the user and don't proceed any further.
108
	 */
109
	if (!origin)
110
		for_each_string_list_item(item, remotes)
111
			if (skip_prefix(item->string, "refs/heads/", &shortname)
112
			    && !strcmp(local, shortname)) {
113
				warning(_("not setting branch '%s' as its own upstream"),
114
					local);
115
				return 0;
116
			}
117

118
	strbuf_addf(&key, "branch.%s.remote", local);
119
	if (git_config_set_gently(key.buf, origin ? origin : ".") < 0)
120
		goto out_err;
121

122
	strbuf_reset(&key);
123
	strbuf_addf(&key, "branch.%s.merge", local);
124
	/*
125
	 * We want to overwrite any existing config with all the branches in
126
	 * "remotes". Override any existing config, then write our branches. If
127
	 * more than one is provided, use CONFIG_REGEX_NONE to preserve what
128
	 * we've written so far.
129
	 */
130
	if (git_config_set_gently(key.buf, NULL) < 0)
131
		goto out_err;
132
	for_each_string_list_item(item, remotes)
133
		if (git_config_set_multivar_gently(key.buf, item->string, CONFIG_REGEX_NONE, 0) < 0)
134
			goto out_err;
135

136
	if (rebasing) {
137
		strbuf_reset(&key);
138
		strbuf_addf(&key, "branch.%s.rebase", local);
139
		if (git_config_set_gently(key.buf, "true") < 0)
140
			goto out_err;
141
	}
142
	strbuf_release(&key);
143

144
	if (flag & BRANCH_CONFIG_VERBOSE) {
145
		struct strbuf tmp_ref_name = STRBUF_INIT;
146
		struct string_list friendly_ref_names = STRING_LIST_INIT_DUP;
147

148
		for_each_string_list_item(item, remotes) {
149
			shortname = item->string;
150
			skip_prefix(shortname, "refs/heads/", &shortname);
151
			if (origin) {
152
				strbuf_addf(&tmp_ref_name, "%s/%s",
153
					    origin, shortname);
154
				string_list_append_nodup(
155
					&friendly_ref_names,
156
					strbuf_detach(&tmp_ref_name, NULL));
157
			} else {
158
				string_list_append(
159
					&friendly_ref_names, shortname);
160
			}
161
		}
162

163
		if (remotes->nr == 1) {
164
			/*
165
			 * Rebasing is only allowed in the case of a single
166
			 * upstream branch.
167
			 */
168
			printf_ln(rebasing ?
169
				_("branch '%s' set up to track '%s' by rebasing.") :
170
				_("branch '%s' set up to track '%s'."),
171
				local, friendly_ref_names.items[0].string);
172
		} else {
173
			printf_ln(_("branch '%s' set up to track:"), local);
174
			for_each_string_list_item(item, &friendly_ref_names)
175
				printf_ln("  %s", item->string);
176
		}
177

178
		string_list_clear(&friendly_ref_names, 0);
179
	}
180

181
	return 0;
182

183
out_err:
184
	strbuf_release(&key);
185
	error(_("unable to write upstream branch configuration"));
186

187
	advise(_("\nAfter fixing the error cause you may try to fix up\n"
188
		"the remote tracking information by invoking:"));
189
	if (remotes->nr == 1)
190
		advise("  git branch --set-upstream-to=%s%s%s",
191
			origin ? origin : "",
192
			origin ? "/" : "",
193
			remotes->items[0].string);
194
	else {
195
		advise("  git config --add branch.\"%s\".remote %s",
196
			local, origin ? origin : ".");
197
		for_each_string_list_item(item, remotes)
198
			advise("  git config --add branch.\"%s\".merge %s",
199
				local, item->string);
200
	}
201

202
	return -1;
203
}
204

205
int install_branch_config(int flag, const char *local, const char *origin,
206
		const char *remote)
207
{
208
	int ret;
209
	struct string_list remotes = STRING_LIST_INIT_DUP;
210

211
	string_list_append(&remotes, remote);
212
	ret = install_branch_config_multiple_remotes(flag, local, origin, &remotes);
213
	string_list_clear(&remotes, 0);
214
	return ret;
215
}
216

217
static int inherit_tracking(struct tracking *tracking, const char *orig_ref)
218
{
219
	const char *bare_ref;
220
	struct branch *branch;
221
	int i;
222

223
	bare_ref = orig_ref;
224
	skip_prefix(orig_ref, "refs/heads/", &bare_ref);
225

226
	branch = branch_get(bare_ref);
227
	if (!branch->remote_name) {
228
		warning(_("asked to inherit tracking from '%s', but no remote is set"),
229
			bare_ref);
230
		return -1;
231
	}
232

233
	if (branch->merge_nr < 1 || !branch->merge_name || !branch->merge_name[0]) {
234
		warning(_("asked to inherit tracking from '%s', but no merge configuration is set"),
235
			bare_ref);
236
		return -1;
237
	}
238

239
	tracking->remote = branch->remote_name;
240
	for (i = 0; i < branch->merge_nr; i++)
241
		string_list_append(tracking->srcs, branch->merge_name[i]);
242
	return 0;
243
}
244

245
/*
246
 * Used internally to set the branch.<new_ref>.{remote,merge} config
247
 * settings so that branch 'new_ref' tracks 'orig_ref'. Unlike
248
 * dwim_and_setup_tracking(), this does not do DWIM, i.e. "origin/main"
249
 * will not be expanded to "refs/remotes/origin/main", so it is not safe
250
 * for 'orig_ref' to be raw user input.
251
 */
252
static void setup_tracking(const char *new_ref, const char *orig_ref,
253
			   enum branch_track track, int quiet)
254
{
255
	struct tracking tracking;
256
	struct string_list tracking_srcs = STRING_LIST_INIT_DUP;
257
	int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
258
	struct find_tracked_branch_cb ftb_cb = {
259
		.tracking = &tracking,
260
		.ambiguous_remotes = STRING_LIST_INIT_DUP,
261
	};
262

263
	if (!track)
264
		BUG("asked to set up tracking, but tracking is disallowed");
265

266
	memset(&tracking, 0, sizeof(tracking));
267
	tracking.spec.dst = (char *)orig_ref;
268
	tracking.srcs = &tracking_srcs;
269
	if (track != BRANCH_TRACK_INHERIT)
270
		for_each_remote(find_tracked_branch, &ftb_cb);
271
	else if (inherit_tracking(&tracking, orig_ref))
272
		goto cleanup;
273

274
	if (!tracking.matches)
275
		switch (track) {
276
		/* If ref is not remote, still use local */
277
		case BRANCH_TRACK_ALWAYS:
278
		case BRANCH_TRACK_EXPLICIT:
279
		case BRANCH_TRACK_OVERRIDE:
280
		/* Remote matches not evaluated */
281
		case BRANCH_TRACK_INHERIT:
282
			break;
283
		/* Otherwise, if no remote don't track */
284
		default:
285
			goto cleanup;
286
		}
287

288
	/*
289
	 * This check does not apply to BRANCH_TRACK_INHERIT;
290
	 * that supports multiple entries in tracking_srcs but
291
	 * leaves tracking.matches at 0.
292
	 */
293
	if (tracking.matches > 1) {
294
		int status = die_message(_("not tracking: ambiguous information for ref '%s'"),
295
					    orig_ref);
296
		if (advice_enabled(ADVICE_AMBIGUOUS_FETCH_REFSPEC)) {
297
			struct strbuf remotes_advice = STRBUF_INIT;
298
			struct string_list_item *item;
299

300
			for_each_string_list_item(item, &ftb_cb.ambiguous_remotes)
301
				/*
302
				 * TRANSLATORS: This is a line listing a remote with duplicate
303
				 * refspecs in the advice message below. For RTL languages you'll
304
				 * probably want to swap the "%s" and leading "  " space around.
305
				 */
306
				strbuf_addf(&remotes_advice, _("  %s\n"), item->string);
307

308
			/*
309
			 * TRANSLATORS: The second argument is a \n-delimited list of
310
			 * duplicate refspecs, composed above.
311
			 */
312
			advise(_("There are multiple remotes whose fetch refspecs map to the remote\n"
313
				 "tracking ref '%s':\n"
314
				 "%s"
315
				 "\n"
316
				 "This is typically a configuration error.\n"
317
				 "\n"
318
				 "To support setting up tracking branches, ensure that\n"
319
				 "different remotes' fetch refspecs map into different\n"
320
				 "tracking namespaces."), orig_ref,
321
			       remotes_advice.buf);
322
			strbuf_release(&remotes_advice);
323
		}
324
		exit(status);
325
	}
326

327
	if (track == BRANCH_TRACK_SIMPLE) {
328
		/*
329
		 * Only track if remote branch name matches.
330
		 * Reaching into items[0].string is safe because
331
		 * we know there is at least one and not more than
332
		 * one entry (because only BRANCH_TRACK_INHERIT can
333
		 * produce more than one entry).
334
		 */
335
		const char *tracked_branch;
336
		if (!skip_prefix(tracking.srcs->items[0].string,
337
				 "refs/heads/", &tracked_branch) ||
338
		    strcmp(tracked_branch, new_ref))
339
			goto cleanup;
340
	}
341

342
	if (tracking.srcs->nr < 1)
343
		string_list_append(tracking.srcs, orig_ref);
344
	if (install_branch_config_multiple_remotes(config_flags, new_ref,
345
				tracking.remote, tracking.srcs) < 0)
346
		exit(1);
347

348
cleanup:
349
	string_list_clear(&tracking_srcs, 0);
350
	string_list_clear(&ftb_cb.ambiguous_remotes, 0);
351
}
352

353
int read_branch_desc(struct strbuf *buf, const char *branch_name)
354
{
355
	char *v = NULL;
356
	struct strbuf name = STRBUF_INIT;
357
	strbuf_addf(&name, "branch.%s.description", branch_name);
358
	if (git_config_get_string(name.buf, &v)) {
359
		strbuf_release(&name);
360
		return -1;
361
	}
362
	strbuf_addstr(buf, v);
363
	free(v);
364
	strbuf_release(&name);
365
	return 0;
366
}
367

368
/*
369
 * Check if 'name' can be a valid name for a branch; die otherwise.
370
 * Return 1 if the named branch already exists; return 0 otherwise.
371
 * Fill ref with the full refname for the branch.
372
 */
373
int validate_branchname(const char *name, struct strbuf *ref)
374
{
375
	if (strbuf_check_branch_ref(ref, name)) {
376
		int code = die_message(_("'%s' is not a valid branch name"), name);
377
		advise_if_enabled(ADVICE_REF_SYNTAX,
378
				  _("See `man git check-ref-format`"));
379
		exit(code);
380
	}
381

382
	return refs_ref_exists(get_main_ref_store(the_repository), ref->buf);
383
}
384

385
static int initialized_checked_out_branches;
386
static struct strmap current_checked_out_branches = STRMAP_INIT;
387

388
static void prepare_checked_out_branches(void)
389
{
390
	int i = 0;
391
	struct worktree **worktrees;
392

393
	if (initialized_checked_out_branches)
394
		return;
395
	initialized_checked_out_branches = 1;
396

397
	worktrees = get_worktrees();
398

399
	while (worktrees[i]) {
400
		char *old;
401
		struct wt_status_state state = { 0 };
402
		struct worktree *wt = worktrees[i++];
403
		struct string_list update_refs = STRING_LIST_INIT_DUP;
404

405
		if (wt->is_bare)
406
			continue;
407

408
		if (wt->head_ref) {
409
			old = strmap_put(&current_checked_out_branches,
410
					 wt->head_ref,
411
					 xstrdup(wt->path));
412
			free(old);
413
		}
414

415
		if (wt_status_check_rebase(wt, &state) &&
416
		    (state.rebase_in_progress || state.rebase_interactive_in_progress) &&
417
		    state.branch) {
418
			struct strbuf ref = STRBUF_INIT;
419
			strbuf_addf(&ref, "refs/heads/%s", state.branch);
420
			old = strmap_put(&current_checked_out_branches,
421
					 ref.buf,
422
					 xstrdup(wt->path));
423
			free(old);
424
			strbuf_release(&ref);
425
		}
426
		wt_status_state_free_buffers(&state);
427

428
		if (wt_status_check_bisect(wt, &state) &&
429
		    state.bisecting_from) {
430
			struct strbuf ref = STRBUF_INIT;
431
			strbuf_addf(&ref, "refs/heads/%s", state.bisecting_from);
432
			old = strmap_put(&current_checked_out_branches,
433
					 ref.buf,
434
					 xstrdup(wt->path));
435
			free(old);
436
			strbuf_release(&ref);
437
		}
438
		wt_status_state_free_buffers(&state);
439

440
		if (!sequencer_get_update_refs_state(get_worktree_git_dir(wt),
441
						     &update_refs)) {
442
			struct string_list_item *item;
443
			for_each_string_list_item(item, &update_refs) {
444
				old = strmap_put(&current_checked_out_branches,
445
						 item->string,
446
						 xstrdup(wt->path));
447
				free(old);
448
			}
449
			string_list_clear(&update_refs, 1);
450
		}
451
	}
452

453
	free_worktrees(worktrees);
454
}
455

456
const char *branch_checked_out(const char *refname)
457
{
458
	prepare_checked_out_branches();
459
	return strmap_get(&current_checked_out_branches, refname);
460
}
461

462
/*
463
 * Check if a branch 'name' can be created as a new branch; die otherwise.
464
 * 'force' can be used when it is OK for the named branch already exists.
465
 * Return 1 if the named branch already exists; return 0 otherwise.
466
 * Fill ref with the full refname for the branch.
467
 */
468
int validate_new_branchname(const char *name, struct strbuf *ref, int force)
469
{
470
	const char *path;
471
	if (!validate_branchname(name, ref))
472
		return 0;
473

474
	if (!force)
475
		die(_("a branch named '%s' already exists"),
476
		    ref->buf + strlen("refs/heads/"));
477

478
	if ((path = branch_checked_out(ref->buf)))
479
		die(_("cannot force update the branch '%s' "
480
		      "used by worktree at '%s'"),
481
		    ref->buf + strlen("refs/heads/"), path);
482

483
	return 1;
484
}
485

486
static int check_tracking_branch(struct remote *remote, void *cb_data)
487
{
488
	char *tracking_branch = cb_data;
489
	struct refspec_item query;
490
	int res;
491
	memset(&query, 0, sizeof(struct refspec_item));
492
	query.dst = tracking_branch;
493
	res = !remote_find_tracking(remote, &query);
494
	free(query.src);
495
	return res;
496
}
497

498
static int validate_remote_tracking_branch(char *ref)
499
{
500
	return !for_each_remote(check_tracking_branch, ref);
501
}
502

503
static const char upstream_not_branch[] =
504
N_("cannot set up tracking information; starting point '%s' is not a branch");
505
static const char upstream_missing[] =
506
N_("the requested upstream branch '%s' does not exist");
507
static const char upstream_advice[] =
508
N_("\n"
509
"If you are planning on basing your work on an upstream\n"
510
"branch that already exists at the remote, you may need to\n"
511
"run \"git fetch\" to retrieve it.\n"
512
"\n"
513
"If you are planning to push out a new local branch that\n"
514
"will track its remote counterpart, you may want to use\n"
515
"\"git push -u\" to set the upstream config as you push.");
516

517
/**
518
 * DWIMs a user-provided ref to determine the starting point for a
519
 * branch and validates it, where:
520
 *
521
 *   - r is the repository to validate the branch for
522
 *
523
 *   - start_name is the ref that we would like to test. This is
524
 *     expanded with DWIM and assigned to out_real_ref.
525
 *
526
 *   - track is the tracking mode of the new branch. If tracking is
527
 *     explicitly requested, start_name must be a branch (because
528
 *     otherwise start_name cannot be tracked)
529
 *
530
 *   - out_oid is an out parameter containing the object_id of start_name
531
 *
532
 *   - out_real_ref is an out parameter containing the full, 'real' form
533
 *     of start_name e.g. refs/heads/main instead of main
534
 *
535
 */
536
static void dwim_branch_start(struct repository *r, const char *start_name,
537
			   enum branch_track track, char **out_real_ref,
538
			   struct object_id *out_oid)
539
{
540
	struct commit *commit;
541
	struct object_id oid;
542
	char *real_ref;
543
	int explicit_tracking = 0;
544

545
	if (track == BRANCH_TRACK_EXPLICIT || track == BRANCH_TRACK_OVERRIDE)
546
		explicit_tracking = 1;
547

548
	real_ref = NULL;
549
	if (repo_get_oid_mb(r, start_name, &oid)) {
550
		if (explicit_tracking) {
551
			int code = die_message(_(upstream_missing), start_name);
552
			advise_if_enabled(ADVICE_SET_UPSTREAM_FAILURE,
553
					  _(upstream_advice));
554
			exit(code);
555
		}
556
		die(_("not a valid object name: '%s'"), start_name);
557
	}
558

559
	switch (repo_dwim_ref(r, start_name, strlen(start_name), &oid,
560
			      &real_ref, 0)) {
561
	case 0:
562
		/* Not branching from any existing branch */
563
		if (explicit_tracking)
564
			die(_(upstream_not_branch), start_name);
565
		break;
566
	case 1:
567
		/* Unique completion -- good, only if it is a real branch */
568
		if (!starts_with(real_ref, "refs/heads/") &&
569
		    validate_remote_tracking_branch(real_ref)) {
570
			if (explicit_tracking)
571
				die(_(upstream_not_branch), start_name);
572
			else
573
				FREE_AND_NULL(real_ref);
574
		}
575
		break;
576
	default:
577
		die(_("ambiguous object name: '%s'"), start_name);
578
		break;
579
	}
580

581
	if (!(commit = lookup_commit_reference(r, &oid)))
582
		die(_("not a valid branch point: '%s'"), start_name);
583
	if (out_real_ref) {
584
		*out_real_ref = real_ref;
585
		real_ref = NULL;
586
	}
587
	if (out_oid)
588
		oidcpy(out_oid, &commit->object.oid);
589

590
	FREE_AND_NULL(real_ref);
591
}
592

593
void create_branch(struct repository *r,
594
		   const char *name, const char *start_name,
595
		   int force, int clobber_head_ok, int reflog,
596
		   int quiet, enum branch_track track, int dry_run)
597
{
598
	struct object_id oid;
599
	char *real_ref;
600
	struct strbuf ref = STRBUF_INIT;
601
	int forcing = 0;
602
	struct ref_transaction *transaction;
603
	struct strbuf err = STRBUF_INIT;
604
	char *msg;
605

606
	if (track == BRANCH_TRACK_OVERRIDE)
607
		BUG("'track' cannot be BRANCH_TRACK_OVERRIDE. Did you mean to call dwim_and_setup_tracking()?");
608
	if (clobber_head_ok && !force)
609
		BUG("'clobber_head_ok' can only be used with 'force'");
610

611
	if (clobber_head_ok ?
612
			  validate_branchname(name, &ref) :
613
			  validate_new_branchname(name, &ref, force)) {
614
		forcing = 1;
615
	}
616

617
	dwim_branch_start(r, start_name, track, &real_ref, &oid);
618
	if (dry_run)
619
		goto cleanup;
620

621
	if (reflog)
622
		log_all_ref_updates = LOG_REFS_NORMAL;
623

624
	if (forcing)
625
		msg = xstrfmt("branch: Reset to %s", start_name);
626
	else
627
		msg = xstrfmt("branch: Created from %s", start_name);
628
	transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
629
						  &err);
630
	if (!transaction ||
631
		ref_transaction_update(transaction, ref.buf,
632
					&oid, forcing ? NULL : null_oid(),
633
					NULL, NULL, 0, msg, &err) ||
634
		ref_transaction_commit(transaction, &err))
635
		die("%s", err.buf);
636
	ref_transaction_free(transaction);
637
	strbuf_release(&err);
638
	free(msg);
639

640
	if (real_ref && track)
641
		setup_tracking(ref.buf + 11, real_ref, track, quiet);
642

643
cleanup:
644
	strbuf_release(&ref);
645
	free(real_ref);
646
}
647

648
void dwim_and_setup_tracking(struct repository *r, const char *new_ref,
649
			     const char *orig_ref, enum branch_track track,
650
			     int quiet)
651
{
652
	char *real_orig_ref = NULL;
653
	dwim_branch_start(r, orig_ref, track, &real_orig_ref, NULL);
654
	setup_tracking(new_ref, real_orig_ref, track, quiet);
655
	free(real_orig_ref);
656
}
657

658
/**
659
 * Creates a branch in a submodule by calling
660
 * create_branches_recursively() in a child process. The child process
661
 * is necessary because install_branch_config_multiple_remotes() (which
662
 * is called by setup_tracking()) does not support writing configs to
663
 * submodules.
664
 */
665
static int submodule_create_branch(struct repository *r,
666
				   const struct submodule *submodule,
667
				   const char *name, const char *start_oid,
668
				   const char *tracking_name, int force,
669
				   int reflog, int quiet,
670
				   enum branch_track track, int dry_run)
671
{
672
	int ret = 0;
673
	struct child_process child = CHILD_PROCESS_INIT;
674
	struct strbuf child_err = STRBUF_INIT;
675
	struct strbuf out_buf = STRBUF_INIT;
676
	char *out_prefix = xstrfmt("submodule '%s': ", submodule->name);
677
	child.git_cmd = 1;
678
	child.err = -1;
679
	child.stdout_to_stderr = 1;
680

681
	prepare_other_repo_env(&child.env, r->gitdir);
682
	/*
683
	 * submodule_create_branch() is indirectly invoked by "git
684
	 * branch", but we cannot invoke "git branch" in the child
685
	 * process. "git branch" accepts a branch name and start point,
686
	 * where the start point is assumed to provide both the OID
687
	 * (start_oid) and the branch to use for tracking
688
	 * (tracking_name). But when recursing through submodules,
689
	 * start_oid and tracking name need to be specified separately
690
	 * (see create_branches_recursively()).
691
	 */
692
	strvec_pushl(&child.args, "submodule--helper", "create-branch", NULL);
693
	if (dry_run)
694
		strvec_push(&child.args, "--dry-run");
695
	if (force)
696
		strvec_push(&child.args, "--force");
697
	if (quiet)
698
		strvec_push(&child.args, "--quiet");
699
	if (reflog)
700
		strvec_push(&child.args, "--create-reflog");
701

702
	switch (track) {
703
	case BRANCH_TRACK_NEVER:
704
		strvec_push(&child.args, "--no-track");
705
		break;
706
	case BRANCH_TRACK_ALWAYS:
707
	case BRANCH_TRACK_EXPLICIT:
708
		strvec_push(&child.args, "--track=direct");
709
		break;
710
	case BRANCH_TRACK_OVERRIDE:
711
		BUG("BRANCH_TRACK_OVERRIDE cannot be used when creating a branch.");
712
		break;
713
	case BRANCH_TRACK_INHERIT:
714
		strvec_push(&child.args, "--track=inherit");
715
		break;
716
	case BRANCH_TRACK_UNSPECIFIED:
717
		/* Default for "git checkout". Do not pass --track. */
718
	case BRANCH_TRACK_REMOTE:
719
		/* Default for "git branch". Do not pass --track. */
720
	case BRANCH_TRACK_SIMPLE:
721
		/* Config-driven only. Do not pass --track. */
722
		break;
723
	}
724

725
	strvec_pushl(&child.args, name, start_oid, tracking_name, NULL);
726

727
	if ((ret = start_command(&child)))
728
		return ret;
729
	ret = finish_command(&child);
730
	strbuf_read(&child_err, child.err, 0);
731
	strbuf_add_lines(&out_buf, out_prefix, child_err.buf, child_err.len);
732

733
	if (ret)
734
		fprintf(stderr, "%s", out_buf.buf);
735
	else
736
		printf("%s", out_buf.buf);
737

738
	strbuf_release(&child_err);
739
	strbuf_release(&out_buf);
740
	return ret;
741
}
742

743
void create_branches_recursively(struct repository *r, const char *name,
744
				 const char *start_committish,
745
				 const char *tracking_name, int force,
746
				 int reflog, int quiet, enum branch_track track,
747
				 int dry_run)
748
{
749
	int i = 0;
750
	char *branch_point = NULL;
751
	struct object_id super_oid;
752
	struct submodule_entry_list submodule_entry_list;
753

754
	/* Perform dwim on start_committish to get super_oid and branch_point. */
755
	dwim_branch_start(r, start_committish, BRANCH_TRACK_NEVER,
756
			  &branch_point, &super_oid);
757

758
	/*
759
	 * If we were not given an explicit name to track, then assume we are at
760
	 * the top level and, just like the non-recursive case, the tracking
761
	 * name is the branch point.
762
	 */
763
	if (!tracking_name)
764
		tracking_name = branch_point;
765

766
	submodules_of_tree(r, &super_oid, &submodule_entry_list);
767
	/*
768
	 * Before creating any branches, first check that the branch can
769
	 * be created in every submodule.
770
	 */
771
	for (i = 0; i < submodule_entry_list.entry_nr; i++) {
772
		if (!submodule_entry_list.entries[i].repo) {
773
			int code = die_message(
774
				_("submodule '%s': unable to find submodule"),
775
				submodule_entry_list.entries[i].submodule->name);
776
			if (advice_enabled(ADVICE_SUBMODULES_NOT_UPDATED))
777
				advise(_("You may try updating the submodules using 'git checkout --no-recurse-submodules %s && git submodule update --init'"),
778
				       start_committish);
779
			exit(code);
780
		}
781

782
		if (submodule_create_branch(
783
			    submodule_entry_list.entries[i].repo,
784
			    submodule_entry_list.entries[i].submodule, name,
785
			    oid_to_hex(&submodule_entry_list.entries[i]
786
						.name_entry->oid),
787
			    tracking_name, force, reflog, quiet, track, 1))
788
			die(_("submodule '%s': cannot create branch '%s'"),
789
			    submodule_entry_list.entries[i].submodule->name,
790
			    name);
791
	}
792

793
	create_branch(r, name, start_committish, force, 0, reflog, quiet,
794
		      BRANCH_TRACK_NEVER, dry_run);
795
	if (dry_run)
796
		return;
797
	/*
798
	 * NEEDSWORK If tracking was set up in the superproject but not the
799
	 * submodule, users might expect "git branch --recurse-submodules" to
800
	 * fail or give a warning, but this is not yet implemented because it is
801
	 * tedious to determine whether or not tracking was set up in the
802
	 * superproject.
803
	 */
804
	if (track)
805
		setup_tracking(name, tracking_name, track, quiet);
806

807
	for (i = 0; i < submodule_entry_list.entry_nr; i++) {
808
		if (submodule_create_branch(
809
			    submodule_entry_list.entries[i].repo,
810
			    submodule_entry_list.entries[i].submodule, name,
811
			    oid_to_hex(&submodule_entry_list.entries[i]
812
						.name_entry->oid),
813
			    tracking_name, force, reflog, quiet, track, 0))
814
			die(_("submodule '%s': cannot create branch '%s'"),
815
			    submodule_entry_list.entries[i].submodule->name,
816
			    name);
817
		repo_clear(submodule_entry_list.entries[i].repo);
818
	}
819
}
820

821
void remove_merge_branch_state(struct repository *r)
822
{
823
	unlink(git_path_merge_head(r));
824
	unlink(git_path_merge_rr(r));
825
	unlink(git_path_merge_msg(r));
826
	unlink(git_path_merge_mode(r));
827
	refs_delete_ref(get_main_ref_store(r), "", "AUTO_MERGE",
828
			NULL, REF_NO_DEREF);
829
	save_autostash_ref(r, "MERGE_AUTOSTASH");
830
}
831

832
void remove_branch_state(struct repository *r, int verbose)
833
{
834
	sequencer_post_commit_cleanup(r, verbose);
835
	unlink(git_path_squash_msg(r));
836
	remove_merge_branch_state(r);
837
}
838

839
void die_if_checked_out(const char *branch, int ignore_current_worktree)
840
{
841
	struct worktree **worktrees = get_worktrees();
842

843
	for (int i = 0; worktrees[i]; i++) {
844
		if (worktrees[i]->is_current && ignore_current_worktree)
845
			continue;
846

847
		if (is_shared_symref(worktrees[i], "HEAD", branch)) {
848
			skip_prefix(branch, "refs/heads/", &branch);
849
			die(_("'%s' is already used by worktree at '%s'"),
850
				branch, worktrees[i]->path);
851
		}
852
	}
853

854
	free_worktrees(worktrees);
855
}
856

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.