由于远程上有一些分支,我似乎对存储库不断在本地重新创建分支有问题。我在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/Abc
和origin/Def
)。
我试图临时更改我的Git配置,以使ignorecase=false
(当前为ignorecase=true
)。但是我注意到行为没有变化。我猜我的本地端当前正在保留那些小写的分支。但是git branch
不会在本地显示这些分支的任何版本。
完全淘汰存储库的时间(尝试拉/取操作时,单独文件夹中的新git clone
不会拉出这些幻像分支),我能做些什么吗?
答案 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
(小写)。
为解决您的问题,我将尝试:
.git/config
文件.git/refs/heads
中损坏的分支,例如abc
重命名为abc-old
git pull
答案 1 :(得分:2)
Git对此有精神分裂症。 1 Git的部分 区分大小写,因此分支HELLO
和分支hello
是不同的分支。无论如何,在Windows和MacOS上,Git的其他部分区分大小写 ,因此分支HELLO
和分支hello
是同一分支
结果是混乱。最好完全避免这种情况。
要纠正此问题,请执行以下操作:
设置一些您不会感到困惑的附加,私有和临时,分支或标签名称,以记住您真正关心的任何提交哈希ID本地存储库。然后运行git pack-refs --all
,以便打包所有引用。这会删除所有文件名,将所有引用都放入.git/packed-refs
平面文件中,其中的文件名区分大小写。现在,您的Git可以从Abc
中告诉您的abc
,如果两者都有。
现在,您的存储库已解除混乱,删除任何错误的分支名称。您的临时名称包含您要记住的值。如果其中一个或两个都弄乱了,则可以删除abc
和 Abc
。您的remember-abc
中包含正确哈希。
转到Linux服务器计算机,该计算机的分支仅与您的分支不同。 (它始终是Linux机器;在Windows或MacOS服务器上永远不会发生此问题,因为它们会尽早进行大小写折叠,因此您一开始就不会 create 。)在那里,重命名或删除冒犯恶名。
Linux机器的大小写没有问题-分支的名称仅在大小写不同的情况下总是不同的-因此这里没有任何怪异之处。列出所有名称可能需要一些步骤和一些git branch
命令,但是最终,您将只剩下清晰而独特的名称:将没有名为Abc
和{{ 1}}两者。
如果Linux服务器上没有此类问题,则步骤2为“什么都不做”。
在本地系统上使用abc
。现在,您不再具有任何坏名作为远程跟踪名,因为在第2步中,您确保服务器(您的本地Git呼叫git fetch --prune
的系统)没有坏名,并且您的本地Git已使您的本地origin
名称与它们的分支名称匹配。
现在重新创建本地所需的任何分支名称,和/或重命名在步骤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
相同。文件中数据变体保留大小写区分和值区分,并认为Abc
和abc
是两个不同的分支,标识了两个不同的提交。
当Abc
或abc
从git 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)
nowox和torek提供的答案非常有帮助,但没有确切的解决方案。 .git/config
中现有的对remote的引用以及git/refs/heads
中的文件不包含abc
或def
的任何版本。
相反,该问题存在于.git/refs/remotes/origin
中。
我的.git/refs/remotes/origin
目录引用了这些功能分支文件夹的小写版本。某些功能分支是使用小写版本在abc
和def
下创建的,但在远程不再存在。这些功能分支的创建者最近切换为在远程上使用Abc
和Def
。我删除了.git/refs/remotes/origin/abc
和.git/refs/remotes/origin/def
,然后执行了新的git pull -p
命令。创建了新文件夹Abc
和Def
,随后的pull
或fetch
正确显示了Already up to date.
感谢nowox和torek让我走上正轨!