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

Remote branch exists, local branch disappeared

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

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

git push origin exif  (lowercase e)

所以它为我创建了一个名为 exif

的新分支

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

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

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

现在,当我执行

git status

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

当我尝试时

git log

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

当我

git branch -a

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

但在我们的 gitlab 服务器上,它显示分支正常,就像什么也没发生一样。

有人知道这里发生了什么吗?

编辑:

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

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

删除分支时,git不区分大小写,这意味着如果您执行

,您的分支"Exif"将被删除
git branch -d exif

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

要返回原来的分支,我会通过再次检查远程分支来创建一个新的本地分支,如下所示:

git checkout origin/exif

这里的另一个答案不太正确,虽然这个:

but on our gitlab server it shows the branch just fine like nothing happened.

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

我将展示一个示例,其中我销毁了自己的 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
$ 

也就是说,这个文件包含(作为纯文本:不是 "rich text",不是 Unicode,不是 Windows UCS-2 格式,只是简单的 ASCII 文本)文字字符串 ref: refs/heads/ ,在 refs/heads/ 之前有一个 space,后跟分支名称,然后是换行符。此文件没有受到伤害!

另一半比较复杂。好消息是大部分并发症都消失了,因为如果没有,分支名称将区分大小写 "the rest of the way",您可能(或可能不会)仍然没问题。但是这个:

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

证明分支值仅存储在文件 .git/refs/heads/<em>branchname</em>.

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

.git/refs/heads/Exif

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

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

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

修复它:如果您有值(或部分值)

如果您可以看到值——甚至只是其中的一部分——某处,例如,在现有的window中,这足以获得整个值背部。例如,如果我在某处显示 3ab228,我可以这样做:

$ git rev-parse 3ab228
3ab228137f980ff72dbdf5064a877d07bec76df9

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

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

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

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

如果你之前已经成功推送了分支,你可能拥有远程跟踪分支的价值:

$ git rev-parse origin/master
3ab228137f980ff72dbdf5064a877d07bec76df9

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

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

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

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

在你的例子中,听起来像远程 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

忽略除 "commit" 之外的所有内容:其中之一是正确的。要找出哪一个,每个 运行 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 它。

reflog不见了;以及您还可以去哪里

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

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

但是,分支的 reflog 现已消失:

$ git reflog master
$ 

HEAD 的 reflog 仍然有效,一旦你在你的分支上做更多的事情,分支的 reflog 将被重新创建。

如果您的文件系统得到备份——例如,通过 MacOS Time Machine,或通过在 Windows 网络驱动器上做快照,或类似的方式——您可以查看您的系统备份。如果幸运的话,您可能会在这些备份中同时找到分支文件 reflog。

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