事情是这样的,在一次文件清理的时候,不知道什么原因,我多选择了一些文件,
因为习惯使用 Shift + Delete + 回车 删除文件,没注意多删除了一些文件,刚好这些文件是正在开发的项目代码,刚好这些代码是本地 GIT 仓库。
在内网机器做开发,管理版本使用了本地 GIT,没有网络备份。
意识到出问题的时候,文件已经删除了一大半,赶紧点取消,然后下载数据恢复软件(Disk Genius 和 Easy Undelete),
没有用,因为内网虚拟机环境,连硬盘都是虚拟的,数据恢复软件根本就不支持扫扇区,这下子芭比Q了。
检查后确认,整个代码目录,所有代码全部被误删,【 .git 】目录的绝大多数文件也被误删了,只剩下【objects】目录的部分文件。
说完前因,接下来说说数据该怎么恢复。
首先科普一下,GIT 的核心,其实是一种基于文件系统的键值对数据库,GIT 所有数据,都是通过这个【数据库】存储的。
这个数据库,就存储在 GIT 仓库的 【 .git/objects 】目录下,两位子目录名 + 文件名的完整哈希值就是数据库的【键】,而文件内容就是【值】
感兴趣的小伙伴可以搜索【GIT BLOB对象】更详细的了解这部分知识。
当然了,直接用记事本打开 objects 目录下的文件,是无法看到我们代码的,我们需要使用 git 客户端提供的工具来查看代码:
git cat-file -p 键
通过这条命令就可以查看对应文件的内容了,例如 【git cat-file -p 0a5a3f6eae33cf0b8552ee9f7bda06ec824b1e98】
当然了,我的情况比较特殊,连 GIT 仓库都没了,只剩下一个 objects 目录,所以这条命令运行后,会报错:
fatal: not a git repository (or any of the parent directories): .git
这个报错的意思就是说,没有 GIT 仓库,所以我们需要先创建一个新的 GIT 仓库,并把 objects 文件复制过来。
或者复制一个其他项目的仓库,删除 objects 目录,更换为我们的 objects 目录,再次运行上述命令,可以成功查看文件内容了。
既然 .git 目录下除了 objects 以外的所有内容都没了,我们也不能指望着用 git 客户端去找 commit 列表恢复数据了。
所以只能手动用上面的命令一点点分析哪些是我们的代码,好在这个过程非常简单。
首先,在 objects 目录下,按 修改日期 对文件夹进行排序,我们要恢复的代码,肯定是最近一次提交的对吧?
接下来,进入最近一次修改的目录内,开始用 git cat-file 命令查看文件内容。
GIT 的 objects 目录不止存储了我们提交 commit 的代码文件,还有每次提交的文件列表等信息,所以我们可以看到各种类型的文件内容,也包括代码。
如果我们找到了最近一次提交的文件列表,它会展示类似这样的文件内容:
D:\Git\xxbot\.git\objects>git cat-file -p 312285f11b3a4d1ae926ff574f2d5b8abd66e0de
100644 blob fe1e0fb20eae168863e69eee48cc085ab06c2f65 build_UiBot_x64.bat
100644 blob 0e53f9534f9376370949a94d77d181dadd4002b3 build_UiBot_x86.bat
040000 tree 797f44fcae5738ddb8c01bb725368d8cecaffa0e help
040000 tree ead92b9b343ed17859c0c67a8bbf5d102543cb6e luamod
100644 blob 21fcecc1d21c0c83474055230c9716f9a1b27fe0 readme.txt
040000 tree 35a82cae2544a6c4ba74a2091b86ecacb087ff24 release
040000 tree a8daeccc38ede627ac4bee09d59d4ffad7ba1ec3 res
040000 tree 950dec9b932267adfb912a90f51f4ad18380c6f1 sdk
040000 tree c62be7880b3497e8fdbe25a8a3035f00b8bde409 tools
100644 blob df6ee0e3dd42cb97b0be74ce1f2b5e2dfaf54698 xBot.c
可以看到,objects 目录下的键和对应的文件名都有了,之后的事情就简单了吧?利用 【 > 】符号将文件内容写到文件里,就完成了代码的恢复,例如上面这些文件,我想要恢复他们,只需要依次运行如下这些命令即可:
// 要先创建 c:\undelete 目录哟,或者你想要把代码恢复到的位置
git cat-file -p fe1e0fb20eae168863e69eee48cc085ab06c2f65 > c:\undelete\build_UiBot_x64.bat
git cat-file -p 0e53f9534f9376370949a94d77d181dadd4002b3 > c:\undelete\build_UiBot_x86.bat
git cat-file -p 21fcecc1d21c0c83474055230c9716f9a1b27fe0 > c:\undelete\readme.txt
git cat-file -p df6ee0e3dd42cb97b0be74ce1f2b5e2dfaf54698 > c:\undelete\xBot.c
之后去 c:\undelete 目录看看,文件是不是已经被恢复了呢?
当然了,因为 objects 目录也被删除了很多文件,所以不一定每一个文件都能成功恢复,但至少我们可以恢复每一个代码文件,相对比较新的版本了不是吗。
对我来说,这件事情最终的结果是,我幸运的恢复了所有的代码的最新版本。
因为 GIT 的 objects 目录下文件众多,删除了很久都只删除了一部分,也因为我平时提交 commit 比较勤快。
当然,这件事给我更多的是警示,删除文件的时候手别太快,确认好了再删,另外 GIT 也尽量别只有本地仓库,能在服务器或者多个机器上备份就多备份,以及代码各个版本,最好都独立备份。
最后希望大家都能稳如老狗,永远不误删代码~