git - 不小心创建了不同大小写的重复分支(Master),如何将其移回master?
问题描述
在将数据从子分支移回master
分支时,我不小心创建了一个Master
分支(大写 M)。
Windows 上的工具集似乎没有注意到大小写的差异,在我的本地仓库中,我只有两个分支:
Directory of C:\Users\Me\source\repos\Me\MyProject\.git\logs\refs\remotes\origin
[.] [..] 64ThreadsPerBlock HEAD master
但是在远程我有三个分支:
64threadsPerBlock
Master
master
我该如何解决问题,以便遥控器没有 aMaster
并且它与本地同步master
?
解决方案
如果你在 Linux 系统上,这很容易,因为 Git总是区分大小写:readme
andREADME
是两个不同的文件,master
andMaster
是两个不同的分支。
如果您使用的是典型的 Windows 或 macOS 文件系统,并且本机文件名不区分大小写,1它会变得混乱:Git认为master
和Master
是两个不同的名称,但有时 将这些名称用作文件系统中的普通文件。然后它期望这两个不同的名称保持不同,但操作系统坚持不这样做。由于 Git 有时只这样做,但有时它会按照 Git 认为的方式工作。
您可以做的是利用两个事实:
- 另一个系统显然将这两个名称视为不同。
- Git 实际上并不关心分支名称是什么——它的拼写方式等——它只关心每个名称中存储的哈希 ID。
因此,解决问题的第一步是运行:
git ls-remote origin
这将吐出几行或多行输出,例如:
e2850a27a95c6f5b141dd88398b1702d2e524a81 HEAD
898f80736c75878acc02dc55672317fcc0e0a5a6 refs/heads/maint
e2850a27a95c6f5b141dd88398b1702d2e524a81 refs/heads/master
5d2a92d10f831493d4b0b258ee3cd18d4a7ae995 refs/heads/next
4141ae219919d2e29f3939983be8501770f247a3 refs/heads/seen
1637c5d31a0b0df8e3dcef7072720fe0381520ac refs/heads/todo
d5aef6e4d58cfe1549adef5b436f3ace984e8c86 refs/tags/gitgui-0.10.0
3d654be48f65545c4d3e35f5d3bbed5489820930 refs/tags/gitgui-0.10.0^{}
[... tons of tags snipped here]
左边的东西,在每一列中,是原始哈希 ID。 这个原始哈希 ID 是 Git 关心的。 右边是另一个 Git 存储库存储原始哈希 ID 的名称。refs/heads/*
名称是它们的分支名称。
您可能希望将所有这些输出保存在一个文件中。还要注意,我们指望另一个 Git 存储库在我们工作时不会对其进行任何更改。如果它是一个高度活跃的存储库,那么您最好启动一个 Linux 系统(或 Linux VM)并在其中执行普通的 Git 操作。
(旁注:git ls-remote -h origin
将输出修剪为仅分支名称,如果有很多标签,这会非常方便。)
1从技术上讲,每个文件系统都区分大小写。在 macOS 上,您可以轻松地设置区分大小写的磁盘映像、挂载、克隆并在那里修复所有内容,甚至无需使用 VM。可能也有适用于 Windows 系统的区分大小写的文件系统,但我不知道,也不知道是否有任何像 macOS “.dmg” 技巧这样相对简单的东西。
第 1 步之后要做什么
如果他们master
和Master
都存储相同的原始哈希 ID,您现在可以要求他们删除两个名称之一:
git push --delete origin Master
(假设您要删除的那个是带有一个大写字母的那个M
)。你现在完成了。
如果它们master
和Master
存储不同的原始哈希 ID,您现在必须弄清楚该怎么做。您将删除这两个名称之一。如果他们master
在他们之前Master
,你可以做同样的事情,如果他们是平等的:只需删除他们的Master
. 但是,如果他们master
落后于他们Master
,或者两者都领先和落后,你就不能完全做到这一点,至少不安全。
理解这一点需要了解“领先”和“落后”的实际含义。在 Git 中,提交哈希 ID 是有向无环图或DAG的一部分。我们需要简要介绍一下图论和偏序集。
偏序集
大多数人都熟悉我们得到的全序,例如整数:1 在 2 之前,2 在 3 之前。任何大于 3 的数字都在所有这些之后。
然而,在图表中,我们可以有一条简单的线:
A--B--C--D--...
或叉子:
C <-- last
/
A--B
\
D <-- also-last
这里,A 在 B 之前,B 在 C 和 D 之前,但我们不能说 C 在 D 之前或之后。从某种意义上说,它们都在同一个位置,就在 B 之后。
这也是 Git 提交的情况。如果每个大写字母都代表一些原始提交哈希,并且last
andalso-last
实际上是master
and Master
,那么我们就会遇到这样一种情况,即删除两个名称中的一个将使 Git 无法找到两个“最后”提交。Git 实际上通过使用标识每个“最后一次提交”的名称来工作,并从那里向后工作,因此 Git需要这两个名称来查找两个提交C
和D
此处。
将部分顺序的东西应用到 Git
用 Git 实用的术语来说,这意味着如果你能确定这master
真的是“之后” Master
——如果他们有:
...--G--H <-- Master
\
I <-- master
那么你就可以Master
安全地删除了。他们现在将拥有:
...--G--H--I <-- master
他们仍然可以找到所有的提交。
但如果这不安全,您应该让他们为以后的提交创建一个新名称。也就是说,如果他们有这个:
...--G--H <-- master
\
I <-- Master
或这个:
H <-- master
/
...--G
\
I <-- Master
那么你应该做的是在他们的 Git 存储库中创建一个新名称,该名称标识与他们的Master
. 为此,您可以运行:
git push origin <hash>:<new-name>
例如,如果他们的哈希 IDmaster
是deadbeef
,并且您选择 name 作为新分支名称save-for-now
,您将运行:
git push origin deadbeef:save-for-now
这将在他们的Git 存储库中创建这种情况:
H <-- master
/
...--G
\
I <-- Master, save-for-now
现在可以安全运行了:
git push origin --delete Master
要求他们删除他们的名字Master
:
H <-- master
/
...--G
\
I <-- save-for-now
请注意,如果您处于“安全”情况,例如当两个名称都标识相同的最后一次提交时,您仍然可以执行以下安全操作:
git push origin <hash>:save-for-now
创建:
...--G--H <-- Master, master, save-for-now
然后删除Master
给你:
...--G--H <-- master, save-for-now
(当然都在他们的Git 存储库中)。
现在你已经解决了问题,只需运行git fetch --prune origin
您现在可以让您的 Git 将您的存储库与他们的 Git 存储库重新同步。您可能需要运行git fetch --prune origin
两次,因为您的本地 Git 可能会Master
在更新后删除该名称master
,并且您的 Git 将该名称存储在一个文件中,您的 Git 可能会删除这两个名称,但这是安全的,因为第二个 git fetch
会恢复它。(一般来说,Git 似乎以 ASCII 顺序执行这些操作,以便一次提取可以正常工作,但我不知道这是否能保证过去和未来的所有 Git 版本。)
如果之前所有的提交都是安全的,那么您就可以安全地删除它们Master
,那么您现在就有了一个正常的设置,可以正常解决所有问题。如果它们以前不安全,那么您现在在自己的 Git 存储库中拥有一个origin/safe-for-now
远程跟踪名称。此名称与您的名称不冲突origin/master
,因此正常解决所有问题都没有问题。
换句话说,无论哪种方式,现在都可以安全地回去工作了。
推荐阅读
- c++ - 根据构造函数字符串文字声明 std::array 成员变量的大小
- javascript - 如何将 firebase 文档中的所有字段检索到地图或键:值对
- node.js - Express proxy + axios + cors:仍然是cors问题
- node.js - 连接到 mongodb 时遇到问题
- python - 为什么 to_datetime 在不分配给列而是变量时会导致错误?
- docker - 如何将实时 pcap 记录从 Kubernetes pod 传输到本地运行的 Wireshark?
- sql - 如何在 SQL 中“分组”日期
- apache-pulsar - Apache Pulsar 连接被拒绝
- mongodb - $group 结果作为键值对 mongo db
- python - 如何在python的数据框中为每个组制作每月箱线图