GitHub分支机构:区分大小写的问题?

时间:2019-03-07 19:46:02

标签: windows git github branch case-sensitive

由于远程上有一些分支,我似乎对存储库不断在本地重新创建分支有问题。我在Windows计算机上,因此我怀疑这是区分大小写的问题。

下面是几个命令示例:

$ git pull
From https://github.com/{my-repo}
 * [new branch]          Abc -> origin/Abc
 * [new branch]          Def -> origin/Def
Already up to date.

$ git pull -p
From https://github.com/{my-repo}
 - [deleted]             (none)     -> origin/abc
 - [deleted]             (none)     -> origin/def
 * [new branch]          Abc -> origin/Abc
 * [new branch]          Def -> origin/Def
Already up to date.

进行git pull时,所讨论的分支都大写。当我执行git pull -p(用于修剪)时,它首先尝试删除分支的小写版本,然后创建大写版本。

远程分支使用大写字母(origin/Abcorigin/Def)。

我试图临时更改我的Git配置,以使ignorecase=false(当前为ignorecase=true)。但是我注意到行为没有变化。我猜我的本地端当前正在保留那些小写的分支。但是git branch不会在本地显示这些分支的任何版本。

完全淘汰存储库的时间(尝试拉/取操作时,单独文件夹中的新git clone不会拉出这些幻像分支),我能做些什么吗?

3 个答案:

答案 0 :(得分:2)

在Git上,分支只是指向提交的指针。分支以纯文件格式存储在.git存储库中。

例如,您可能在abc上有def.git/refs/heads个文件。

$ tree .git/refs/heads/
.git/refs/heads/
├── abc
├── def
└── master

这些文件的内容只是分支指向的提交编号。

我不确定,但是我认为选项ignorecase仅与您的工作目录有关,而与.git文件夹无关。因此,要删除 weird 大写的分支,您可能只需要删除/重命名.git/refs/heads中的文件。

除此之外,从本地分支到远程分支的上游链接存储在.git/config文件中。在此文件中,您可能会有类似的内容:

[branch "Abc"]
        remote = origin
        merge = refs/heads/abc

在此示例中,请注意,远程分支名为Abc,而本地分支名为abc(小写)。

为解决您的问题,我将尝试:

  1. 修改.git/config文件
  2. 重命名.git/refs/heads中损坏的分支,例如abc重命名为abc-old
  3. 尝试您的git pull

答案 1 :(得分:2)

Git对此有精神分裂症。 1 Git的部分 区分大小写,因此分支HELLO和分支hello不同的分支。无论如何,在Windows和MacOS上,Git的其他部分区分大小写 ,因此分支HELLO和分支hello同一分支

结果是混乱。最好完全避免这种情况。

