背景

我的manjaro Linux滚动更新后nVidia显卡HDMI输出出现了问题,暂时无法解决,因此开发环境切换到Windows.环境搭建的很顺利.

问题的产生

今日在执行git commit时提交的信息中包含了大量垃圾信息(换行符从LF换掉CRLF)又没有注意到,提交后发现commit message与我预想的不对,随后又发现所有行后面都加上了Windows的换行符,因此打算撤回这次commit,更改换行符到LF再重新commit.于是终端中执行.

git log
git reset --mixed <commit-hash>

理论上执行很快就能完成,但不巧的是Windows卡住然后蓝屏了,经调查蓝屏原因是nvme SSD接口故障.硬盘错误可能会导致数据损坏,果然,再打开仓库时,git说这不是一个有效的git仓库

$ git status
fatal: 不是一个 git 仓库(或者向上递归至挂载点 /mnt 的任何祖先目录)
停止在文件系统边界(未设置 GIT_DISCOVERY_ACROSS_FILESYSTEM)

然而.git文件夹还在那里,推测git仓库的部分文件损坏.由于最近两次的commit都没有提交,因此需要从这些文件中找回写过的代码,要不然就要重写.

查看损坏的repo中workspace中的文件,全部变成了乱码的二进制文件.找到Linux中的历史版本,使用diff工具比较.git,objects文件夹即为数据文件, 不要更改, 查找其他乱码的文件, 发现以下文件损坏, 使用旧仓库的覆盖.

  • .git/index
  • .git/config
  • .git/HEAD

.git/HEAD的内容为ref: refs/heads/master, 打开正常仓库的.git/refs/heads/master, 里面为commit-hash, 打开损坏仓库的.git/logs/refs/heads/master, 发现内容正常, 为commit的历史, 将最后一次的hash复制到.git/refs/heads/master, 再执行git reset --hard <commit-hash>, 文件成功恢复.

提醒

.git中的文件在正常情况下不要手动修改, 除非出现这种事故.

本地仓库commit后就应该push到远程仓库, 防止文件损坏.