]> git.ipfire.org Git - thirdparty/git.git/commitdiff
branch: update the message to refuse touching a branch in-use
authorJunio C Hamano <gitster@pobox.com>
Fri, 21 Jul 2023 21:53:12 +0000 (14:53 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 21 Jul 2023 22:30:57 +0000 (15:30 -0700)
The "git branch -f" command can refuse to force-update a branch that
is used by another worktree.  The original rationale for this
behaviour was that updating a branch that is checked out in another
worktree, without making a matching change to the index and the
working tree files in that worktree, will lead to a very confused
user.  "git diff HEAD" will no longer give a useful patch, because
HEAD is a commit unrelated to what the index and the working tree in
the worktree were based on, for example.

These days, the same mechanism also protects branches that are being
rebased or bisected, and the same machanism is expected to be the
right place to add more checks, when we decide to protect branches
undergoing other kinds of operations.  We however forgot to rethink
the messaging, which originally said that we are refusing to touch
the branch because it is "checked out" elsewhere, when d2ba271a
(branch: check for bisects and rebases, 2022-06-14) started to
protect branches that are being rebased or bisected.

The spirit of the check has always been that we do not want to
disrupt the use of the same branch in other worktrees.  Let's reword
the message slightly to say that the branch is "used by" another
worktree, instead of "checked out".

We could teach the branch.c:prepare_checked_out_branches() function
to remember why it decided that a particular branch needs protecting
(i.e. was it because it was checked out?  being bisected?  something
else?) in addition to which worktree the branch was in use, and use
that in the error message to say "you cannot force update this
branch because it is being bisected in the worktree X", etc., but it
is dubious that such extra complexity is worth it.  The message
already tells which directory the worktree in question is, and it
should be just a "chdir" away for the user to find out what state it
is in, if the user felt curious enough.  So let's not go there yet.

Helped-by: Josh Sref <jsoref@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
branch.c
t/t2407-worktree-heads.sh

index cdf70b0ef0706eb328902ea21049ab57eaa675a3..3e4684f79f693059a6272465dd983e149aee5eb9 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -471,7 +471,7 @@ int validate_new_branchname(const char *name, struct strbuf *ref, int force)
 
        if ((path = branch_checked_out(ref->buf)))
                die(_("cannot force update the branch '%s' "
-                     "checked out at '%s'"),
+                     "used by worktree at '%s'"),
                    ref->buf + strlen("refs/heads/"), path);
 
        return 1;
index 019a40df2ca99480c547910026bf97102d54a23c..469443d8ae8c44483c7dbea8dd3c3fc2baef0745 100755 (executable)
@@ -58,7 +58,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in bisect' '
        git -C wt-4 bisect good wt-1 &&
 
        test_must_fail git branch -f wt-4 HEAD 2>err &&
-       grep "cannot force update the branch '\''wt-4'\'' checked out at.*wt-4" err
+       grep "cannot force update the branch '\''wt-4'\'' used by worktree at.*wt-4" err
 '
 
 test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (apply)' '
@@ -68,7 +68,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (app
        test_must_fail git -C wt-2 rebase --apply conflict-2 &&
 
        test_must_fail git branch -f wt-2 HEAD 2>err &&
-       grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err
+       grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err
 '
 
 test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (merge)' '
@@ -78,7 +78,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (mer
        test_must_fail git -C wt-2 rebase conflict-2 &&
 
        test_must_fail git branch -f wt-2 HEAD 2>err &&
-       grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err
+       grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err
 '
 
 test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with --update-refs' '
@@ -90,7 +90,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with
        for i in 3 4
        do
                test_must_fail git branch -f can-be-updated HEAD 2>err &&
-               grep "cannot force update the branch '\''can-be-updated'\'' checked out at.*wt-3" err ||
+               grep "cannot force update the branch '\''can-be-updated'\'' used by worktree at.*wt-3" err ||
                        return 1
        done
 '
@@ -150,7 +150,7 @@ test_expect_success 'refuse to overwrite when in error states' '
        for i in 1 2
        do
                test_must_fail git branch -f fake-$i HEAD 2>err &&
-               grep "cannot force update the branch '\''fake-$i'\'' checked out at" err ||
+               grep "cannot force update the branch '\''fake-$i'\'' used by worktree at" err ||
                        return 1
        done
 '