]> git.ipfire.org Git - thirdparty/git.git/commitdiff
tag: "git tag" refuses to use HEAD as a tagname
authorJunio C Hamano <gitster@pobox.com>
Tue, 3 Dec 2024 02:32:40 +0000 (11:32 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Dec 2024 03:38:50 +0000 (12:38 +0900)
Even though the plumbing level allows you to create refs/tags/HEAD
and refs/heads/HEAD, doing so makes it confusing within the context
of the UI Git Porcelain commands provides.  Just like we prevent a
branch from getting called "HEAD" at the Porcelain layer (i.e. "git
branch" command), teach "git tag" to refuse to create a tag "HEAD".

With a few new tests, we make sure that

 - "git tag HEAD" and "git tag -a HEAD" are rejected

 - "git update-ref refs/tags/HEAD" is still allowed (this is a
   deliberate design decision to allow others to create their own UI
   on top of Git infrastructure that may be different from our UI).

 - "git tag -d HEAD" can remove refs/tags/HEAD to recover from an
   mistake.

Helped-by: Jeff King <peff@peff.net>
Helped-by: Rubén Justo <rjusto@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
t/t7004-tag.sh

diff --git a/refs.c b/refs.c
index a24bfe3845b8c83e051a6db250096fb1e9634e1d..01ef2a309381a4ed328db30bb7eb0c04ebadfcf6 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -735,7 +735,7 @@ int check_branch_ref(struct strbuf *sb, const char *name)
 
 int check_tag_ref(struct strbuf *sb, const char *name)
 {
-       if (name[0] == '-')
+       if (name[0] == '-' || !strcmp(name, "HEAD"))
                return -1;
 
        strbuf_reset(sb);
index b1316e62f46ded39a3c65a78ef465dc5ba8cae0d..34d34b0dfb43af740591ee43477e51a0be34eaa2 100755 (executable)
@@ -91,6 +91,18 @@ test_expect_success 'creating a tag using default HEAD should succeed' '
        test_must_fail git reflog exists refs/tags/mytag
 '
 
+test_expect_success 'HEAD is forbidden as a tagname' '
+       test_when_finished "git update-ref --no-deref -d refs/tags/HEAD || :" &&
+       test_must_fail git tag HEAD &&
+       test_must_fail git tag -a -m "useless" HEAD
+'
+
+test_expect_success '"git tag" can remove a tag named HEAD' '
+       test_when_finished "git update-ref --no-deref -d refs/tags/HEAD || :" &&
+       git update-ref refs/tags/HEAD HEAD &&
+       git tag -d HEAD
+'
+
 test_expect_success 'creating a tag with --create-reflog should create reflog' '
        git log -1 \
                --format="format:tag: tagging %h (%s, %cd)%n" \