{"thread":{"id":"66239","subject":"[Bug] Porcelain allows creation of '@' branch","startedAt":"2026-08-31T14:24:04Z","lastAt":"2026-09-06T07:57:00Z","messageCount":8,"participants":["Bence Csókás","D. Ben Knoble","Jeff King","Kristoffer Haugsbakk","Ben Knoble","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"551557","messageId":"4e8d8b75-ddf4-4602-a2a8-26e5214c65f0@arm.com","threadId":"66239","inReplyTo":null,"subject":"[Bug] Porcelain allows creation of '@' branch","fromName":"Bence Csókás","fromEmail":"bence.csokas@arm.com","sentAt":"2026-08-31T14:22:43Z","receivedAt":"2026-08-31T14:24:04Z","isPatch":false,"body":"Hi,\n\nI ran into this issue a few weeks ago. I'm using Git 2.55.0, which is\nthe latest released.\n\n`git help check-ref-format` says this about a branch name:\n\n   [...]\n   9. They cannot be the single character @.\n   [...]\n\nAnd as expected, it is rejected:\n\n   $ git check-ref-format @ && echo BUG!\n   $\n\nHowever, the following commands all create a branch named @ :\n\n   $ git checkout -b @\n   $ git switch -c @\n   $ git branch @\n\nI believe this to be a bug. Other invalid names are properly rejected\nthough:\n\n   $ git checkout -b master@{1}\n   fatal: 'master@{1}' is not a valid branch name\n   hint: See 'git help check-ref-format'\n   hint: Disable this message with \"git config set advice.refSyntax false\"\n   $ git checkout -b @{1}\n   fatal: '@{1}' is not a valid branch name\n   hint: See 'git help check-ref-format'\n   hint: Disable this message with \"git config set advice.refSyntax false\"\n   $ git checkout -b @^\n   fatal: '@^' is not a valid branch name\n   hint: See 'git help check-ref-format'\n   hint: Disable this message with \"git config set advice.refSyntax false\"\n\nAfter creation, this branch cannot be checked out again, as `git\ncheckout @` is a no-op. Luckily though, `git branch -d @` works, so I\ndidn't permanently damage my Git repo :P\n\nBence\n\nP.S. as I was typing this mail, I realized that I should've given\n`--branch` to check-ref-format, and sure enough, there's the problem:\n\n   $ git check-ref-format --branch @\n   @\n   $ git check-ref-format --branch @{1}\n   fatal: '@{1}' is not a valid branch name\n   $\n\nNot sure why it thinks that would be a valid branch name...\nIMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.\n"},{"id":"551600","messageId":"CALnO6CCph_xC394v_BetLPyoriYc9dLZY42LsXhjVNdvt2e-cQ@mail.gmail.com","threadId":"66239","inReplyTo":"4e8d8b75-ddf4-4602-a2a8-26e5214c65f0@arm.com","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-08-31T19:59:56Z","receivedAt":"2026-08-31T20:00:08Z","isPatch":false,"body":"On Mon, Aug 31, 2026 at 3:12 PM Bence Csókás <bence.csokas@arm.com> wrote:\n>\n> Hi,\n>\n> I ran into this issue a few weeks ago. I'm using Git 2.55.0, which is\n> the latest released.\n>\n> `git help check-ref-format` says this about a branch name:\n>\n>    [...]\n>    9. They cannot be the single character @.\n>    [...]\n\nThis is the rule for a reference.\n\n> And as expected, it is rejected:\n>\n>    $ git check-ref-format @ && echo BUG!\n>    $\n>\n> However, the following commands all create a branch named @ :\n>\n>    $ git checkout -b @\n>    $ git switch -c @\n>    $ git branch @\n\nBut (with git refs list) we should see this creates a ref \"refs/heads/@\".\n\nI happen to think that's extremely confusing given that \"@\" is the\nshorthand for HEAD, but… it's not against the current documented\nrules, I think. (e.g., \"git switch @\" will fail, since it sees \"git\nswitch HEAD\"; using \"refs/heads/@\" will also fail.) git-checkout\ndoesn't fail but also doesn't change to the \"@\" branch. Futzing with\n.git/HEAD and restoring the working tree works, but… yikes.\n\nOf course, --branch mode is allowed to be stricter; maybe we should\nreject this case?\n\n> I believe this to be a bug. Other invalid names are properly rejected\n> though:\n>\n>    $ git checkout -b master@{1}\n>    fatal: 'master@{1}' is not a valid branch name\n>    hint: See 'git help check-ref-format'\n>    hint: Disable this message with \"git config set advice.refSyntax false\"\n>    $ git checkout -b @{1}\n>    fatal: '@{1}' is not a valid branch name\n>    hint: See 'git help check-ref-format'\n>    hint: Disable this message with \"git config set advice.refSyntax false\"\n>    $ git checkout -b @^\n>    fatal: '@^' is not a valid branch name\n>    hint: See 'git help check-ref-format'\n>    hint: Disable this message with \"git config set advice.refSyntax false\"\n>\n> After creation, this branch cannot be checked out again, as `git\n> checkout @` is a no-op. Luckily though, `git branch -d @` works, so I\n> didn't permanently damage my Git repo :P\n>\n> Bence\n>\n> P.S. as I was typing this mail, I realized that I should've given\n> `--branch` to check-ref-format, and sure enough, there's the problem:\n>\n>    $ git check-ref-format --branch @\n>    @\n>    $ git check-ref-format --branch @{1}\n>    fatal: '@{1}' is not a valid branch name\n>    $\n>\n> Not sure why it thinks that would be a valid branch name...\n> IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.\n\n(I don't recall offhand where we describe valid branch names, if at all.)\n\n-- \nD. Ben Knoble\n"},{"id":"551732","messageId":"20260902073753.GC70165@coredump.intra.peff.net","threadId":"66239","inReplyTo":"CALnO6CCph_xC394v_BetLPyoriYc9dLZY42LsXhjVNdvt2e-cQ@mail.gmail.com","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-09-02T07:37:53Z","receivedAt":"2026-09-02T07:37:55Z","isPatch":false,"body":"On Mon, Aug 31, 2026 at 03:59:56PM -0400, D. Ben Knoble wrote:\n\n> But (with git refs list) we should see this creates a ref \"refs/heads/@\".\n> \n> I happen to think that's extremely confusing given that \"@\" is the\n> shorthand for HEAD, but… it's not against the current documented\n> rules, I think. (e.g., \"git switch @\" will fail, since it sees \"git\n> switch HEAD\"; using \"refs/heads/@\" will also fail.) git-checkout\n> doesn't fail but also doesn't change to the \"@\" branch. Futzing with\n> .git/HEAD and restoring the working tree works, but… yikes.\n> \n> Of course, --branch mode is allowed to be stricter; maybe we should\n> reject this case?\n\nYeah, sadly bare \"@\" is allowed in a component (but not \"@{\") because\nwe've maintained strict backwards compatibility. So I don't think it's a\n_bug_ exactly, but in the past we have restricted the porcelain\ninterfaces (so git-branch, but not git-update-ref) to avoid such\nfootguns. The most notable one is HEAD:\n\n  $ git check-ref-format refs/heads/HEAD; echo $?\n  0\n\n  $ git check-ref-format --branch HEAD; echo $?\n  fatal: 'HEAD' is not a valid branch name\n  128\n\nwhich also shows off that \"--branch\" is a convenience option for using\nthose stricter porcelain rules.\n\nI think it would make sense to treat bare \"@\" the same as HEAD here. We\nprobably _don't_ want to forbid any \"@\", though. Branches and tags like\nfoo@bar are legal (if IMHO somewhat gross), and less likely to be used\naccidentally.\n\nSo I think there is no bug, in the sense that the system is working as\ndesigned, but it sure would be a nice feature to block this footgun.\n\n> (I don't recall offhand where we describe valid branch names, if at all.)\n\nI don't think we document the magic porcelain-tightening rules anywhere.\nThat's probably OK in practice; the point of \"check-ref-format --branch\"\nis to check against them programatically.\n\n-Peff\n"},{"id":"551836","messageId":"958622c0-e0a5-4e27-9815-cd1fff2ed111@app.fastmail.com","threadId":"66239","inReplyTo":"CALnO6CCph_xC394v_BetLPyoriYc9dLZY42LsXhjVNdvt2e-cQ@mail.gmail.com","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-09-03T08:38:31Z","receivedAt":"2026-09-03T08:38:56Z","isPatch":false,"body":"On Mon, Aug 31, 2026, at 21:59, D. Ben Knoble wrote:\n> On Mon, Aug 31, 2026 at 3:12 PM Bence Csókás <bence.csokas@arm.com> wrote:\n>>\n>> Hi,\n>>\n>> I ran into this issue a few weeks ago. I'm using Git 2.55.0, which is\n>> the latest released.\n>>\n>> `git help check-ref-format` says this about a branch name:\n>>\n>>    [...]\n>>    9. They cannot be the single character @.\n>>    [...]\n>\n> This is the rule for a reference.\n>\n>> And as expected, it is rejected:\n>>\n>>    $ git check-ref-format @ && echo BUG!\n>>    $\n>>\n>> However, the following commands all create a branch named @ :\n>>\n>>    $ git checkout -b @\n>>    $ git switch -c @\n>>    $ git branch @\n>\n> But (with git refs list) we should see this creates a ref \"refs/heads/@\".\n>\n> I happen to think that's extremely confusing given that \"@\" is the\n> shorthand for HEAD, but… it's not against the current documented\n> rules, I think. (e.g., \"git switch @\" will fail, since it sees \"git\n> switch HEAD\"; using \"refs/heads/@\" will also fail.) git-checkout\n> doesn't fail but also doesn't change to the \"@\" branch. Futzing with\n> .git/HEAD and restoring the working tree works, but… yikes.\n>\n> Of course, --branch mode is allowed to be stricter; maybe we should\n> reject this case?\n\nNot a bug (2024) https://lore.kernel.org/git/xmqqy12z7eti.fsf@gitster.g/\n\n    I suspect that it is much more productive to deprecate and remove\n    \"@\" that is a built-in synomym for HEAD (but \"refs/remotes/origin/@\"\n    does not act as a synonym for \"refs/remotes/origin/HEAD\"). [...]\n\n>[snip]\n"},{"id":"551859","messageId":"2006115b-bcf2-486a-ac7a-681caae686b4@arm.com","threadId":"66239","inReplyTo":"958622c0-e0a5-4e27-9815-cd1fff2ed111@app.fastmail.com","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"Bence Csókás","fromEmail":"bence.csokas@arm.com","sentAt":"2026-09-03T12:35:51Z","receivedAt":"2026-09-03T12:36:33Z","isPatch":false,"body":"On 2026. 09. 03. 10:38, Kristoffer Haugsbakk wrote:\n> Not a bug (2024) https://lore.kernel.org/git/xmqqy12z7eti.fsf@gitster.g/\n>\n>      I suspect that it is much more productive to deprecate and remove\n>      \"@\" that is a built-in synomym for HEAD (but \"refs/remotes/origin/@\"\n>      does not act as a synonym for \"refs/remotes/origin/HEAD\"). [...]\nI would not want to see @ removed, I have abandoned using HEAD years\nago, too much typing (especially if you want to express more complex\nthings, e.g. `git range-diff long-branch-name{^..otherbranch,..@}`, to\npick an example out of my bash-history).\n\nBence\nIMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.\n"},{"id":"551878","messageId":"E4F5C2BA-B083-42F6-A7B1-93A5FB984604@gmail.com","threadId":"66239","inReplyTo":"2006115b-bcf2-486a-ac7a-681caae686b4@arm.com","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-09-03T15:14:05Z","receivedAt":"2026-09-03T15:14:18Z","isPatch":false,"body":"\n> Le 3 sept. 2026 à 08:36, Bence Csókás <bence.csokas@arm.com> a écrit :\n> \n> ﻿On 2026. 09. 03. 10:38, Kristoffer Haugsbakk wrote:\n>> Not a bug (2024) https://lore.kernel.org/git/xmqqy12z7eti.fsf@gitster.g/\n>> \n>>     I suspect that it is much more productive to deprecate and remove\n>>     \"@\" that is a built-in synomym for HEAD (but \"refs/remotes/origin/@\"\n>>     does not act as a synonym for \"refs/remotes/origin/HEAD\"). [...]\n> I would not want to see @ removed, I have abandoned using HEAD years\n> ago, too much typing (especially if you want to express more complex\n> things, e.g. `git range-diff long-branch-name{^..otherbranch,..@}`, to\n> pick an example out of my bash-history).\n\nDitto, though thanks for digging up the reference. It will surely be important to justify when proposing to tighten the branch-mode rules. "},{"id":"551900","messageId":"xmqqmrtyb2dd.fsf@gitster.g","threadId":"66239","inReplyTo":"E4F5C2BA-B083-42F6-A7B1-93A5FB984604@gmail.com","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-09-03T18:45:18Z","receivedAt":"2026-09-03T18:45:21Z","isPatch":false,"body":"Ben Knoble <ben.knoble@gmail.com> writes:\n\n>> Le 3 sept. 2026 à 08:36, Bence Csókás <bence.csokas@arm.com> a écrit :\n>> \n>> ﻿On 2026. 09. 03. 10:38, Kristoffer Haugsbakk wrote:\n>>> Not a bug (2024) https://lore.kernel.org/git/xmqqy12z7eti.fsf@gitster.g/\n>>> \n>>>     I suspect that it is much more productive to deprecate and remove\n>>>     \"@\" that is a built-in synomym for HEAD (but \"refs/remotes/origin/@\"\n>>>     does not act as a synonym for \"refs/remotes/origin/HEAD\"). [...]\n>> I would not want to see @ removed, I have abandoned using HEAD years\n>> ago, too much typing (especially if you want to express more complex\n>> things, e.g. `git range-diff long-branch-name{^..otherbranch,..@}`, to\n>> pick an example out of my bash-history).\n>\n> Ditto, though thanks for digging up the reference. It will surely be important to justify when proposing to tighten the branch-mode rules. \n\nIt is very unfortunate that the quote is partial and incomplete,\nthough, and would not be a good input for people to decide on their\nown.\n\n"},{"id":"552066","messageId":"2e2dcf60-4175-4cc4-8379-f6618340da40@app.fastmail.com","threadId":"66239","inReplyTo":"xmqqmrtyb2dd.fsf@gitster.g","subject":"Re: [Bug] Porcelain allows creation of '@' branch","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-09-06T07:56:34Z","receivedAt":"2026-09-06T07:57:00Z","isPatch":false,"body":"On Thu, Sep 3, 2026, at 20:45, Junio C Hamano wrote:\n> Ben Knoble <ben.knoble@gmail.com> writes:\n>\n>>> Le 3 sept. 2026 à 08:36, Bence Csókás <bence.csokas@arm.com> a écrit :\n>>>\n>>> ﻿On 2026. 09. 03. 10:38, Kristoffer Haugsbakk wrote:\n>>>> Not a bug (2024) https://lore.kernel.org/git/xmqqy12z7eti.fsf@gitster.g/\n>>>>\n>>>>     I suspect that it is much more productive to deprecate and remove\n>>>>     \"@\" that is a built-in synomym for HEAD (but \"refs/remotes/origin/@\"\n>>>>     does not act as a synonym for \"refs/remotes/origin/HEAD\"). [...]\n>>> I would not want to see @ removed, I have abandoned using HEAD years\n>>> ago, too much typing (especially if you want to express more complex\n>>> things, e.g. `git range-diff long-branch-name{^..otherbranch,..@}`, to\n>>> pick an example out of my bash-history).\n>>\n>> Ditto, though thanks for digging up the reference. It will surely be important to justify when proposing to tighten the branch-mode rules.\n>\n> It is very unfortunate that the quote is partial and incomplete,\n> though, and would not be a good input for people to decide on their\n> own.\n\nSorry that I misrepresented your post. The gist to me was that you\nweren’t interested in more code to deal with the `@` shorthand.\n"}]}