git reset --hard
但未提交全部文件到仓库导致的文件丢失问题git commit
时 只上传了部分文件,但是直接进行了--hard版本穿梭
,导致工作区、暂存区的文件都消失或被覆盖的问题
。
我当时将所有文件都add到了暂存区,但只commit了一个pom.xml文件(当时脑子不知道怎么想的),随后进行了版本回退,reset --hard
到了一个只有.idea文件夹的初始版本,导致我项目中的src文件夹、target文件夹都消失了(超多文件,心态直接炸裂),并且仓库中不存在 拥有src文件夹的版本,无法通过git reflog
和reset
解决
git reset --hard
[版本哈希值] 会撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交。(慎用)
若此时暂存区内有未commit的文件,会直接丢失。
前提
:文件必须add到暂存区过!没add神都救不了你! .git文件夹也必须没有改动过如果 git reflog
可以找到拥有丢失的文件的版本,可以直接git reset
版本号 回退,但本问题明显不是这么简单可以解决的。
git fsck --lost-found
git read-tree --prefix=lib 文件哈希
git checkout --lib
首先输入:
git fsck --lost-found
git fsck --lost-found
可以通过一些神奇的方式把曾经add到暂存区过的文件以某种算法算出来加到 .git/lost-found
文件夹里,直接去文件夹里找便可以找到丢失的特殊文件
输出记录:
可以看到第二列 blob
、tree
、commit
为文件类型,第三列为文件名(哈希值)
这是git的底层文件对象
commit数据结构
在每次提交之后都会生成一个,当我们进行commit之后,首先会创建一个commit组件,之后创建一个tree组件,把所有的文件信息都储存在里面,每个blob代表一个文件,都可以在tree里找到
blob组件
并不会对文件信息进行存储,而是只对文件的内容进行记录,文件信息存储在tree里
通俗的讲,blob是文件,可以直接打开看到其中的文字,tree为文件夹,git show可以看到目录结构但只有文件名
git show 文件名
tree
类型可以通过git ls-tree
文件哈希 来列出其下面的文件名和id
git ls-tree 文件名
既然tree内部的文件的哈希都拿到了,就可以一层一层地拿到文件的内容了
但是我丢掉的文件实在是太多了,让我一层一层的取,一层一层的复制粘贴?目录结构也要自己新建?开玩笑!
当时的我真准备“破釜沉舟”开肝了,后来搜索半天又查阅官方文档,终于找到了一个git的命令!!!
使用子树合并,可以实现一个项目中引用其他项目的数据,并建立跟踪关联。
官方文档:git read-tree --help
简而言之,使用git read-tree
可以解析tree文件并存入index暂存区
输入:
git read-tree --prefix=lib 要解析的tree文件哈希值
此命令会将tree递归解析,将其关联的所有目录树以子目录形式添加到master分支
接下来 git status
打印状态
可以看到它将此tree文件所指向的文件全部写入了暂存区,但又将工作区删了个干净 ,所以你执行完是看不见lib文件夹的。
它只是更新了index,所以还要加上
git checkout --lib
来更新工作区的lib目录内容
此时奇迹便发生了!