git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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


  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).