From: Junio C Hamano <gitster@pobox.com>
To: Willem Verstraeten <willem.verstraeten@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: git checkout -B <branch> lets you checkout a branch that is already checked out in another worktree Inbox
Date: Thu, 23 Nov 2023 14:58:48 +0900 [thread overview]
Message-ID: <xmqqv89tau3r.fsf@gitster.g> (raw)
In-Reply-To: <xmqqjzq9cl70.fsf@gitster.g> (Junio C. Hamano's message of "Thu, 23 Nov 2023 10:28:19 +0900")
Junio C Hamano <gitster@pobox.com> writes:
> I guess we could change the behaviour so that
>
> git checkout -B <branch> [<start-point>]
>
> fails when <branch> is an existing branch that is in use in another
> worktree, and allow "-f" to be used to override the safety, i.e.,
>
> git checkout -f -B <branch> [<start-point>]
>
> would allow the <branch> to be repointed to <start-point> (or HEAD)
> even when it is used elsewhere.
It turns out that for some reason "-f" is not how we decided to
override this one---there is "--ignore-other-worktrees" option.
I'll attach the first step (preparatory refactoring) to this message
below, and follow it up with the second step to implement and test
the change.
--- >8 ---
From: Junio C Hamano <gitster@pobox.com>
Date: Thu, 23 Nov 2023 14:11:41 +0900
Subject: [PATCH 1/2] checkout: refactor die_if_checked_out() caller
There is a bit dense logic to make a call to "die_if_checked_out()"
while trying to check out a branch. Extract it into a helper
function and give it a bit of comment to describe what is going on.
The most important part of the refactoring is the separation of the
guarding logic before making the call to die_if_checked_out() into
the caller specific part (e.g., the logic that decides that the
caller is trying to check out an existing branch) and the bypass due
to the "--ignore-other-worktrees" option. The latter will be common
no matter how the current or future callers decides they need this
protection.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/checkout.c | 32 +++++++++++++++++++++++---------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index f02434bc15..b4ab972c5a 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1516,6 +1516,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)
{
@@ -1576,15 +1596,9 @@ 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);
if (!new_branch_info->commit && opts->new_branch) {
struct object_id rev;
--
2.43.0
next prev parent reply other threads:[~2023-11-23 5:58 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-22 19:08 git checkout -B <branch> lets you checkout a branch that is already checked out in another worktree Inbox Willem Verstraeten
2023-11-23 1:28 ` Junio C Hamano
2023-11-23 5:58 ` Junio C Hamano [this message]
2023-11-23 6:00 ` [PATCH 2/2] checkout: forbid "-B <branch>" from touching a branch used elsewhere Junio C Hamano
2023-11-23 16:33 ` Phillip Wood
2023-11-23 17:09 ` Eric Sunshine
2023-11-24 1:19 ` Junio C Hamano
2023-11-27 1:51 ` Junio C Hamano
2023-11-27 21:31 ` Jeff King
2023-11-30 15:22 ` Phillip Wood
2023-12-04 12:20 ` Willem Verstraeten
2023-12-04 21:06 ` Eric Sunshine
2023-12-08 17:13 ` Junio C Hamano
2024-01-30 12:37 ` Willem Verstraeten
2024-01-30 22:30 ` Junio C Hamano
2023-11-23 22:03 ` git checkout -B <branch> lets you checkout a branch that is already checked out in another worktree Inbox Andy Koppe
2023-11-23 12:12 ` Willem Verstraeten
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xmqqv89tau3r.fsf@gitster.g \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=willem.verstraeten@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).