`git pull`怎么吃掉我的作业了?

`git pull`怎么吃掉我的作业了?

我感觉就像校长办公室里的一个孩子,解释说狗在截止日期前一天晚上吃了我的作业,但我正盯着一些疯狂的数据丢失错误,我不明白这是怎么发生的。我想知道 git 如何吃掉我的整个存储库!我已经多次对 git 进行绞尽脑汁,但它从来没有眨眼过。我用它把 20 Gig Subversion 存储库拆分为 27 个 git 存储库,并从它们中过滤分支 foo 以理清混乱,而且它从来没有丢失任何字节。 reflog 总是可以依靠的。这次地毯不见了!

从我的角度来看,我所做的只是运行git pull,它摧毁了我的整个本地存储库。我并不是说它“搞乱了签出的版本”或“我所在的分支”或类似的东西。我是说一切都消失了

这是事件发生时我的终端的屏幕截图:

事件屏幕截图

让我带您了解一下。我的命令提示符包含有关当前 git 存储库的数据(使用 prezto 的 vcs_info 实现),以便您可以看到 git 存储库何时消失。第一个命令很正常:

  » caleb » jaguar » ~/p/w/incil.info » ◼  zend ★ »
❯❯❯ git co master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

在那里你可以看到我在“zend”分支上,并检查了 master。到目前为止,一切都很好。您将在我的下一个命令之前的提示中看到它成功切换了分支:

  » caleb » jaguar » ~/p/w/incil.info » ◼  master ★ »
❯❯❯ git pull
remote: Counting objects: 37, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 37 (delta 25), reused 0 (delta 0)
Unpacking objects: 100% (37/37), done.
From gitlab.alerque.com:ipk/incil.info
 + 7412a21...eca4d26 master     -> origin/master  (forced update)
   f03fa5d..c8ea00b  devel      -> origin/devel
 + 2af282c...009b8ec verse-spinner -> origin/verse-spinner  (forced update)
First, rewinding head to replay your work on top of it...
>>> elapsed time 11s

就这样它就消失了。如果经过时间超过 10 秒,则在下一个提示之前输出经过时间标记。 Git 没有给出任何输出,除了通知它正在倒回重放之外。没有任何迹象表明它已经完成。

下一个提示不包含有关我们所在分支或 git 状态的数据。

我没有注意到它失败了,我无意中尝试运行另一个 git 命令,却被告知我不在 git 存储库中。请注意 PWD 未更改:

  » caleb » jaguar » ~/p/w/incil.info »
❯❯❯ git fetch --all
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

之后环顾四周,发现我处于一个完全空的目录中。没有什么。没有“.git”目录,什么也没有。空的。

我本地的git版本是2.0.2。以下是我的 git 配置中的一些花絮,可能与弄清楚发生了什么有关:

[branch]
        autosetuprebase = always
        rebase = preserve
[pull]
        rebase = true
[rebase]
        autosquash = true
        autostash = true
[alias]
        co = checkout

例如,我git pull设置为始终进行变基而不是合并,因此上面的输出部分是正常的。

我可以恢复数据。我认为除了一些不重要的存储之外没有任何 git 对象没有被推送到其他存储库,但是我想知道发生了什么事

我已经检查过:

  • dmesg 或 systemd 日志中的消息。没有任何相关的东西。
  • 没有迹象表明驱动器或文件系统出现故障(LVM + LUKS + EXT4 看起来都正常)。失物招领中什么也没有。
  • 我没有运行其他任何东西。上面没有显示任何历史记录,并且在此期间没有使用其他终端。没有rm可能在错误的 CWD 中执行的命令等。
  • 戳另一个目录中的另一个 git repo 显示执行git pulls 没有明显的异常。

我还应该在这里寻找什么?

答案1

是的,git吃了我的作业。所有的。

dd事件发生后,我制作了这张磁盘的映像,并在稍后对其进行了修改。从系统日志中重构一系列事件,我推断发生的事情是这样的:

  1. pacman -Syu在此事件发生前几天,已发出系统更新命令 ( )。
  2. 长时间的网络中断意味着它必须重新尝试下载软件包。由于缺乏互联网而感到沮丧,我会让系统进入睡眠状态然后上床睡觉。
  3. 几天后,系统被唤醒,并开始再次查找和下载软件包。
  4. 在我碰巧摆弄这个存储库之前的某个时候,软件包下载已经完成。
  5. 系统glibc安装在 之前git checkout和之后进行了更新git pull
  6. 二进制文件在启动后和完成前git被替换。git pull
  7. 第七天,git一切劳作都休息了。并删除了世界,所以其他人也必须休息。

我不知道确切地发生了什么竞争条件导致了这种情况的发生,但是在操作中间交换二进制文件肯定不是很好,也不是可测试/可重复的条件。通常,正在运行的二进制文件的副本存储在内存中,但这git很奇怪,而且它重新生成自身版本的方式我确信导致了这种混乱。显然它应该死而不是毁灭一切,但事实就是这样。

答案2

可能是由于未能定义要删除的文件路径。

你的案例让我想起了美好的一天,当我的自制remove(path)方法尝试删除根文件夹时,因为给定的参数是空字符串,操作系统将其纠正为根文件夹(!)。

这可能是一个类似的 git bug。这样:

  1. Rebase 命令想要删除一个文件,例如remove(project_folder + file_path)(伪代码)
  2. 不知怎的,file_path当时是空的。
  3. 命令评估为类似的东西remove(project_folder)

答案3

幸运的话,您可以使用以下命令修复此问题:

git reset --hard ORIG_HEAD  

当潜在的危险更改开始时,git 会将您当前的状态存储在 ORIG_HEAD 中。使用它您可以撤消合并或变基。

Git 手册:撤消合并

答案4

看起来有人运行了git push --force这个存储库,并且您撤下了这些更改。尝试克隆新的存储库,这应该会让您再次回到干净的工作状态。

相关内容