git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Rubén Justo" <rjusto@gmail.com>
To: Git List <git@vger.kernel.org>
Subject: [PATCH] branch: consider orphans when validate_branchname()
Date: Fri, 23 Dec 2022 01:58:12 +0100	[thread overview]
Message-ID: <4247f730-5592-de10-a238-5582eac2952d@gmail.com> (raw)

When a branch does not yet have a commit, we call that an orphan branch.
More technically, an orphan branch is a HEAD that points to a
nonexistent ref.

Orphan branches are not normal branches; can only be created, we cannot
simply switch to them.  The initial branch in an empty repository is
an orphan branch.  We can create new orphan branches using
"switch --orphan".

An orphan branch becomes an ordinary branch when the ref it points to is
created, i.e. when the first commit for the branch is done or the branch
is reset to an existing commit.

When we are asked to create a new branch, orphan or not, we use
validate_branchname() to check if a branch already exists in the
repository with the same desired name for the new branch.  In that
function we use ref_exists(), so we are not considering any orphan
branches as there is no ref related to an orphan branch.

If we switch from an orphan branch to a different one, orphan or not,
the initial orphan branch is simply lost.  We cannot switch back to it,
there is nothing to switch back to.  Therefore, there is no major
problem if we only check for valid refs when creating branches, orphans
or not, as there is no orphan branches to consider in the worktree.

Since 529fef20 (checkout: support checking out into a new working
directory, 2014-12-01) we have a safe way to use multiple worktrees with
a Git repository.

This allows the possibility of having multiple (ordinary and orphan)
branches simultaneously, and since we do not check for orphan branches
in validate_branchname(), the same orphan branch name can be used
multiple times.  Once any one of them becomes an ordinary branch, or a
new ordinary branch with the same name is created, all of them will be
/switched/ to that new branch.

It also opens the possibility to copy or rename a normal branch to a
name currently used by an orphan branch, with similar results.

Since 31ad6b61bd (branch: add branch_checked_out() helper, 2022-06-15)
we have a convenient way to see if a branch is checked out in any
worktree.

Let's use branch_checked_out() in validate_branchname() to prevent using
the same branch name multiple times, considering orphan branches too.

Signed-off-by: Rubén Justo <rjusto@gmail.com>
---
 branch.c                |  2 +-
 t/t2400-worktree-add.sh | 10 ++++++++++
 t/t3200-branch.sh       | 10 ++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/branch.c b/branch.c
index d182756827..4029721806 100644
--- a/branch.c
+++ b/branch.c
@@ -367,7 +367,7 @@ int validate_branchname(const char *name, struct strbuf *ref)
 	if (strbuf_check_branch_ref(ref, name))
 		die(_("'%s' is not a valid branch name"), name);
 
-	return ref_exists(ref->buf);
+	return ref_exists(ref->buf) || branch_checked_out(ref->buf);
 }
 
 static int initialized_checked_out_branches;
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index d587e0b20d..f1e4b605da 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -118,6 +118,16 @@ test_expect_success '"add" worktree creating new branch' '
 	)
 '
 
+test_expect_success 'do not allow multiple worktrees with same orphan branch' '
+	test_when_finished "git worktree remove --force detached-wt-A" &&
+	test_when_finished "git worktree remove --force detached-wt-B" &&
+	git worktree add --detach detached-wt-A &&
+	git -C detached-wt-A checkout --orphan orphan-branch &&
+	git worktree add --detach detached-wt-B &&
+	test_must_fail git -C detached-wt-B checkout --orphan orphan-branch &&
+	test_must_fail git checkout --orphan orphan-branch
+'
+
 test_expect_success 'die the same branch is already checked out' '
 	(
 		cd here &&
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 5a169b68d6..68bc579fff 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -192,6 +192,16 @@ test_expect_success 'git branch -M foo bar should fail when bar is checked out i
 	test_must_fail git branch -M bar wt
 '
 
+test_expect_success 'git branch -M/-C bar should fail when destination exists as orphan' '
+	test_when_finished "git worktree remove --force orphan-worktree" &&
+	git worktree add --detach orphan-worktree &&
+	git -C orphan-worktree checkout --orphan orphan-branch &&
+	test_must_fail git checkout --orphan orphan-branch &&
+	test_must_fail git branch orphan-branch &&
+	test_must_fail git branch -M orphan-branch &&
+	test_must_fail git branch -C orphan-branch
+'
+
 test_expect_success 'git branch -M baz bam should succeed when baz is checked out' '
 	git checkout -b baz &&
 	git branch bam &&
-- 
2.36.1


                 reply	other threads:[~2022-12-23  1:03 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4247f730-5592-de10-a238-5582eac2952d@gmail.com \
    --to=rjusto@gmail.com \
    --cc=git@vger.kernel.org \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).