branch -d: refuse deleting a branch which is currently checked out
authorKazuki Yamaguchi <k@rhe.jp>
Tue, 29 Mar 2016 09:38:39 +0000 (18:38 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 29 Mar 2016 20:05:53 +0000 (13:05 -0700)
When a branch is checked out by current working tree, deleting the
branch is forbidden. However when the branch is checked out only by
other working trees, deleting incorrectly succeeds.
Use find_shared_symref() to check if the branch is in use, not just
comparing with the current working tree's HEAD.

Helped-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Kazuki Yamaguchi <k@rhe.jp>
Reviewed-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/branch.c
t/t3200-branch.sh
index 7b45b6bd6b80613de9f894cfbe8e9d2dcae77b09..8885d9f8e2cdbd6b7c3e1ff753147f57ffd37243 100644 (file)
@@ -20,6 +20,7 @@
 #include "utf8.h"
 #include "wt-status.h"
 #include "ref-filter.h"
+#include "worktree.h"
 
 static const char * const builtin_branch_usage[] = {
        N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
@@ -215,16 +216,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                int flags = 0;
 
                strbuf_branchname(&bname, argv[i]);
-               if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) {
-                       error(_("Cannot delete the branch '%s' "
-                             "which you are currently on."), bname.buf);
-                       ret = 1;
-                       continue;
-               }
-
                free(name);
-
                name = mkpathdup(fmt, bname.buf);
+
+               if (kinds == FILTER_REFS_BRANCHES) {
+                       char *worktree = find_shared_symref("HEAD", name);
+                       if (worktree) {
+                               error(_("Cannot delete branch '%s' "
+                                       "checked out at '%s'"),
+                                     bname.buf, worktree);
+                               free(worktree);
+                               ret = 1;
+                               continue;
+                       }
+               }
+
                target = resolve_ref_unsafe(name,
                                            RESOLVE_REF_READING
                                            | RESOLVE_REF_NO_RECURSE
index a897248490650ebef1a33a60a1aa9cf4431f06ff..508007fd377260fd46e385d6a47b8a9732ef1dd0 100755 (executable)
@@ -403,6 +403,12 @@ test_expect_success 'test deleting branch without config' '
        test_i18ncmp expect actual
 '
 
+test_expect_success 'deleting currently checked out branch fails' '
+       git worktree add -b my7 my7 &&
+       test_must_fail git -C my7 branch -d my7 &&
+       test_must_fail git branch -d my7
+'
+
 test_expect_success 'test --track without .fetch entries' '
        git branch --track my8 &&
        test "$(git config branch.my8.remote)" &&