Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2023-12-28 01:52:24 +0300
committerJunio C Hamano <gitster@pobox.com>2023-12-28 01:52:24 +0300
commitf09e74175dfa5b46587dab3c5dcbad16e9586de3 (patch)
tree98626534b7796b0deb7948757fc5ec78b58166b2 /builtin
parent055bb6e9969085777b7fab83e3fee0017654f134 (diff)
parentb23285a921a84c3b83d9aaca31afedf290c59254 (diff)
Merge branch 'jc/checkout-B-branch-in-use'
"git checkout -B <branch> [<start-point>]" allowed a branch that is in use in another worktree to be updated and checked out, which might be a bit unexpected. The rule has been tightened, which is a breaking change. "--ignore-other-worktrees" option is required to unbreak you, if you are used to the current behaviour that "-B" overrides the safety. * jc/checkout-B-branch-in-use: checkout: forbid "-B <branch>" from touching a branch used elsewhere checkout: refactor die_if_checked_out() caller
Diffstat (limited to 'builtin')
-rw-r--r--builtin/checkout.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/builtin/checkout.c b/builtin/checkout.c
index d5c784854f..59cca80dd4 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1518,6 +1518,26 @@ static void die_if_some_operation_in_progress(void)
wt_status_state_free_buffers(&state);
}
+/*
+ * die if attempting to checkout an existing branch that is in use
+ * in another worktree, unless ignore-other-wortrees option is given.
+ * The check is bypassed when the branch is already the current one,
+ * as it will not make things any worse.
+ */
+static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts,
+ const char *full_ref)
+{
+ int flags;
+ char *head_ref;
+
+ if (opts->ignore_other_worktrees)
+ return;
+ head_ref = resolve_refdup("HEAD", 0, NULL, &flags);
+ if (head_ref && (!(flags & REF_ISSYMREF) || strcmp(head_ref, full_ref)))
+ die_if_checked_out(full_ref, 1);
+ free(head_ref);
+}
+
static int checkout_branch(struct checkout_opts *opts,
struct branch_info *new_branch_info)
{
@@ -1578,14 +1598,15 @@ static int checkout_branch(struct checkout_opts *opts,
if (!opts->can_switch_when_in_progress)
die_if_some_operation_in_progress();
- if (new_branch_info->path && !opts->force_detach && !opts->new_branch &&
- !opts->ignore_other_worktrees) {
- int flag;
- char *head_ref = resolve_refdup("HEAD", 0, NULL, &flag);
- if (head_ref &&
- (!(flag & REF_ISSYMREF) || strcmp(head_ref, new_branch_info->path)))
- die_if_checked_out(new_branch_info->path, 1);
- free(head_ref);
+ /* "git checkout <branch>" */
+ if (new_branch_info->path && !opts->force_detach && !opts->new_branch)
+ die_if_switching_to_a_branch_in_use(opts, new_branch_info->path);
+
+ /* "git checkout -B <branch>" */
+ if (opts->new_branch_force) {
+ char *full_ref = xstrfmt("refs/heads/%s", opts->new_branch);
+ die_if_switching_to_a_branch_in_use(opts, full_ref);
+ free(full_ref);
}
if (!new_branch_info->commit && opts->new_branch) {