如何从 git reset –hard 中拯救代码
admin
2023-07-31 01:46:09
0

上个周末遇到了一个这样的场景

场景

自己写了大半天的一个小东西的代码,目录结构大概如下
node_modules
src
  - ...files
test
  - test.js
package.json

睡前本来准备上传到github仓库

  • git init

  • git add -A

发现忘记添加.gitignore,把node_modules文件都add进去了
于是手贱输入了git reset --hard

然后发现…目录里的东西全部没了(只剩下.git/文件架),

当时我的内心

挽救

心急如焚懊悔不已的我,经过查阅相关资料,还是找到了一些拯救代码的方法

由于每次git命令进行操作时git都会对相关文件进行快照,并通过一定形式把信息保存再.git/目录下。

由于此前我使用过git add -A命令,因此当文件被放进暂存区时,快照信息对象就已经保存了,而实用git reset --hard之后,这些对象就变成了悬空文件对象(dangling blob)。

我们可以实用git fsck命令显示他们

git fsck:用于验证当前git仓库数据的有效性和一致性,能够显示那些\”丢失\”的commitblob(文件)、tree等。

我们可以通过以下命令
git fsck --cache --unreachable $(git for-each-ref --format=\"%(objectname)\")

我们得到一大堆blob的hash ID

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03
...

接下来使用git show就能显示这些对象的内容了,例如git show 907b308

自动还原

但是由于我曾经添加的文件实在太多node_modules里的文件可能有上千个,因此对逐个ID进行git show肉眼筛选是非常不科学。

因此我写了个简单的nodejs脚本(因为我比较熟悉),筛选还原那些我需要的文件。

首先使用git fsck把hash ID都存到一个文件里
git fsck --cache --unreachable $(git for-each-ref --format=\"%(objectname)\") > allhashes

\"use strict\";

const fs = require(\"fs\");
const shelljs = require(\"shelljs\");
const through = require(\"through2\");

let buf = fs.readFileSync(\"./allhashes\")
buf = buf.toString();
let hashes = []
buf.replace(/dangling blob (\\w+)/gi,function (matached, hash) {
    hashes.push(hash)
});

let all = hashes.length;
let left = all;
hashes.forEach(hash=>{
    let fullContent = \"\"
    let stdout = shelljs.exec(\"git show \"+hash,{silent:true}).stdout;
    let input = through();
    console.log((left--)+\"/\"+all);
    //TODO:through2原来是为了处理stdout流的异步数据引入的,当前同步过程下不需要
    input.pipe(through((buf,_,next)=>{
        fullContent = fullContent+buf.toString();
        next(null,buf)
    },flush=>{
        if (matchContent(fullContent)){
            fs.writeFile(\"./objects/\"+hash,fullContent)
        }
        flush()
    }))

    input.push(stdout);
    input.push(null);
})

function matchContent(content){
    // ... 匹配规则
}

于是经过几分钟的执行,我找回了我的代码

参考链接

  • Undo git reset –hard with uncommitted files in the staging area

  • Recovering Git repository from objects only

  • Git的维护(git gc和git fsck)

上一篇:[TODO]Python拾遗(二)

下一篇:Python Path

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
项目管理和工程管理的区别 项目管理 项目管理,顾名思义就是专注于开发和完成项目的管理,以实现目标并满足成功标准和项目要求。 工...