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

Sco*_*ott 10 windows git branch github 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.
Run Code Online (Sandbox Code Playgroud)

执行 a 时git pull,有问题的分支大写。当我做一个git pull -p(修剪)时,它首先尝试删除分支的小写版本,然后创建大写版本。

远程分支大写 (origin/Abcorigin/Def)。

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

如果没有完全清除存储库(git clone尝试拉/取时,单独文件夹中的新文件不会拉出这些幻影分支),我能做些什么吗?

tor*_*rek 21

Git 对此感到精神分裂。1 Git 的一部分区分大小写的,所以branchHELLO和branchhello不同的分支。混帐的其他部分,在Windows和MacOS反正区分敏感,使分支HELLO和分支hello相同的分支。

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

要纠正问题:

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

    现在您的存储库已消除混淆,请删除任何错误的分支名称。您的临时名称包含您想要记住的值。您可以删除两者abc Abc如果其中一个或两个可能会搞砸。你remember-abc正确的哈希。

  2. 转到具有与您的分支不同的分支的 Linux 服务器计算机。(它总是一台 Linux 机器;这个问题在 Windows 或 MacOS 服务器上永远不会发生,因为它们很早就进行了大小写折叠,所以你永远不会首先创建问题。)在那里,重命名或删除有问题的坏名称。

    Linux 机器没有大小写问题——名称不同的分支总是不同的——所以这里没有什么奇怪的。可能需要几个步骤和一些git branch命令来列出所有名称,但最终,您将只拥有清晰明确的名称:不会有分支命名,Abc并且abc两者都有。

    如果Linux服务器上没有这样的问题,步骤2就是“什么都不做”。

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

  4. 现在重新创建的任何分支的名称,你想在本地和/或重命名您在步骤1举例来说,如果做你所做的临时名字remember-abc记住abc,你可以运行git branch -m remember-abc abc移动 remember-abcabc

    如果abc应该origin/abc设置为其上游,请立即执行:

    git branch --set-upstream-to=origin/abc abc
    
    Run Code Online (Sandbox Code Playgroud)

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

您可以使用多种快捷方式,而不是上面的 4 个步骤。我列出了四个这样的明确的目的:它应该是显而易见的,你什么每一步都旨在完成,如果你读的这剩下的,为什么你在做这一步。

出现问题的原因在nowox 的回答中有概述:Git 有时将分支名称存储在文件名中,有时将其作为字符串存储在数据文件中。由于Windows(和MacOS)倾向于使用文件名称混为一谈,文件名的变体保留了原有的情况,但忽略尝试创建另一种情况下变的名字的第二个文件,然后GIT中认为,Abcabc在其他方面的一样。data-in-a-file 变体保留了 case-distinction 和 value-distinction,并认为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,也许是混帐可以使用一个命名的文件refs/heads/6d6173746572,尽管这一半的可用组件的名称长度。(练习: 0x6d m、 0x61a等如何?)


1从技术上讲,这是错误的词。虽然它肯定是描述性的。一个更好的词可能是schizoid,正如《囚徒一集的标题中所使用的那样,但它也有错误的含义。这里的词根实际上是schism,意思是分裂和有点自我反对,这就是我们在这里所要推动的。

  • @nowox:除此之外,从某种意义上说,它*是* Git 的错:Git 不应该依赖于文件系统。这就是跨平台软件比仅仅停留在像 Linux 这样的友好系统上更难的原因。当然,当你想让人们看到和编辑*文件*时,“不依赖于文件系统”变得*极其*困难,但至少对于分支名称,这并不难——这个机制已经存在了,因为没有人应该依赖于各种 `.git/refs/` *files* 而是使用 `git rev-parse` 和 `git update-ref`。 (4认同)

now*_*wox 5

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

例如,您可能有abcdef上的文件.git/refs/heads

$ tree .git/refs/heads/
.git/refs/heads/
??? abc
??? def
??? master
Run Code Online (Sandbox Code Playgroud)

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

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

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

[branch "Abc"]
        remote = origin
        merge = refs/heads/abc
Run Code Online (Sandbox Code Playgroud)

请注意,在此示例中,远程分支已命名,Abc但本地分支是abc(小写)。

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

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


Sco*_*ott 5

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

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

我的.git/refs/remotes/origin目录引用了这些功能分支文件夹的小写版本。一些功能分支是在小写版本下创建的abcdef使用小写版本,但它们不再存在于远程。这些功能分支的创建者最近改用远程Abc使用。Def我删除.git/refs/remotes/origin/abc然后.git/refs/remotes/origin/def执行新git pull -p命令。新文件夹、AbcDef已创建,后续pulls 或fetches 正确显示Already up to date.

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

  • 使用“git pack-refs”*应该*有效,因为这*也会*删除“.git/refs/remotes/origin/*”(同时将*名称*留在打包文件中,但这些名称应该在`git fetch -p`)。编辑:啊,我忘了在推荐命令中添加 `--all` ,可能就是这样。 (4认同)