GitHub分支:案例敏感性问题?

问题描述 投票:2回答:3

我似乎遇到了一个问题,即存储库不断在本地重新创建分支,因为远程上有一些分支。我在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在尝试拉取/取出时不会拉动这些幻影分支),有什么我可以做的吗?

windows git github branch case-sensitive
3个回答
2
投票

在Git上,分支只是提交的指针。分支在.git存储库中作为普通文件存储。

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

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

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

我不确定,但我认为选项ignorecase仅与您的工作目录相关,而不是.git文件夹。因此,要删除奇怪的大写分支,您可能只需要删除/重命名.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

2
投票

Git是关于此的精神分裂症.Git的部分区分大小写,因此分支HELLO和分支hello是不同的分支。无论如何,在Windows和MacOS上,Git的其他部分不区分大小写,因此分支HELLO和分支hello是相同的分支。

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

要纠正问题:

  1. 设置一些您不会感到困惑的其他,私有和临时的分支或标记名称,以便在您自己的本地存储库中记住您真正关心的任何提交哈希ID。然后运行git pack-refs --all以便打包所有引用。这将删除所有文件名,将所有引用放入.git/packed-refs平面文件中,其名称区分大小写。如果你有两个,你的Git现在可以从你的Abc告诉你的abc。 现在您的存储库被解除混淆,删除任何错误的分支名称。您的临时名称包含您要记住的值。你可以删除abcAbc,如果其中一个或两个可能搞砸了。你的remember-abc中有正确的哈希值。
  2. 转到具有不同分支的Linux服务器计算机,以防止与您的分支不同。 (它总是一台Linux机器;这个问题永远不会发生在Windows或MacOS服务器上,因为它们会尽早进行大小写折叠,以至于你从不创建问题。)在那里,重命名或删除有问题的坏名称。 Linux机器的case分支没有问题,只是在名称不同的情况下总是不同的 - 所以这里没有任何奇怪之处。它可能需要几个步骤,并且一些git branch命令列出所有名称,但最终,你将只有明确和不同的名称:没有名为Abcabc的分支。 如果Linux服务器上没有这样的问题,第2步是“什么都不做”。
  3. 在本地系统上使用git fetch --prune。您现在不再有任何坏名称作为远程跟踪名称,因为在第2步中,您确保服务器 - 您的本地Git调用origin的系统没有错误名称,并且您的本地Git已使您的本地origin/*名称匹配他们的分支名称。
  4. 现在重新创建你想要的任何分支名称,和/或重命名你在步骤1中创建的临时名称。例如,如果你让remember-abc记住abc,你可以运行git branch -m remember-abc abcremember-abc移动到abc。 如果abc应该将origin/abc设置为其上游,请立即执行此操作: git branch --set-upstream-to=origin/abc abc (当你创建remember-abc时,你可以在第1步中执行此操作,但我认为这更有意义,所以我将它放在第4步中。)

您可以使用各种快捷方式,而不是上述4个步骤。为了清楚起见,我以这种方式列出了所有这四个方面:对于每个步骤要完成的内容应该是显而易见的,如果您阅读其余内容,那么为什么要执行该步骤。

问题发生的原因在nowox's answer中概述:Git有时将分支名称存储在文件名中,有时将其作为字符串存储在数据文件中。由于Windows(和MacOS)倾向于使用文件名混淆,文件名变体保留其原始情况,但忽略尝试创建另一个案例变体名称的第二个文件,然后Git认为Abcabc是否则一样。文件中的数据变体保留了区分大小和区分值,并认为Abcabc是两个不同的分支,用于标识两个不同的提交。

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

设置core.ignorecase(对任何东西)根本没有帮助,因为这只影响Git在工作树中处理大小写折叠的方式。 Git内部数据库中的文件不受任何影响。

如果例如Git使用真实数据库来存储其<reference-name,hash-ID>表,则整个问题永远不会出现。使用单个文件在Linux上运行正常。它在Windows和MacOS上无法正常工作,不管怎么说都不行。如果Git没有将它们存储在具有可读名称的文件中,那么使用单个文件可以在那里工作 - 例如,而不是refs/heads/master,也许Git可以使用名为refs/heads/6d6173746572的文件,尽管这会将可用的组件名称长度减半。 (练习:0x6d m,0x61 a怎么样,依此类推?)


1技术上,这是错误的词。但它确实具有描述性。一个更好的词可能是精神分裂,正如one episode of The Prisoner的标题中所使用的那样,但它也有错误的含义。这里的根词真的是schism,意思是分裂和有点自相矛盾,这就是我们在这里开车的原因。


1
投票

nowoxtorek提供的答案非常有用,但没有包含确切的解决方案。在.git/config中对远程的现有引用,以及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,随后pulls或fetches正确显示Already up to date.

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

© www.soinside.com 2019 - 2024. All rights reserved.