{"thread":{"id":"35964","subject":"Branch Name Case Sensitivity","startedAt":"2014-02-26T21:06:54Z","lastAt":"2014-03-05T14:02:48Z","messageCount":27,"participants":["Lee Hopkins","Junio C Hamano","Torsten Bögershausen","Michael Haggerty","Karsten Blees","Johannes Sixt","Stephen Leake","Duy Nguyen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"235420","messageId":"CAJHY66EQD280QgXBCoZU4y_aqSEu3A1hXzeW7X-rtT6vMZ92oA@mail.gmail.com","threadId":"35964","inReplyTo":null,"subject":"Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-02-26T21:06:54Z","receivedAt":"2014-02-26T21:06:54Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"Hello,\n\nLast week I ran across a potential bug with branch names on case\ninsensitive file systems, the complete scenario can be found here:\n\nhttps://groups.google.com/forum/#!topic/msysgit/ugKL-sVMiqI\n\nThe tldr is because refs are stored as plain text files except when\npacked into packed-refs, Git occasionally cannot tell the difference\nbetween branches whose names only differ in case, and this could\npotentially lead to the loss of history.\n\nIt sounds like this is a known issue, and after some more digging I\ndid find some older threads related to this topic, but nothing recent.\nSo I guess I just wanted to bring this to the attention of the Git\ndevs and maybe restart some discussions.\n\nThanks,\n-Lee\n"},{"id":"235498","messageId":"xmqqvbw0xrl6.fsf@gitster.dls.corp.google.com","threadId":"35964","inReplyTo":"CAJHY66EQD280QgXBCoZU4y_aqSEu3A1hXzeW7X-rtT6vMZ92oA@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-27T19:50:45Z","receivedAt":"2014-02-27T19:50:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lee Hopkins <leerhop@gmail.com> writes:\n\n> Last week I ran across a potential bug with branch names on case\n> insensitive file systems, the complete scenario can be found here:\n>\n> https://groups.google.com/forum/#!topic/msysgit/ugKL-sVMiqI\n>\n> The tldr is because refs are stored as plain text files except when\n> packed into packed-refs, Git occasionally cannot tell the difference\n> between branches whose names only differ in case, and this could\n> potentially lead to the loss of history.\n>\n> It sounds like this is a known issue, and after some more digging I\n> did find some older threads related to this topic, but nothing recent.\n\nYes, it is not limited to branch names but also applies to tags and\nfilenames in your working tree.\n\nPerhaps git-{branch,tag}.txt and possibly gitrepository-layout.txt\nin Documentation/ may need a new \"*Note*\" section to warn against\nthis.\n\nThanks.\n"},{"id":"235504","messageId":"530FA0C1.3000109@web.de","threadId":"35964","inReplyTo":"xmqqvbw0xrl6.fsf@gitster.dls.corp.google.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2014-02-27T20:32:01Z","receivedAt":"2014-02-27T20:32:01Z","isPatch":false,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2014-02-27 20.50, Junio C Hamano wrote:\n> Lee Hopkins <leerhop@gmail.com> writes:\n> \n>> Last week I ran across a potential bug with branch names on case\n>> insensitive file systems, the complete scenario can be found here:\n>>\n>> https://groups.google.com/forum/#!topic/msysgit/ugKL-sVMiqI\n>>\n>> The tldr is because refs are stored as plain text files except when\n>> packed into packed-refs, Git occasionally cannot tell the difference\n>> between branches whose names only differ in case, and this could\n>> potentially lead to the loss of history.\n>>\n>> It sounds like this is a known issue, and after some more digging I\n>> did find some older threads related to this topic, but nothing recent.\n> \n> Yes, it is not limited to branch names but also applies to tags and\n> filenames in your working tree.\n> \n> Perhaps git-{branch,tag}.txt and possibly gitrepository-layout.txt\n> in Documentation/ may need a new \"*Note*\" section to warn against\n> this.\n> \n> Thanks.\nThere is a possible workaround:\ngit pack-refs --all --prune\n\nIf this can be triggered by a hook, I don't know (I never used a hook)\n\nIt uses the C-function pack_refs(flags) in builtin/pack-refs.c\nOr we can possibly trigger this function at the the of\n\"checkout -b\" or \"fetch\" commands ?\nOnly when core.ignorecase == true ?\n"},{"id":"235507","messageId":"CAJHY66H2M2aQvQ8MLN7XB4uYiFohRfhhsXhd56hwDR5qMGi6Tg@mail.gmail.com","threadId":"35964","inReplyTo":"530FA0C1.3000109@web.de","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-02-27T20:37:49Z","receivedAt":"2014-02-27T20:37:49Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"> Perhaps git-{branch,tag}.txt and possibly gitrepository-layout.txt\n> in Documentation/ may need a new \"*Note*\" section to warn against\n> this.\n\nA little more documentation never hurt anyone :).\n\n> Or we can possibly trigger this function at the the of\n> \"checkout -b\" or \"fetch\" commands ?\n> Only when core.ignorecase == true ?\n\nThis would essentially make git always use packed-refs when\ncore.ignorecase == true, correct? Are there any downsides to always\nusing packed-refs?\n\nThanks,\n-Lee\n\nOn Thu, Feb 27, 2014 at 3:32 PM, Torsten Bögershausen <tboegi@web.de> wrote:\n> On 2014-02-27 20.50, Junio C Hamano wrote:\n>> Lee Hopkins <leerhop@gmail.com> writes:\n>>\n>>> Last week I ran across a potential bug with branch names on case\n>>> insensitive file systems, the complete scenario can be found here:\n>>>\n>>> https://groups.google.com/forum/#!topic/msysgit/ugKL-sVMiqI\n>>>\n>>> The tldr is because refs are stored as plain text files except when\n>>> packed into packed-refs, Git occasionally cannot tell the difference\n>>> between branches whose names only differ in case, and this could\n>>> potentially lead to the loss of history.\n>>>\n>>> It sounds like this is a known issue, and after some more digging I\n>>> did find some older threads related to this topic, but nothing recent.\n>>\n>> Yes, it is not limited to branch names but also applies to tags and\n>> filenames in your working tree.\n>>\n>> Perhaps git-{branch,tag}.txt and possibly gitrepository-layout.txt\n>> in Documentation/ may need a new \"*Note*\" section to warn against\n>> this.\n>>\n>> Thanks.\n> There is a possible workaround:\n> git pack-refs --all --prune\n>\n> If this can be triggered by a hook, I don't know (I never used a hook)\n>\n> It uses the C-function pack_refs(flags) in builtin/pack-refs.c\n> Or we can possibly trigger this function at the the of\n> \"checkout -b\" or \"fetch\" commands ?\n> Only when core.ignorecase == true ?\n>\n>\n>\n>\n>\n>\n>\n"},{"id":"235510","messageId":"530FA77B.2030707@alum.mit.edu","threadId":"35964","inReplyTo":"CAJHY66H2M2aQvQ8MLN7XB4uYiFohRfhhsXhd56hwDR5qMGi6Tg@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2014-02-27T21:00:43Z","receivedAt":"2014-02-27T21:00:43Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 02/27/2014 09:37 PM, Lee Hopkins wrote:\n>> Perhaps git-{branch,tag}.txt and possibly gitrepository-layout.txt\n>> in Documentation/ may need a new \"*Note*\" section to warn against\n>> this.\n> \n> A little more documentation never hurt anyone :).\n> \n>> Or we can possibly trigger this function at the the of\n>> \"checkout -b\" or \"fetch\" commands ?\n>> Only when core.ignorecase == true ?\n> \n> This would essentially make git always use packed-refs when\n> core.ignorecase == true, correct? Are there any downsides to always\n> using packed-refs?\n\nThere are at least two reasons I can think of:\n\n1. Efficiency: any time a reference changes, the whole packed-refs file\nwould have to be read and written as opposed to a single, small\nloose-ref file.\n\n2. Lock contention: two processes can modify loose references at the\nsame time without contending with each other.  If they always wrote the\npacked-refs file, there would be more lock contention (which in the git\nworld means that one of the processes would fail).\n\nWhether these are concern for a single user using a local git repository\n(as opposed to git running on a server) mostly depends on how many\nreferences you have.  With a hundred references you would probably not\nnotice any difference.  With ten thousand you probably would.  Somewhere\nin between lies the pain threshold.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"235521","messageId":"530FBB1D.3050505@gmail.com","threadId":"35964","inReplyTo":"530FA0C1.3000109@web.de","subject":"Re: Branch Name Case Sensitivity","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2014-02-27T22:24:29Z","receivedAt":"2014-02-27T22:24:29Z","isPatch":false,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Am 27.02.2014 21:32, schrieb Torsten Bögershausen:\n> On 2014-02-27 20.50, Junio C Hamano wrote:\n>> Lee Hopkins <leerhop@gmail.com> writes:\n>>\n>>> Last week I ran across a potential bug with branch names on case\n>>> insensitive file systems, the complete scenario can be found here:\n>>>\n>>> https://groups.google.com/forum/#!topic/msysgit/ugKL-sVMiqI\n>>>\n>>> The tldr is because refs are stored as plain text files except when\n>>> packed into packed-refs, Git occasionally cannot tell the difference\n>>> between branches whose names only differ in case, and this could\n>>> potentially lead to the loss of history.\n>>>\n>>> It sounds like this is a known issue, and after some more digging I\n>>> did find some older threads related to this topic, but nothing recent.\n>>\n>> Yes, it is not limited to branch names but also applies to tags and\n>> filenames in your working tree.\n>>\n>> Perhaps git-{branch,tag}.txt and possibly gitrepository-layout.txt\n>> in Documentation/ may need a new \"*Note*\" section to warn against\n>> this.\n>>\n>> Thanks.\n> There is a possible workaround:\n> git pack-refs --all --prune\n> \n\nIf I understand the issue correctly, the problem is that packed-refs are always case-sensitive, even if core.ignorecase=true. OTOH, checking / updating _unpacked_ refs on a case-insensitive file system is naturally case-insensitive. So wouldn't it be a better workaround to disallow packed refs (i.e. 'git config gc.packrefs false')?\n"},{"id":"235527","messageId":"CAJHY66FtC03YbJrbVn+adsePkYnVD2RGH1TGkzz2pKNBoee_iQ@mail.gmail.com","threadId":"35964","inReplyTo":"530FBB1D.3050505@gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-02-27T23:38:04Z","receivedAt":"2014-02-27T23:38:04Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"> If I understand the issue correctly, the problem is that packed-refs are always case-sensitive, even if core.ignorecase=true.\n> OTOH, checking / updating _unpacked_ refs on a case-insensitive file system is naturally case-insensitive.\n> So wouldn't it be a better workaround to disallow packed refs (i.e. 'git config gc.packrefs false')?\n\nYou are correct, the issue boils down to mixing the usage of\npacked-refs and loose refs on case insensitive file systems. So either\nalways using packed-refs or always using loose refs would take care of\nthe problem. Based Michael Haggerty's response, it seems that always\nusing loose refs would be a better workaround.\n\nIf I understand gc.packrefs = false correctly, it only prevents git gc\nfrom running git pack-refs, so my question would be is there anything\nelse aside from git gc that would trigger git pack-refs? Are there\nsignificant downsides to always using loose refs? Would checking\ncore.ignorecase in builtin\\pack-refs.c, and exiting if true, be\nappropriate?\n\nThanks,\n-Lee\n"},{"id":"235543","messageId":"53102FB0.6040603@viscovery.net","threadId":"35964","inReplyTo":"CAJHY66FtC03YbJrbVn+adsePkYnVD2RGH1TGkzz2pKNBoee_iQ@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2014-02-28T06:41:52Z","receivedAt":"2014-02-28T06:41:52Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 2/28/2014 0:38, schrieb Lee Hopkins:\n>> If I understand the issue correctly, the problem is that packed-refs\n>> are always case-sensitive, even if core.ignorecase=true. OTOH,\n\ncore.ignorecase is intended to affect filenames of the worktree, not\nanything else, BTW.\n\n>> checking / updating _unpacked_ refs on a case-insensitive file system\n>> is naturally case-insensitive. So wouldn't it be a better workaround\n>> to disallow packed refs (i.e. 'git config gc.packrefs false')?\n> \n> You are correct, the issue boils down to mixing the usage of \n> packed-refs and loose refs on case insensitive file systems. So either \n> always using packed-refs or always using loose refs would take care of \n> the problem. Based Michael Haggerty's response, it seems that always \n> using loose refs would be a better workaround.\n\nSo, everybody on a case-insensitive file system should pay the price even\nif they do not need the \"feature\"? No way.\n\nIf you are on a case-insensitive filesystem, or work on a cross-platform\nproject, ensure that you avoid ambiguous refs. Problem solved.\n\n-- Hannes\n"},{"id":"235565","messageId":"8538j31u1n.fsf@stephe-leake.org","threadId":"35964","inReplyTo":"530FBB1D.3050505@gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Stephen Leake","fromEmail":"stephen_leake@stephe-leake.org","sentAt":"2014-02-28T09:11:00Z","receivedAt":"2014-02-28T09:11:00Z","isPatch":false,"sender":{"key":"stephen_leake@stephe-leake.org","avatar":null},"body":"Karsten Blees <karsten.blees@gmail.com> writes:\n\n> If I understand the issue correctly, the problem is that packed-refs\n> are always case-sensitive, even if core.ignorecase=true. \n\nPerhaps that could be changed? if core.ignorecase=true, packed-refs\nshould be compared with case-insensitive string compares.\n\n-- \n-- Stephe\n"},{"id":"235567","messageId":"53105343.2040703@alum.mit.edu","threadId":"35964","inReplyTo":"CAJHY66FtC03YbJrbVn+adsePkYnVD2RGH1TGkzz2pKNBoee_iQ@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2014-02-28T09:13:39Z","receivedAt":"2014-02-28T09:13:39Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 02/28/2014 12:38 AM, Lee Hopkins wrote:\n> [...] Based Michael Haggerty's response, it seems that always\n> using loose refs would be a better workaround.\n\nNo, I answered the question \"what would be the disadvantages of using\nonly packed refs?\".  Now I will answer the question \"what would be the\ndisadvantages of using only loose refs?\":\n\n1. Efficiency.  Any time all of the references have to be read, loose\nrefs are far slower than packed refs.\n\n2. Disk space and inode usage: loose refs consume one inode and one disk\nsector (typically 4k) each, whereas packed refs consume only one inode\nin total, and many packed refs can fit into each disk sector.\n\nAfter all, there is a reason that we have both packed refs and loose\nrefs.  The basic idea is to use packed refs for the bulk of references,\nespecially \"cold\" references like tags that only change infrequently,\nbut to store \"hot\" references as loose refs so that they can be modified\ncheaply.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"235583","messageId":"53105BC0.5040304@alum.mit.edu","threadId":"35964","inReplyTo":"8538j31u1n.fsf@stephe-leake.org","subject":"Re: Branch Name Case Sensitivity","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2014-02-28T09:49:52Z","receivedAt":"2014-02-28T09:49:52Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 02/28/2014 10:11 AM, Stephen Leake wrote:\n> Karsten Blees <karsten.blees@gmail.com> writes:\n> \n>> If I understand the issue correctly, the problem is that packed-refs\n>> are always case-sensitive, even if core.ignorecase=true. \n> \n> Perhaps that could be changed? if core.ignorecase=true, packed-refs\n> should be compared with case-insensitive string compares.\n\nI think you are putting too much focus on what the local Git repository\ndoes.  As soon as you pull content from somebody else, you are at the\nmercy of the reference names that they have chosen.\n\nIn my opinion, a more fruitful approach is to have a pre-receive hook at\nyour central repository that prevents references that differ in case\nonly from being pushed in the first place.  As an extra convenience, you\ncan set your local repos up with a pre-commit hook that does the same\nthing, so that developers (usually) see the problem immediately rather\nthan only when they try to push.\n\nOf course, the pre-receive/pre-commit hooks could be even stricter by,\nfor example, allowing only lower-case branch names.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"235609","messageId":"5310959D.709@gmail.com","threadId":"35964","inReplyTo":"53102FB0.6040603@viscovery.net","subject":"Re: Branch Name Case Sensitivity","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2014-02-28T13:56:45Z","receivedAt":"2014-02-28T13:56:45Z","isPatch":false,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Am 28.02.2014 07:41, schrieb Johannes Sixt:\n> Am 2/28/2014 0:38, schrieb Lee Hopkins:\n>>> If I understand the issue correctly, the problem is that packed-refs\n>>> are always case-sensitive, even if core.ignorecase=true. OTOH,\n> \n> core.ignorecase is intended to affect filenames of the worktree, not\n> anything else, BTW.\n> \n\nfrom git-config(1):\n\"enables various workarounds to enable git to work better on filesystems that are not case sensitive\"\n\nIt says nothing about work-tree only, so I'd expect it to apply to all git components that store potentially case-sensitive information in file names.\n\n...it also says \"better\", not \"flawlessly\" :-)\n\n>>> checking / updating _unpacked_ refs on a case-insensitive file system\n>>> is naturally case-insensitive. So wouldn't it be a better workaround\n>>> to disallow packed refs (i.e. 'git config gc.packrefs false')?\n>>\n>> You are correct, the issue boils down to mixing the usage of \n>> packed-refs and loose refs on case insensitive file systems. So either \n>> always using packed-refs or always using loose refs would take care of \n>> the problem. Based Michael Haggerty's response, it seems that always \n>> using loose refs would be a better workaround.\n> \n> So, everybody on a case-insensitive file system should pay the price even\n> if they do not need the \"feature\"? No way.\n> \n> If you are on a case-insensitive filesystem, or work on a cross-platform\n> project, ensure that you avoid ambiguous refs. Problem solved.\n> \n\nSo its OK to lose data if you accidentally use an ambiguous ref? I cannot believe you actually meant that.\n\nIMO the proper solution is to teach packed-refs about core.ignorecase. Until that happens, disabling gc.packrefs seems to be a valid workaround for people who have that problem.\n"},{"id":"235611","messageId":"CAJHY66EPKnmSGGSxRi=p8m4dsys=wiLNWoQF6+3Xe4j9J+DivQ@mail.gmail.com","threadId":"35964","inReplyTo":"5310959D.709@gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-02-28T14:10:56Z","receivedAt":"2014-02-28T14:10:56Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"> If you are on a case-insensitive filesystem, or work on a cross-platform\n> project, ensure that you avoid ambiguous refs. Problem solved.\n\nI agree this is the best solution, and I personally avoid the use of\nambiguous refs. However, since there is nothing in git stopping the\nuse of ambiguous refs, there is no way to stop every person who works\non a shared repo from using them.\n\n> So, everybody on a case-insensitive file system should pay the price even\n> if they do not need the \"feature\"? No way.\n\nI would say preventing potential loss of commits is a price worth paying.\n\n> IMO the proper solution is to teach packed-refs about core.ignorecase. Until that happens, disabling gc.packrefs seems to be a valid\n> workaround for people who have that problem.\n\nOnce again, based on Michael Haggerty's very informative input, maybe\nan even better solution would be to add a core.allowambiguousrefs\n(default to true) option and when it is false do a case insensitive\ncomparison during ref creation (branching, tagging).\n\nThanks,\n-Lee\n"},{"id":"235617","messageId":"CACsJy8B7fFBJ5ZbJDjGj4G6mx1byitC7BU4oJ3C0zq7cuv4fvA@mail.gmail.com","threadId":"35964","inReplyTo":"53105343.2040703@alum.mit.edu","subject":"Re: Branch Name Case Sensitivity","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-28T14:31:29Z","receivedAt":"2014-02-28T14:31:29Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Feb 28, 2014 at 4:13 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n> On 02/28/2014 12:38 AM, Lee Hopkins wrote:\n>> [...] Based Michael Haggerty's response, it seems that always\n>> using loose refs would be a better workaround.\n>\n> No, I answered the question \"what would be the disadvantages of using\n> only packed refs?\".  Now I will answer the question \"what would be the\n> disadvantages of using only loose refs?\":\n>\n> 1. Efficiency.  Any time all of the references have to be read, loose\n> refs are far slower than packed refs.\n>\n> 2. Disk space and inode usage: loose refs consume one inode and one disk\n> sector (typically 4k) each, whereas packed refs consume only one inode\n> in total, and many packed refs can fit into each disk sector.\n>\n> After all, there is a reason that we have both packed refs and loose\n> refs.  The basic idea is to use packed refs for the bulk of references,\n> especially \"cold\" references like tags that only change infrequently,\n> but to store \"hot\" references as loose refs so that they can be modified\n> cheaply.\n\nCould we have a staging place for new refs in between? Case\nsensitivity is just another limitation we hit because we rely on\nfilesystem. We already have problems with having both refs foo and\nfoo/bar at the same time. Not all repos are super busy and need the\ntop efficiencies of loose refs.\n\nAnd about rewriting packed-refs every time, I don't think that's a big\nproblem for \"normal\" repos. linux-2.6 index file is 4MB(*) and it's\nrewritten on nearly every worktree-related operation and nobody\ncomplains (out loud anyway). Assuming an average ref takes 100 bytes,\nthat's about 41k refs.\n\n(*) it's 3MB with index-v4 but I don't think v4 is popular\n-- \nDuy\n"},{"id":"235621","messageId":"5310A105.50403@alum.mit.edu","threadId":"35964","inReplyTo":"CACsJy8B7fFBJ5ZbJDjGj4G6mx1byitC7BU4oJ3C0zq7cuv4fvA@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2014-02-28T14:45:25Z","receivedAt":"2014-02-28T14:45:25Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"On 02/28/2014 03:31 PM, Duy Nguyen wrote:\n> On Fri, Feb 28, 2014 at 4:13 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n>> On 02/28/2014 12:38 AM, Lee Hopkins wrote:\n>>> [...] Based Michael Haggerty's response, it seems that always\n>>> using loose refs would be a better workaround.\n>>\n>> No, I answered the question \"what would be the disadvantages of using\n>> only packed refs?\".  Now I will answer the question \"what would be the\n>> disadvantages of using only loose refs?\":\n>>\n>> 1. Efficiency.  Any time all of the references have to be read, loose\n>> refs are far slower than packed refs.\n>>\n>> 2. Disk space and inode usage: loose refs consume one inode and one disk\n>> sector (typically 4k) each, whereas packed refs consume only one inode\n>> in total, and many packed refs can fit into each disk sector.\n>>\n>> After all, there is a reason that we have both packed refs and loose\n>> refs.  The basic idea is to use packed refs for the bulk of references,\n>> especially \"cold\" references like tags that only change infrequently,\n>> but to store \"hot\" references as loose refs so that they can be modified\n>> cheaply.\n> \n> Could we have a staging place for new refs in between? Case\n> sensitivity is just another limitation we hit because we rely on\n> filesystem. We already have problems with having both refs foo and\n> foo/bar at the same time. Not all repos are super busy and need the\n> top efficiencies of loose refs.\n\nTrue.  Nor should most people usually need the ability to run multiple\ngit commands simultaneously.\n\nIn fact, I've started working on a pluggable backend for reference\nstorage.  After that change, it should be easy to experiment with\ndifferent combinations of loose-only, packed-only, or other (new)\nstorage schemes that don't suffer from directory/file conflicts, etc.  I\nhaven't talked about this work on the list yet because it's still very\nyoung.\n\nMichael\n\n-- \nMichael Haggerty\nmhagger@alum.mit.edu\nhttp://softwareswirl.blogspot.com/\n"},{"id":"235654","messageId":"xmqqk3cfuksd.fsf@gitster.dls.corp.google.com","threadId":"35964","inReplyTo":"5310959D.709@gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-28T18:58:10Z","receivedAt":"2014-02-28T18:58:10Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Karsten Blees <karsten.blees@gmail.com> writes:\n\n>> If you are on a case-insensitive filesystem, or work on a cross-platform\n>> project, ensure that you avoid ambiguous refs. Problem solved.\n>> \n>\n> So its OK to lose data if you accidentally use an ambiguous ref? I\n> cannot believe you actually meant that.\n\nI think he meant what he said: \"you avoid ambiguous refs\".  He did\nnot say \"it is not Git's business to help you doing so\".\n\nI think it is prudent to warn in the end-user facing layer (read: do\nnot touch refs.c to implement something like that) when the user\ncreates \"refs/heads/Next\" when there already is \"refs/heads/next\",\nand I further think it would make sense to do so even on case\nsensitive platforms.\n\nWe warn ambiguous refs across refs hierarchies (e.g. if you have\nrefs/heads/next and refs/tags/next) with core.warnAmbiguousRefs; I\ndo not think it is a stretch to either introduce a new configuration\ncore.warnCaseInsensitiveRefs (auto-detected at the same place as we\nauto-detect core.ignorecase) or use the same core.warnAmbiguousRefs\nto trigger a warning upon seeing both \"refs/heads/next\" and\n\"refs/heads/Next\".\n"},{"id":"235676","messageId":"CACsJy8A6etyFkxn3D7hjM9JgzmokPBARXrEncVuw1x+OOHJ_Lg@mail.gmail.com","threadId":"35964","inReplyTo":"xmqqk3cfuksd.fsf@gitster.dls.corp.google.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-02-28T23:22:09Z","receivedAt":"2014-02-28T23:22:09Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sat, Mar 1, 2014 at 1:58 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Karsten Blees <karsten.blees@gmail.com> writes:\n>\n>>> If you are on a case-insensitive filesystem, or work on a cross-platform\n>>> project, ensure that you avoid ambiguous refs. Problem solved.\n>>>\n>>\n>> So its OK to lose data if you accidentally use an ambiguous ref? I\n>> cannot believe you actually meant that.\n>\n> I think he meant what he said: \"you avoid ambiguous refs\".  He did\n> not say \"it is not Git's business to help you doing so\".\n>\n> I think it is prudent to warn in the end-user facing layer (read: do\n> not touch refs.c to implement something like that) when the user\n> creates \"refs/heads/Next\" when there already is \"refs/heads/next\",\n> and I further think it would make sense to do so even on case\n> sensitive platforms.\n\nThat does not help when the user creates \"next\" and pulls \"Next\" from\nelsewhere, does it?\n-- \nDuy\n"},{"id":"235678","messageId":"xmqq7g8eu891.fsf@gitster.dls.corp.google.com","threadId":"35964","inReplyTo":"CACsJy8A6etyFkxn3D7hjM9JgzmokPBARXrEncVuw1x+OOHJ_Lg@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-02-28T23:28:58Z","receivedAt":"2014-02-28T23:28:58Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> On Sat, Mar 1, 2014 at 1:58 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Karsten Blees <karsten.blees@gmail.com> writes:\n>>\n>>>> If you are on a case-insensitive filesystem, or work on a cross-platform\n>>>> project, ensure that you avoid ambiguous refs. Problem solved.\n>>>>\n>>>\n>>> So its OK to lose data if you accidentally use an ambiguous ref? I\n>>> cannot believe you actually meant that.\n>>\n>> I think he meant what he said: \"you avoid ambiguous refs\".  He did\n>> not say \"it is not Git's business to help you doing so\".\n>>\n>> I think it is prudent to warn in the end-user facing layer (read: do\n>> not touch refs.c to implement something like that) when the user\n>> creates \"refs/heads/Next\" when there already is \"refs/heads/next\",\n>> and I further think it would make sense to do so even on case\n>> sensitive platforms.\n>\n> That does not help when the user creates \"next\" and pulls \"Next\" from\n> elsewhere, does it?\n\nThat depends on what the project policy would be.  At that point,\nthat user needs to talk with the \"elsewhere\" person and resolve the\nissue (if there is one) according to the policy of their project,\nand it is not Git's business to _solve_ it for them.  Warning I\nsuggested was a way to help avoiding without getting in a way of\nprojects whose policy is to allow these.\n"},{"id":"235688","messageId":"CAJHY66EP539ZsLJcmHcnRQcOqcLqXK-M45wME9DkKkqmumg8fA@mail.gmail.com","threadId":"35964","inReplyTo":"xmqq7g8eu891.fsf@gitster.dls.corp.google.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-03-01T02:42:12Z","receivedAt":"2014-03-01T02:42:12Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"I went ahead and took a stab at a solution. My solution is more\naggressive than a warning, I actually prevent the creation of\nambiguous refs. My changes are also in refs.c, which may not be\nappropriate, but it seemed like the natural place.\n\nI have never contributed to Git (in fact this is my first dive into\nthe source) and my C is a bit rusty, so bear with me, this is just a\nsuggestion:\n\n---\n refs.c |   31 ++++++++++++++++++++++++-------\n 1 files changed, 24 insertions(+), 7 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 89228e2..12ccdac 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -359,14 +359,24 @@ struct string_slice {\n  const char *str;\n };\n\n+static int ref_entry_ncmp(const void *key_, const void *ent_, int\n(*cmp_fn)(const char *, const char *, size_t))\n+{\n+    const struct string_slice *key = key_;\n+    const struct ref_entry *ent = *(const struct ref_entry * const *)ent_;\n+    int cmp = cmp_fn(key->str, ent->name, key->len);\n+    if (cmp)\n+        return cmp;\n+    return '\\0' - (unsigned char)ent->name[key->len];\n+}\n+\n static int ref_entry_cmp_sslice(const void *key_, const void *ent_)\n {\n- const struct string_slice *key = key_;\n- const struct ref_entry *ent = *(const struct ref_entry * const *)ent_;\n- int cmp = strncmp(key->str, ent->name, key->len);\n- if (cmp)\n- return cmp;\n- return '\\0' - (unsigned char)ent->name[key->len];\n+ return ref_entry_ncmp(key_, ent_, strncmp);\n+}\n+\n+static int ref_entry_casecmp_sslice(const void *key_, const void *ent_)\n+{\n+    return ref_entry_ncmp(key_, ent_, strncasecmp);\n }\n\n /*\n@@ -378,6 +388,7 @@ static int search_ref_dir(struct ref_dir *dir,\nconst char *refname, size_t len)\n {\n  struct ref_entry **r;\n  struct string_slice key;\n+    int (*cmp_fn)(const void *, const void *);\n\n  if (refname == NULL || !dir->nr)\n  return -1;\n@@ -385,8 +396,14 @@ static int search_ref_dir(struct ref_dir *dir,\nconst char *refname, size_t len)\n  sort_ref_dir(dir);\n  key.len = len;\n  key.str = refname;\n+\n+    if(ignore_case)\n+        cmp_fn = ref_entry_casecmp_sslice;\n+    else\n+        cmp_fn = ref_entry_cmp_sslice;\n+\n  r = bsearch(&key, dir->entries, dir->nr, sizeof(*dir->entries),\n-    ref_entry_cmp_sslice);\n+    cmp_fn);\n\n  if (r == NULL)\n  return -1;\n--\n"},{"id":"235698","messageId":"53118436.5080507@web.de","threadId":"35964","inReplyTo":"CAJHY66EP539ZsLJcmHcnRQcOqcLqXK-M45wME9DkKkqmumg8fA@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2014-03-01T06:54:46Z","receivedAt":"2014-03-01T06:54:46Z","isPatch":false,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2014-03-01 03.42, Lee Hopkins wrote:\n> I went ahead and took a stab at a solution. My solution is more\n> aggressive than a warning, I actually prevent the creation of\n> ambiguous refs. My changes are also in refs.c, which may not be\n> appropriate, but it seemed like the natural place.\n> \n> I have never contributed to Git (in fact this is my first dive into\n> the source) and my C is a bit rusty, so bear with me, this is just a\n> suggestion:\n> \n> ---\n>  refs.c |   31 ++++++++++++++++++++++++-------\n>  1 files changed, 24 insertions(+), 7 deletions(-)\n> \n> diff --git a/refs.c b/refs.c\n> index 89228e2..12ccdac 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -359,14 +359,24 @@ struct string_slice {\n>   const char *str;\n>  };\n> \n> +static int ref_entry_ncmp(const void *key_, const void *ent_, int\n> (*cmp_fn)(const char *, const char *, size_t))\n> +{\n> +    const struct string_slice *key = key_;\n> +    const struct ref_entry *ent = *(const struct ref_entry * const *)ent_;\n> +    int cmp = cmp_fn(key->str, ent->name, key->len);\n> +    if (cmp)\n> +        return cmp;\n> +    return '\\0' - (unsigned char)ent->name[key->len];\n> +}\n> +\n>  static int ref_entry_cmp_sslice(const void *key_, const void *ent_)\n>  {\n> - const struct string_slice *key = key_;\n> - const struct ref_entry *ent = *(const struct ref_entry * const *)ent_;\n> - int cmp = strncmp(key->str, ent->name, key->len);\n> - if (cmp)\n> - return cmp;\n> - return '\\0' - (unsigned char)ent->name[key->len];\n> + return ref_entry_ncmp(key_, ent_, strncmp);\n> +}\n> +\n> +static int ref_entry_casecmp_sslice(const void *key_, const void *ent_)\n> +{\n> +    return ref_entry_ncmp(key_, ent_, strncasecmp);\n>  }\n> \n>  /*\n> @@ -378,6 +388,7 @@ static int search_ref_dir(struct ref_dir *dir,\n> const char *refname, size_t len)\n>  {\n>   struct ref_entry **r;\n>   struct string_slice key;\n> +    int (*cmp_fn)(const void *, const void *);\n> \n>   if (refname == NULL || !dir->nr)\n>   return -1;\n> @@ -385,8 +396,14 @@ static int search_ref_dir(struct ref_dir *dir,\n> const char *refname, size_t len)\n>   sort_ref_dir(dir);\n>   key.len = len;\n>   key.str = refname;\n> +\n> +    if(ignore_case)\nOnly looking at ignore_case here closes the door for people\nwho have a branch \"foo\" and \"Foo\" at the same time.\n(Which means that they are carefully running git pack-refs)\nHow about something like this:\n +    if (refs_ignore_case < 0)\n +      refs_ignore_case = ignore_case;\n +    if (refs_ignore_case)\n(And then we need the diff further down on top of this.)\n(And of course Documentation/config.txt)\nThe main motivation is that you can set refs.ignorecase == true on\ne.g. Linux, to prevent to have branches \"Foo\" and \"foo\" at the same time,\nwhich gives problems when pulling into e.g. Windows/Mac OS\n> +        cmp_fn = ref_entry_casecmp_sslice;\n> +    else\n> +        cmp_fn = ref_entry_cmp_sslice;\n> +\n>   r = bsearch(&key, dir->entries, dir->nr, sizeof(*dir->entries),\n> -    ref_entry_cmp_sslice);\n> +    cmp_fn);\n> \n>   if (r == NULL)\n>   return -1;\n> --\n\n\n\n\ndiff --git a/builtin/init-db.c b/builtin/init-db.c\nindex c7c76bb..dbfc61f 100644\n--- a/builtin/init-db.c\n+++ b/builtin/init-db.c\n@@ -288,8 +288,10 @@ static int create_default_files(const char *template_path)\n                /* Check if the filesystem is case-insensitive */\n                path[len] = 0;\n                strcpy(path + len, \"CoNfIg\");\n-               if (!access(path, F_OK))\n-                       git_config_set(\"core.ignorecase\", \"true\");\n+               if (!access(path, F_OK)) {\n+                       git_config_set(\"core.ignorecase\", \"true\");\n+                       git_config_set(\"refs.ignorecase\", \"true\");\n+               }\n                probe_utf8_pathname_composition(path, len);\n        }\n \ndiff --git a/config.c b/config.c\nindex d969a5a..8f1ec81 100644\n--- a/config.c\n+++ b/config.c\n@@ -698,6 +698,11 @@ static int git_default_core_config(const char *var, const char *value)\n                return 0;\n        }\n \n+       if (!strcmp(var, \"refs.ignorecase\")) {\n+               refs_ignore_case = git_config_bool(var, value);\n+               return 0;\n+       }\n+\n        if (!strcmp(var, \"core.attributesfile\"))\n                return git_config_pathname(&git_attributes_file, var, value);\n \ndiff --git a/environment.c b/environment.c\nindex 4a3437d..2eced48 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -18,6 +18,7 @@ int check_stat = 1;\n int has_symlinks = 1;\n int minimum_abbrev = 4, default_abbrev = 7;\n int ignore_case;\n+int refs_ignore_case = -1;\n int assume_unchanged;\n int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\n"},{"id":"235759","messageId":"CAJHY66G9WkL7sk99GhiyxjWCTkX_ip7Qb8P5gF9ovgQ-A+Yjyw@mail.gmail.com","threadId":"35964","inReplyTo":"53118436.5080507@web.de","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-03-01T19:38:47Z","receivedAt":"2014-03-01T19:38:47Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"Incorporating Torsten suggestions and some documentation:\n\n---\n Documentation/config.txt |   12 ++++++++++++\n builtin/init-db.c        |    4 +++-\n config.c                 |    5 +++++\n environment.c            |    1 +\n refs.c                   |   26 +++++++++++++++++++++++---\n 5 files changed, 44 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 040197b..c0a6c5c 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -2077,6 +2077,18 @@ receive.shallowupdate::\n  If set to true, .git/shallow can be updated when new refs\n  require new shallow roots. Otherwise those refs are rejected.\n\n+refs.ignorecase::\n+ If true, this option prevents the creation of ref names\n+ that differ in case only. For example, if a branch Foo exists,\n+ `git checkout -b foo` would fail. This is the case\n+ across ref hierarchies, so `git tag foo` would also fail.\n+ This option is useful on filesystems that are not case\n+ sensitive.\n++\n+The default is false, except linkgit:git-clone[1] or linkgit:git-init[1]\n+will probe and set refs.ignorecase true if appropriate when the repository\n+is created. refs.ignorecase will also be true if core.ignorecase is true.\n+\n remote.pushdefault::\n  The remote to push to by default.  Overrides\n  `branch.<name>.remote` for all branches, and is overridden by\ndiff --git a/builtin/init-db.c b/builtin/init-db.c\nindex c7c76bb..7c6931b 100644\n--- a/builtin/init-db.c\n+++ b/builtin/init-db.c\n@@ -288,8 +288,10 @@ static int create_default_files(const char *template_path)\n  /* Check if the filesystem is case-insensitive */\n  path[len] = 0;\n  strcpy(path + len, \"CoNfIg\");\n- if (!access(path, F_OK))\n+ if (!access(path, F_OK)) {\n  git_config_set(\"core.ignorecase\", \"true\");\n+ git_config_set(\"refs.ignorecase\", \"true\");\n+ }\n  probe_utf8_pathname_composition(path, len);\n  }\n\ndiff --git a/config.c b/config.c\nindex 314d8ee..797391a 100644\n--- a/config.c\n+++ b/config.c\n@@ -702,6 +702,11 @@ static int git_default_core_config(const char\n*var, const char *value)\n  return 0;\n  }\n\n+ if (!strcmp(var, \"refs.ignorecase\")) {\n+ refs_ignore_case = git_config_bool(var, value);\n+ return 0;\n+ }\n+\n  if (!strcmp(var, \"core.attributesfile\"))\n  return git_config_pathname(&git_attributes_file, var, value);\n\ndiff --git a/environment.c b/environment.c\nindex 4a3437d..2eced48 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -18,6 +18,7 @@ int check_stat = 1;\n int has_symlinks = 1;\n int minimum_abbrev = 4, default_abbrev = 7;\n int ignore_case;\n+int refs_ignore_case = -1;\n int assume_unchanged;\n int prefer_symlink_refs;\n int is_bare_repository_cfg = -1; /* unspecified */\ndiff --git a/refs.c b/refs.c\nindex 89228e2..1915ec2 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -359,16 +359,26 @@ struct string_slice {\n  const char *str;\n };\n\n-static int ref_entry_cmp_sslice(const void *key_, const void *ent_)\n+static int ref_entry_ncmp(const void *key_, const void *ent_, int\n(*cmp_fn)(const char *, const char *, size_t))\n {\n  const struct string_slice *key = key_;\n  const struct ref_entry *ent = *(const struct ref_entry * const *)ent_;\n- int cmp = strncmp(key->str, ent->name, key->len);\n+ int cmp = cmp_fn(key->str, ent->name, key->len);\n  if (cmp)\n  return cmp;\n  return '\\0' - (unsigned char)ent->name[key->len];\n }\n\n+static int ref_entry_cmp_sslice(const void *key_, const void *ent_)\n+{\n+ return ref_entry_ncmp(key_, ent_, strncmp);\n+}\n+\n+static int ref_entry_casecmp_sslice(const void *key_, const void *ent_)\n+{\n+ return ref_entry_ncmp(key_, ent_, strncasecmp);\n+}\n+\n /*\n  * Return the index of the entry with the given refname from the\n  * ref_dir (non-recursively), sorting dir if necessary.  Return -1 if\n@@ -378,6 +388,7 @@ static int search_ref_dir(struct ref_dir *dir,\nconst char *refname, size_t len)\n {\n  struct ref_entry **r;\n  struct string_slice key;\n+ int (*cmp_fn)(const void *, const void *);\n\n  if (refname == NULL || !dir->nr)\n  return -1;\n@@ -385,8 +396,17 @@ static int search_ref_dir(struct ref_dir *dir,\nconst char *refname, size_t len)\n  sort_ref_dir(dir);\n  key.len = len;\n  key.str = refname;\n+\n+ if(refs_ignore_case < 0)\n+ refs_ignore_case  = ignore_case;\n+\n+ if(ignore_case)\n+ cmp_fn = ref_entry_casecmp_sslice;\n+ else\n+ cmp_fn = ref_entry_cmp_sslice;\n+\n  r = bsearch(&key, dir->entries, dir->nr, sizeof(*dir->entries),\n-    ref_entry_cmp_sslice);\n+ cmp_fn);\n\n  if (r == NULL)\n  return -1;\n--\n"},{"id":"235858","messageId":"53145375.4040802@gmail.com","threadId":"35964","inReplyTo":"53118436.5080507@web.de","subject":"Re: Branch Name Case Sensitivity","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2014-03-03T10:03:33Z","receivedAt":"2014-03-03T10:03:33Z","isPatch":false,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Am 01.03.2014 07:54, schrieb Torsten Bögershausen:\n> On 2014-03-01 03.42, Lee Hopkins wrote:\n>> +\n>> +    if(ignore_case)\n> Only looking at ignore_case here closes the door for people\n> who have a branch \"foo\" and \"Foo\" at the same time.\n> (Which means that they are carefully running git pack-refs)\n> How about something like this:\n>  +    if (refs_ignore_case < 0)\n>  +      refs_ignore_case = ignore_case;\n>  +    if (refs_ignore_case)\n\nI don't think this distinction is necessary, either you have a case-insensitive file system or you don't. The case that the .git directory is case-sensitive and the worktree directory isn't (or the other way around) is probably so exotic that we can ignore it.\n\n> (And then we need the diff further down on top of this.)\n> (And of course Documentation/config.txt)\n> The main motivation is that you can set refs.ignorecase == true on\n> e.g. Linux, to prevent to have branches \"Foo\" and \"foo\" at the same time,\n> which gives problems when pulling into e.g. Windows/Mac OS\n\nIf you want to prevent problems with Windows/Mac OS, you should set core.ignorecase = true. I don't see why we need yet another config setting for refs (and logs?).\n"},{"id":"235873","messageId":"CAJHY66Hmq6ffv73MuK85k4_11TO_hysncZ5SveeW4WF52ZfTkA@mail.gmail.com","threadId":"35964","inReplyTo":"53145375.4040802@gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-03-03T14:21:10Z","receivedAt":"2014-03-03T14:21:10Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"> I don't think this distinction is necessary, either you have a case-insensitive file system or you don't. The case\n> that the .git directory is case-sensitive and the worktree directory isn't (or the other way around) is\n> probably so exotic that we can ignore it.\n\nI think Torsten's use case was for someone who is carefully curating\ntheir loose and packed-refs, e.g. gc.packrefs = false. This could be\nfor backwards compatibility (existing ambiguous refs whose names\ncannot be changed for some reason) or simply because they want to.\n\n> If you want to prevent problems with Windows/Mac OS, you should set core.ignorecase = true. I don't see why we need\n> yet another config setting for refs (and logs?).\n\nSince refs.ignorecase falls back to core.ignorecase, you could just\nset core.ignorecase = true and feel safe when sharing with Windows/Mac\nOS. I think having the distinction just makes Git more flexible, OTOH\nI can see how having both refs.ignorecase and core.ignorecase could be\nconfusing and possibly redundant.\n"},{"id":"235889","messageId":"xmqqsiqzrwzr.fsf@gitster.dls.corp.google.com","threadId":"35964","inReplyTo":"CAJHY66EP539ZsLJcmHcnRQcOqcLqXK-M45wME9DkKkqmumg8fA@mail.gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-03-03T17:51:52Z","receivedAt":"2014-03-03T17:51:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lee Hopkins <leerhop@gmail.com> writes:\n\n> I went ahead and took a stab at a solution. My solution is more\n> aggressive than a warning, I actually prevent the creation of\n> ambiguous refs. My changes are also in refs.c, which may not be\n> appropriate, but it seemed like the natural place.\n>\n> I have never contributed to Git (in fact this is my first dive into\n> the source) and my C is a bit rusty, so bear with me, this is just a\n> suggestion:\n>\n> ---\n>  refs.c |   31 ++++++++++++++++++++++++-------\n>  1 files changed, 24 insertions(+), 7 deletions(-)\n\nStarting something like this from forbidding is likely to turn out\nto be a very bad idea that can break existing repositories.\n\nA new configuration\n\n\trefs.caseInsensitive = {warn|error|allow}\n\nthat defaults to \"warn\" and the user can choose to set to \"error\" to\nforbid, would be more palatable, I would say.\n\nIf the variable is not in 'core.' namespace, you should implement\nthis check at the Porcelain level, allowing lower-level tools like\nupdate-ref as an escape hatch that let users bypass the restriction\nto be used to correct breakages; it would mean an unconditional \"if\n!stricmp(), it is an error\" in refs.c will not work well.\n\nI think it might be OK to have\n\n\tcore.allowCaseInsentitiveRefs = {yes|no|warn}\n\nwhich defaults to 'warn' (and 'yes' corresponds to 'allow', 'no'\ncorresponds to 'error', in the previous suggestion), instead. If we\nwanted to prevent even lower-level tools like update-ref from\nbypassing the check, that is.\n"},{"id":"235991","messageId":"5315D3B9.6050602@gmail.com","threadId":"35964","inReplyTo":"xmqqsiqzrwzr.fsf@gitster.dls.corp.google.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Karsten Blees","fromEmail":"karsten.blees@gmail.com","sentAt":"2014-03-04T13:23:05Z","receivedAt":"2014-03-04T13:23:05Z","isPatch":false,"sender":{"key":"karsten.blees@gmail.com","avatar":"https://avatars.githubusercontent.com/u/1111200?v=4"},"body":"Am 03.03.2014 18:51, schrieb Junio C Hamano:\n> Lee Hopkins <leerhop@gmail.com> writes:\n> \n>> I went ahead and took a stab at a solution. My solution is more\n>> aggressive than a warning, I actually prevent the creation of\n>> ambiguous refs. My changes are also in refs.c, which may not be\n>> appropriate, but it seemed like the natural place.\n>>\n>> I have never contributed to Git (in fact this is my first dive into\n>> the source) and my C is a bit rusty, so bear with me, this is just a\n>> suggestion:\n>>\n>> ---\n>>  refs.c |   31 ++++++++++++++++++++++++-------\n>>  1 files changed, 24 insertions(+), 7 deletions(-)\n> \n> Starting something like this from forbidding is likely to turn out\n> to be a very bad idea that can break existing repositories.\n> \n\nIts sure worth considering what should be done with pre-existing duplicates. However, repositories with such refs are already broken on case-insensitive filesystems, and allowing something that's known to be broken is even more dangerous, IMO.\n\nAn alternative approach could be to encode upper-case letters in loose refs if core.ignorecase == true (e.g. \"Foo\" -> \"%46oo\"). Although this may pose a problem for commands that bypass the refs API / plumbing for whatever reason.\n\n> A new configuration\n> \n> \trefs.caseInsensitive = {warn|error|allow}\n> \n\ns/caseInsensitive/caseSensitive/\nIts case-sensitive refs that cause trouble, case-insensitive refs would be fine on all platforms.\n\nI still don't see why we need an extra setting for this. The problems are inherently caused by case-insensitive filesystems, and we already have 'core.ignorecase' for that (its even automatically configured). Having an extra setting for refs is somewhat like making 'core.ignorecase' configurable per sub-directory.\n\n> that defaults to \"warn\" and the user can choose to set to \"error\" to\n> forbid, would be more palatable, I would say.\n> \n> If the variable is not in 'core.' namespace, you should implement\n> this check at the Porcelain level, allowing lower-level tools like\n> update-ref as an escape hatch that let users bypass the restriction\n> to be used to correct breakages; it would mean an unconditional \"if\n> !stricmp(), it is an error\" in refs.c will not work well.\n> \n> I think it might be OK to have\n> \n> \tcore.allowCaseInsentitiveRefs = {yes|no|warn}\n> \n> which defaults to 'warn' (and 'yes' corresponds to 'allow', 'no'\n> corresponds to 'error', in the previous suggestion), instead. If we\n> wanted to prevent even lower-level tools like update-ref from\n> bypassing the check, that is.\n> \n\nIts the plumbing that's broken, so implementing checks at the porcelain level won't help much. In particular, git-update-ref currently drops branches (or resets them to an earlier state) and messes up reflogs.\n"},{"id":"236037","messageId":"53163992.20701@web.de","threadId":"35964","inReplyTo":"5315D3B9.6050602@gmail.com","subject":"Re: Branch Name Case Sensitivity","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2014-03-04T20:37:38Z","receivedAt":"2014-03-04T20:37:38Z","isPatch":false,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2014-03-04 14.23, Karsten Blees wrote:\n> Am 03.03.2014 18:51, schrieb Junio C Hamano:\n>> Lee Hopkins <leerhop@gmail.com> writes:\n>>\n>>> I went ahead and took a stab at a solution. My solution is more\n>>> aggressive than a warning, I actually prevent the creation of\n>>> ambiguous refs. My changes are also in refs.c, which may not be\n>>> appropriate, but it seemed like the natural place.\n>>>\n>>> I have never contributed to Git (in fact this is my first dive into\n>>> the source) and my C is a bit rusty, so bear with me, this is just a\n>>> suggestion:\n>>>\n>>> ---\n>>>  refs.c |   31 ++++++++++++++++++++++++-------\n>>>  1 files changed, 24 insertions(+), 7 deletions(-)\n>>\n>> Starting something like this from forbidding is likely to turn out\n>> to be a very bad idea that can break existing repositories.\n>>\n> \n> Its sure worth considering what should be done with pre-existing duplicates. However, repositories with such refs are already broken on case-insensitive filesystems, and allowing something that's known to be broken is even more dangerous, IMO.\n> \n> An alternative approach could be to encode upper-case letters in loose refs if core.ignorecase == true (e.g. \"Foo\" -> \"%46oo\"). Although this may pose a problem for commands that bypass the refs API / plumbing for whatever reason.\n> \n>> A new configuration\n>>\n>> \trefs.caseInsensitive = {warn|error|allow}\n>>\n> \n> s/caseInsensitive/caseSensitive/\n> Its case-sensitive refs that cause trouble, case-insensitive refs would be fine on all platforms.\n> \n> I still don't see why we need an extra setting for this. The problems are inherently caused by case-insensitive filesystems, and we already have 'core.ignorecase' for that (its even automatically configured). Having an extra setting for refs is somewhat like making 'core.ignorecase' configurable per sub-directory.\nI start to agree here.\nThe case-insensitive file system does not allow branches foo and Foo at the same time,\nand the packed refs should simply follow this convention/restriction/behaviour.\n\n(and everything else could and should go into another patch:\n If we ever want Linux to ignore the case in refs,\n to ease the cross-platform development with Windows.\n Or if we allow Windows/Mac OS to handle case insensitive refs (by always packing them)\n to ease the co-working with e.g. Linux.\n)\n\nLee, could you improve your change in refs.c into a real patch, with a commit message?\n(And please have a look at the indentation with TABs)\n\nA test case could be good, if time allows I can make a suggestion.\n\nThanks for all comments\n/Torsten\n \n"},{"id":"236084","messageId":"CAJHY66Fu-b8ugy7im=JtEQtYKFe5VVutMpCZGxYP0xCzeuzT_Q@mail.gmail.com","threadId":"35964","inReplyTo":"53163992.20701@web.de","subject":"Re: Branch Name Case Sensitivity","fromName":"Lee Hopkins","fromEmail":"leerhop@gmail.com","sentAt":"2014-03-05T14:02:48Z","receivedAt":"2014-03-05T14:02:48Z","isPatch":false,"sender":{"key":"leerhop@gmail.com","avatar":null},"body":"> Lee, could you improve your change in refs.c into a real patch, with a commit message?\n> (And please have a look at the indentation with TABs)\n>\n> A test case could be good, if time allows I can make a suggestion.\n\nI will remove the refs.ignorecase flag and work on a test care or two,\nit will have to wait a few days tho.\n\n> (and everything else could and should go into another patch:\n>  If we ever want Linux to ignore the case in refs,\n>  to ease the cross-platform development with Windows.\n>  Or if we allow Windows/Mac OS to handle case insensitive refs (by always packing them)\n>  to ease the co-working with e.g. Linux.\n> )\n\nI was actually planning on tying to add this to my changes if they\ngained any traction. Why is another patch desirable?\n\n> If the variable is not in 'core.' namespace, you should implement\n> this check at the Porcelain level, allowing lower-level tools like\n> update-ref as an escape hatch that let users bypass the restriction\n> to be used to correct breakages; it would mean an unconditional \"if\n> !stricmp(), it is an error\" in refs.c will not work well.\n>\n> I think it might be OK to have\n>\n>         core.allowCaseInsentitiveRefs = {yes|no|warn}\n>\n> which defaults to 'warn' (and 'yes' corresponds to 'allow', 'no'\n> corresponds to 'error', in the previous suggestion), instead. If we\n> wanted to prevent even lower-level tools like update-ref from\n> bypassing the check, that is.\n\nI also would not mind working on either of Junio's suggestions if one\nis more desirable than what I already have.\n\n-Lee\n"}]}