远程分支存在,本地分支消失



好的,所以上下文是我在自己的分支上工作,为某个项目创建一个功能。

我的分支叫做Exif(大写E),今天我不小心做了

git push origin exif  (lowercase e)

所以它为我创建了一个名为Exif的新分支

在我意识到这一点之后,我做了

$ git push origin --delete exif
$ git branch -d exif

再次有效地删除分支。
我必须补充一点,当我在 Exif(大写 E)中签出时,我执行了这 2 行,但这应该无关紧要吧?

现在,当我执行

git status

我得到一个巨大的列表,说整个项目中的每个文件都是一个新文件

当我尝试时

git log

它说,你当前的分支还没有任何提交

当我这样做时

git branch -a

所有分支都在那里,除了Exif,它也不在远程分支列表中

但是在我们的 GitHubLab 服务器上,它很好地显示了分支,就像什么都没发生一样。

有谁知道这里发生了什么?

编辑:

在 eclipse 中,它在每个文件旁边显示一个星号,这意味着每个文件都被暂存。

在 eclipse 中,它还显示在根项目文件夹旁边,该项目具有 [NO-HEAD]

删除分支时,git 不区分大小写,这意味着如果你执行,你的分支"Exif"将被删除

git branch -d exif

您甚至没有首先创建分支"Exif",因为通过推送到不同的分支,您不会在本地存储库中自动创建该分支。

要返回到原始分支,我将通过再次签出远程分支来创建新的本地分支,如下所示:

git checkout origin/exif

这里的另一个答案不太正确,尽管这个:

但是在我们的 GitHubLab 服务器上,它很好地显示了分支,就像什么都没发生一样。

很有前途,因此您可能有一种简单的方法来解决问题。

我将展示一个我销毁自己的master分支的示例(当然是在克隆中)。 由于这个特定的系统区分大小写,我只是手动删除了master分支(在 Git 的背后,就像它一样)。

Git 错误:分支名称区分大小写,除非它们不区分大小写

这是 Git 中的一个错误:它设法删除了您站立的分支。

出现此问题是因为 Git区分大小写:就 Git 而言,分支exif与分支Exif完全分开。 当你要求 Git 删除exif它时,本质上,检查了:

  • 我在分行exif吗?
  • 如果是这样,请拒绝尝试,因为它会搞砸一切。
  • 否则,请继续删除exif

所以 Git 检查了一下,它看到你当前的分支是Exif,而不是exif。 好吧,对于 Git,这些显然是不同的,删除必须是安全的! 只。。。他们不是,也不是。 事实很复杂,但在 Windows 和 MacOS 系统上,Git 要么需要一些实现更改——这样分支名称才能始终区分大小写——要么 Git 需要停止相信它们是区分大小写的,因为它们有时(通常在这些系统上)不是

修复它

与此同时,棘手的部分是恢复您的分支。 这需要深入研究 Git 内部。

两部分

在 Git 中,当前分支有两个关键组件。 一个是文件.git/HEAD。 此文件包含一个简单的字符串:

$ cat .git/HEAD
ref: refs/heads/master
$ 

也就是说,此文件包含(作为纯文本:不是"富文本",不是Unicode,不是Windows UCS-2格式,只是简单的ASCII文本)文字字符串ref: refs/heads/,在refs/heads/之前有一个空格,后跟分支的名称,后跟换行符。 此文件安然无恙!

另一半则更为复杂。 好消息是大部分复杂性都消失了,因为如果没有,分支名称将在"其余方式"区分大小写,您可能(或可能不会)仍然可以。 但是这个:

$ git log
fatal: your current branch 'Exif' does not have any commits yet

证明分支值仅存储在文件.git/refs/heads/branchname中。

也就是说,您曾经有一个名为:

.git/refs/heads/Exif

其中有一些哈希值,类似于这个(但具有不同的哈希):

$ cat .git/refs/heads/master
3ab228137f980ff72dbdf5064a877d07bec76df9

我们需要做的是使用相同的值将该文件放回原处。

修复它:如果您有价值(或其中的一部分)

如果您可以在某处(例如,在现有窗口中)看到该值(甚至只是其中的一部分),则足以取回整个值。 例如,如果我在某处显示3ab228,我可以这样做:

$ git rev-parse 3ab228
3ab228137f980ff72dbdf5064a877d07bec76df9

这让我可以这样做来解决问题:

$ git rev-parse 3ab228 > .git/refs/heads/master

我们完成了。 (请参阅下面关于 reflogs 的最后一项。

修复它:如果您将其作为远程跟踪分支

如果您之前已成功推送分支,则可能具有远程跟踪分支的值:

$ git rev-parse origin/master
3ab228137f980ff72dbdf5064a877d07bec76df9

在这种情况下,您可以将其放回原位:

$ git rev-parse origin/master > .git/refs/heads/master

大功告成。 (请参阅下面关于 reflogs 的最后一项。

修复它:如果你的上游有它

在您的情况下,听起来名为origin的远程在名称exif(全部小写)下具有正确的哈希 ID,即由于某种原因它忽略了git push --delete命令。 在这种情况下,您可以向遥控器询问该值。 请注意,从那时起,其他人可能已经更新了它:

$ git ls-remote origin master
454cb6bd52a4de614a3633e4f547af03d5c3b640        refs/heads/master

(显然我的遥控器已经移动了,所以我无法使用它,但如果你幸运的话,你的遥控器没有)。 确保值正确:

$ git rev-parse 454cb6bd
454cb6bd
fatal: ambiguous argument '454cb6bd': unknown revision or path
not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

(所以这对我不起作用,因为他们确实已经离开了)。

作为最后的手段,您可以运行:

$ git fsck --unreachable

这很可能会吐出一大堆unreachable消息:

unreachable commit fcfbe9a1165e38467b4d24d41b3166a20c1dfb80
unreachable commit c8056a11ef8eee1bfaaaa2e32a9cc92a02eae2e0
unreachable blob 010a1a22a90b2bd78e6b87a3922c3324c44a8a9b
unreachable commit c1163ad1eeff0c86f030483907ea8cedcdd431e3
unreachable commit f35fc21adeb21e1a4800ccebd5719317efb968dc

忽略除"提交"之外的所有内容:其中一个是正确的。 要找出哪一个,请在每个上运行git show,也许有一些东西可以帮助缩短它们,例如:

$ git show --pretty=oneline --no-patch fcfbe9a1165e38467b4d24d41b3166a20c1dfb80
fcfbe9a1165e38467b4d24d41b3166a20c1dfb80 WIP on precious: e59f6c2 The last
minute bits of fixes

(这表明此特定项目实际上是git stash提交)。

当你找到合适的存储库时,你可以把它放到.git/refs/heads/Exif中来恢复价值,你的存储库将大部分恢复原状。git rev-parse方法在这里也有效,尽管由于您拥有完整的原始哈希,因此您实际上不必rev-parse它。

引用日志不见了;还有什么地方可以看

恢复分支文件可以修复分支并使一切准备就绪,例如:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

但是,分支的引用日志现在消失了:

$ git reflog master
$ 

HEAD的引用日志仍然有效,一旦您在分支上执行了更多操作,将重新创建分支的引用日志。

如果您的文件系统被备份(例如,通过 MacOS Time Machine,或通过在 Windows 网络驱动器上执行快照,或诸如此类),您可以查看系统备份。 如果幸运的话,您可能会在这些备份中找到分支文件reflog。

在这种情况下,您可以简单地将它们还原到位。 这与找到正确的哈希具有相同的效果,但是通过恢复 reflog,您可以取回您的 reflog。

最新更新