{"thread":{"id":"40167","subject":"bug: git branch -d and case-insensitive file-systems","startedAt":"2015-08-24T16:11:13Z","lastAt":"2015-08-25T15:42:03Z","messageCount":3,"participants":["Aaron Dufour","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"268576","messageId":"CAJrRhQz1UmnDi6Giejetfoh3aPX08aYcgY-neZfcKjpUav0=sA@mail.gmail.com","threadId":"40167","inReplyTo":null,"subject":"bug: git branch -d and case-insensitive file-systems","fromName":"Aaron Dufour","fromEmail":"thedufer@gmail.com","sentAt":"2015-08-24T16:11:13Z","receivedAt":"2015-08-24T16:11:13Z","isPatch":false,"sender":{"key":"thedufer@gmail.com","avatar":null},"body":"I use git (2.2.1) on OS X (10.9.5) and recently my repo got into a bad\nstate.  I think this involves a mis-handling of case-insensitive file\nsystems.\n\nThis reproduces the problem:\n\n    > git init\n    Initialized empty Git repository in /Users/aarond_local/code/git-test/.git/\n    > git commit --allow-empty -m 'first commit'\n    [master (root-commit) 923d8b8] first commit\n    > git checkout -b feature\n    Switched to a new branch 'feature'\n    > git checkout -b Feature\n    fatal: A branch named 'Feature' already exists.\n    > git checkout -B Feature\n    Switched to and reset branch 'Feature'\n    > git branch -d feature\n    Deleted branch feature (was 923d8b8).\n    > git log\n    fatal: bad default revision 'HEAD'\n\nThis is the behavior when there isn't a case mismatch, which is what I\nwould have expected in the previous case as well:\n\n    > git init\n    Initialized empty Git repository in /Users/aarond_local/code/git-test/.git/\n    > git commit --allow-empty -m 'first commit'\n    [master (root-commit) 48df19f] first commit\n    > git checkout -b feature\n    Switched to a new branch 'feature'\n    > git branch -d feature\n    error: Cannot delete the branch 'feature' which you are currently on.\n\nI can also reproduce the issue on git 2.5.0.\n\n-Aaron Dufour\n"},{"id":"268626","messageId":"20150825052123.GA523@sigill.intra.peff.net","threadId":"40167","inReplyTo":"CAJrRhQz1UmnDi6Giejetfoh3aPX08aYcgY-neZfcKjpUav0=sA@mail.gmail.com","subject":"Re: bug: git branch -d and case-insensitive file-systems","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-08-25T05:21:23Z","receivedAt":"2015-08-25T05:21:23Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Aug 24, 2015 at 12:11:13PM -0400, Aaron Dufour wrote:\n\n> I use git (2.2.1) on OS X (10.9.5) and recently my repo got into a bad\n> state.  I think this involves a mis-handling of case-insensitive file\n> systems.\n> \n> This reproduces the problem:\n> \n>     > git init\n>     Initialized empty Git repository in /Users/aarond_local/code/git-test/.git/\n>     > git commit --allow-empty -m 'first commit'\n>     [master (root-commit) 923d8b8] first commit\n>     > git checkout -b feature\n>     Switched to a new branch 'feature'\n>     > git checkout -b Feature\n>     fatal: A branch named 'Feature' already exists.\n>     > git checkout -B Feature\n>     Switched to and reset branch 'Feature'\n>     > git branch -d feature\n>     Deleted branch feature (was 923d8b8).\n>     > git log\n>     fatal: bad default revision 'HEAD'\n\nI don't work on a case-insensitive filesystem, so my knowledge may be\nout of date, but as far as I know, we do not do anything special to\nhandle ref case-sensitivity. I expect your problem would go away with\nthis patch:\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 58aa84f..c5545de 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -19,6 +19,7 @@\n #include \"column.h\"\n #include \"utf8.h\"\n #include \"wt-status.h\"\n+#include \"dir.h\"\n \n static const char * const builtin_branch_usage[] = {\n \tN_(\"git branch [<options>] [-r | -a] [--merged | --no-merged]\"),\n@@ -223,7 +224,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,\n \t\tint flags = 0;\n \n \t\tstrbuf_branchname(&bname, argv[i]);\n-\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\n+\t\tif (kinds == REF_LOCAL_BRANCH && !strcmp_icase(head, bname.buf)) {\n \t\t\terror(_(\"Cannot delete the branch '%s' \"\n \t\t\t      \"which you are currently on.\"), bname.buf);\n \t\t\tret = 1;\n\nbut I think that is just the tip of the iceberg. E.g. (on a vfat\nfilesystem I just created):\n\n  $ git init\n  $ git commit -q --allow-empty -m one\n  $ git branch foo\n  $ git branch FOO\n  fatal: A branch named 'FOO' already exists.\n\n  $ git pack-refs --all --prune ;# usually run as part of git-gc\n  $ git commit -q --allow-empty -m two\n  $ git branch FOO\n  $ git for-each-ref --format='%(refname) %(subject)'\n  refs/heads/FOO two\n  refs/heads/foo one\n  refs/heads/master two\n\nNow the patch I showed above would do the wrong thing. Running \"git\ncheckout foo; git branch -d FOO\" would be rejected, even though I really\ndo have two separate branches.\n\nIt would be a much more invasive change to fix this correctly. It is\nprobably less work overall to move to a pluggable ref system, and to\ndesign ref storage that isn't dependent on the filesystem (this work is\nalready underway).\n\nIn the meantime, I think the best advice for mixed-case branch names on\na case-insensitive filesystem is: don't.\n\n-Peff\n"},{"id":"268652","messageId":"CAJrRhQyiiAQi6RqHJcVFn7=jBfxNvpp_mbOXTsAWHQMWc6gcuQ@mail.gmail.com","threadId":"40167","inReplyTo":"CAJrRhQw-+kbQLexPwa0A6ih-LH9DgbyoTD0DiWWhQeXrOvkYbA@mail.gmail.com","subject":"Fwd: bug: git branch -d and case-insensitive file-systems","fromName":"Aaron Dufour","fromEmail":"thedufer@gmail.com","sentAt":"2015-08-25T15:42:03Z","receivedAt":"2015-08-25T15:42:03Z","isPatch":false,"sender":{"key":"thedufer@gmail.com","avatar":null},"body":"On Tue, Aug 25, 2015 at 1:21 AM, Jeff King <peff@peff.net> wrote:\n> On Mon, Aug 24, 2015 at 12:11:13PM -0400, Aaron Dufour wrote:\n>\n>> I use git (2.2.1) on OS X (10.9.5) and recently my repo got into a bad\n>> state.  I think this involves a mis-handling of case-insensitive file\n>> systems.\n>>\n>> This reproduces the problem:\n>>\n>>     > git init\n>>     Initialized empty Git repository in /Users/aarond_local/code/git-test/.git/\n>>     > git commit --allow-empty -m 'first commit'\n>>     [master (root-commit) 923d8b8] first commit\n>>     > git checkout -b feature\n>>     Switched to a new branch 'feature'\n>>     > git checkout -b Feature\n>>     fatal: A branch named 'Feature' already exists.\n>>     > git checkout -B Feature\n>>     Switched to and reset branch 'Feature'\n>>     > git branch -d feature\n>>     Deleted branch feature (was 923d8b8).\n>>     > git log\n>>     fatal: bad default revision 'HEAD'\n>\n> I don't work on a case-insensitive filesystem, so my knowledge may be\n> out of date, but as far as I know, we do not do anything special to\n> handle ref case-sensitivity. I expect your problem would go away with\n> this patch:\n>\n> diff --git a/builtin/branch.c b/builtin/branch.c\n> index 58aa84f..c5545de 100644\n> --- a/builtin/branch.c\n> +++ b/builtin/branch.c\n> @@ -19,6 +19,7 @@\n>  #include \"column.h\"\n>  #include \"utf8.h\"\n>  #include \"wt-status.h\"\n> +#include \"dir.h\"\n>\n>  static const char * const builtin_branch_usage[] = {\n>         N_(\"git branch [<options>] [-r | -a] [--merged | --no-merged]\"),\n> @@ -223,7 +224,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,\n>                 int flags = 0;\n>\n>                 strbuf_branchname(&bname, argv[i]);\n> -               if (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\n> +               if (kinds == REF_LOCAL_BRANCH && !strcmp_icase(head, bname.buf)) {\n>                         error(_(\"Cannot delete the branch '%s' \"\n>                               \"which you are currently on.\"), bname.buf);\n>                         ret = 1;\n>\n> but I think that is just the tip of the iceberg. E.g. (on a vfat\n> filesystem I just created):\n>\n>   $ git init\n>   $ git commit -q --allow-empty -m one\n>   $ git branch foo\n>   $ git branch FOO\n>   fatal: A branch named 'FOO' already exists.\n>\n>   $ git pack-refs --all --prune ;# usually run as part of git-gc\n>   $ git commit -q --allow-empty -m two\n>   $ git branch FOO\n>   $ git for-each-ref --format='%(refname) %(subject)'\n>   refs/heads/FOO two\n>   refs/heads/foo one\n>   refs/heads/master two\n>\n> Now the patch I showed above would do the wrong thing. Running \"git\n> checkout foo; git branch -d FOO\" would be rejected, even though I really\n> do have two separate branches.\n>\n> It would be a much more invasive change to fix this correctly. It is\n> probably less work overall to move to a pluggable ref system, and to\n> design ref storage that isn't dependent on the filesystem (this work is\n> already underway).\n\nThat's great news!\n\n>\n> In the meantime, I think the best advice for mixed-case branch names on\n> a case-insensitive filesystem is: don't.\n\nYeah, that's definitely the solution.  I got into a weird place\nbecause our build system uses branch names, but it restricts them to\nlowercase letters and I made the mistake of camel-casing.  I'll just\nbe more careful.\n\n>\n> -Peff\n\n-Aaron\n"}]}