【问题标题】:Remote branch exists, local branch disappeared远程分支存在,本地分支消失
【发布时间】:2017-04-19 02:22:58
【问题描述】:

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

我的分支叫做 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 github branch


    【解决方案1】:

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

    git branch -d exif
    

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

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

    git checkout origin/exif
    

    【讨论】:

    • 好的,如果我理解正确,我删除了我的分支的本地版本,这意味着我目前在一个不存在的分支中?因为我现在在 Exif。但是我今天的工作中仍然有很多更改的文件,你是否建议我复制这些文件,然后在我签出远程分支后将它们粘贴回去?
    • 如果你有未提交的更改,我会先按照官方 git 手册中的描述存储它们:git-scm.com/book/en/v1/Git-Tools-Stashing。然后我会检查远程分支并将存储应用到签出的分支上。跨度>
    • 当我尝试 git stash 时,它说致命:错误的修订版 'HEAD' 致命的:错误的修订版 'HEAD' 致命的:需要一个您还没有初始提交的修订版
    • 您现在似乎没有在任何分支上工作。尝试在本地创建一个分支并将其设置为跟随远程分支,如下所示:git branch --track exif origin/exif。您可以先备份您的文件夹,以确保不会意外删除任何内容。
    • Git 区分大小写的;当在 区分大小写的系统(Windows、Mac)上使用 Git 时会出现问题,并且 Git 会感到困惑,因为它认为可以删除与当前 @ 不同的 exif 987654325@(因为 Git 区分大小写),但这会删除 Exif(因为 OS 不区分大小写)。这是 Git 中的一个错误,尽管如果不进行一些可能等待 Git 3.0 的返工就很难克服。
    【解决方案2】:

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

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

    很有希望,因此您可能有一个简单的方法来解决问题。

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

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

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

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

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

    Git 检查了一下,发现你当前的分支是Exif,而不是exif。好吧,对于 Git,这些显然是不同,删除它一定是安全的!只是......他们不是,也不是。 The truth is complicated,但在 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/<em>branchname</em>中。

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

    .git/refs/heads/Exif
    

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

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

    我们需要做的是将该文件放回原处,并具有相同的值。

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

    如果你可以看到这个值——甚至只是它的一部分——在某个地方,例如,在一个现有的窗口中,这就足以取回整个值。例如,如果我有 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
    

    忽略除“提交”之外的所有内容:其中一个是正确的。要找出是哪一个,请在每一个上运行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。

    【讨论】:

    • 我真的很感激你在这个答案中付出的努力,但我做了其他人所说的,我获取了远程 Exif 并创建了一个新的本地分支来跟踪远程分支,我认为它有效.你认为这个更简单的方法有什么问题吗,我忽略了什么吗?
    • @jelte:不,鉴于您在遥控器上有所需的东西,您可以使用该方法。但这个 bug 可能会咬到其他人,也许是其他没有做过git push 的人,所以我想我会写一个方法来处理这个 bug,直到 Git 至少可以被修补,如果不是彻底修复的话。
    猜你喜欢
    • 2013-04-30
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 2016-07-08
    • 2016-04-12
    • 2018-09-12
    • 1970-01-01
    相关资源
    最近更新 更多