要纠正此问题,请执行以下操作:

  1. 设置一些您不会感到困惑的附加,私有和临时,分支或标签名称,以记住您真正关心的任何提交哈希ID本地存储库。然后运行git pack-refs --all,以便打包所有引用。这会删除所有文件名,将所有引用都放入.git/packed-refs平面文件中,其中的文件名区分大小写。现在,您的Git可以从Abc中告诉您的abc,如果两者都有。

    现在,您的存储库已解除混乱,删除任何错误的分支名称。您的临时名称包含您要记住的值。如果其中一个或两个都弄乱了,则可以删除abc Abc。您的remember-abc中包含正确哈希。

  2. 转到Linux服务器计算机,该计算机的分支仅与您的分支不同。 (它始终是Linux机器;在Windows或MacOS服务器上永远不会发生此问题,因为它们会尽早进行大小写折叠,因此您一开始就不会 create 。)在那里,重命名或删除冒犯恶名。

    Linux机器的大小写没有问题-分支的名称仅在大小写不同的情况下总是不同的-因此这里没有任何怪异之处。列出所有名称可能需要一些步骤和一些git branch命令,但是最终,您将只剩下清晰而独特的名称:将没有名为Abc和{{ 1}}两者。

    如果Linux服务器上没有此类问题,则步骤2为“什么都不做”。

  3. 在本地系统上使用abc。现在,您不再具有任何坏名作为远程跟踪名,因为在第2步中,您确保服务器(您的本地Git呼叫git fetch --prune的系统)没有坏名,并且您的本地Git已使您的本地origin名称与它们的分支名称匹配。

  4. 现在重新创建本地所需的任何分支名称,和/或重命名在步骤1中创建的临时名称。例如,如果您使origin/*记住了remember-abc,则可以只需运行abc即可移动 git branch -m remember-abc abc即可remember-abc

    如果abc应该将abc设置为其上游,请立即执行以下操作:

    origin/abc

    (您可以在创建git branch --set-upstream-to=origin/abc abc 时在步骤1中执行此操作,但我认为在这里更有意义,因此将其放在步骤4中。)

您可以使用多种快捷方式,而不是上面的4个步骤。为了清楚起见,我以这种方式列出了这四种方式:打算完成的每个步骤对您来说应该很明显;如果您阅读其余内容,那么为什么正在执行该步骤。

nowox's answer中概述了发生问题的原因:Git有时将分支名称存储在文件名中,有时将其作为字符串存储在数据文件中。由于Windows(和MacOS)倾向于使用文件名配置,因此文件名变体保留其原始大小写,但是忽略了尝试创建另一个具有其他大小写变体名称的文件的尝试,然后Git认为{{1} }和remember-abc 相同。文件中数据变体保留大小写区分和值区分,并认为Abcabc是两个不同的分支,标识了两个不同的提交。

Abcabcgit rev-parse refs/heads/abc(包含字符串的数据文件)获取其信息时,它将获取“正确的”信息。但是,当它从文件系统获取信息时,尝试打开git rev-parse refs/remotes/origin/abc.git/packed-refs实际上会打开.git/refs/heads/abc(如果该文件现在存在)或类似名称的远程跟踪变量(如果该文件存在),Git将获得“错误”信息。

.git/refs/remotes/origin/abc(设置为任何值)完全没有帮助,因为这只会影响Gem处理工作树中的案例折叠的方式。 。 Git内部数据库中的文件不会受到任何影响。

例如,如果Git使用真实的数据库来存储其<引用名称,哈希ID>表,则将永远不会出现整个问题。在Linux上使用单个文件可以正常工作。在Windows和MacOS上,它不能正常工作,无论如何不是这样。如果Git不会将单个文件存储在名称可读的文件中,则可以使用单个文件 进行操作-例如,代替.git/refs/heads/Abc,Git可以使用一个文件名为core.ignorecase的组件,尽管可以将可用组件名称的长度减半。 (锻炼:0x6d refs/heads/master,0x61 refs/heads/6d6173746572等如何?)


1 从技术上讲,这是错误的单词。它肯定是描述性的。 one episode of The Prisoner标题中使用的更好的词可能是 schizoid ,但它的含义也错误。此处的词根实际上是schism,表示分裂且有些自相矛盾,这就是我们在这里追求的目标。

答案 2 :(得分:1)

nowoxtorek提供的答案非常有帮助,但没有确切的解决方案。 .git/config中现有的对remote的引用以及git/refs/heads中的文件不包含abcdef的任何版本。

相反,该问题存在于.git/refs/remotes/origin中。

我的.git/refs/remotes/origin目录引用了这些功能分支文件夹的小写版本。某些功能分支是使用小写版本在abcdef下创建的,但在远程不再存在。这些功能分支的创建者最近切换为在远程上使用AbcDef。我删除了.git/refs/remotes/origin/abc.git/refs/remotes/origin/def,然后执行了新的git pull -p命令。创建了新文件夹AbcDef,随后的pullfetch正确显示了Already up to date.

感谢nowox和torek让我走上正轨!