事情起因
早上合代码的时候,get merge 解决完代码冲突后,迷迷糊糊敲下了git add .
git status 一看把一些还没写好的文件也add到merge的分支里了, 情急之下,立马
git log -n 1
git reset --hard sha1
重新合并add commit push 一顿操作完事后美滋滋地去新需求评审了
直到下午需要切分支回来继续开发时发现不对了,咦我写的代码哪去了?
git status 没有
git stash list 也没有
这时候预感有点不对,马上history | grep git 看了一下 然后傻掉了git reset hard sha1恢复时,把add的内容直接覆盖掉,也就是说写的代码找不到了!!!
尝试恢复
马上谷歌搜救命的办法,对下面几种办法一一进行了尝试
1.
用git log 查找commit 然后回退到merge之前的commit
这里我的代码只执行了git add, 没有进行commit 因此这种方式没有效果
2.
git fsck --lost-found 后去 .git/lost-found/other中找代码
去看了一下,里面的有一堆文件
00f757ab1e7011d658e497eea0c2c9e67218c6c6
0a4fc242825d73e32ab9d3e2aeee98651ec6fab3
打开后看到里面是之前merge的其他分支上的代码,并不是我add的未提交的代码
3.
find .git/objects -type f
查找早上的文件obj对应的哈希
再借助git cat-file -p sha1 读取内容
find .git/objects -type f | xargs ls -lt | sed 136q | awk '{gsub(".git/objects/", "", $9);gsub("/","",$9);print $9}' | tee obj
用脚本从obj的sha1中dump出内容, 这里用了lua
f = io.open("obj", "r")
local line = f:read("*l")
while line do
cmd = "git cat-file -p " .. line
dump_file = io.open("files/" .. line, 'w+')
local ret = io.popen(cmd)
for line in ret:lines() do
dump_file:write(line .. '\n')
end
dump_file:close()
line = f:read("*l")
end
f:close()
执行lua dumpfromsha1.lua 后files文件夹中出现了136个sha1对应的obj的内容 然后从文件夹中grep 内容
[aidu35@aidu35 ~/workspace/odcp-console/extract/files]$ grep "scan_unused" *
6d73eae999ed1d21288524a3b2f48d47b78dee7f:local function scan_unused(dst_dir, required_path_arr)
6d73eae999ed1d21288524a3b2f48d47b78dee7f: scan_unused(dst_dir, required_path_arr)
76f7d1d575e7c2d205446cbd8441bb23224f1baf:100644 blob 6d73eae999ed1d21288524a3b2f48d47b78dee7f scan_unused.lua
打开6d73eae999ed1d21288524a3b2f48d47b78dee7f, 熟悉的代码又回来啦,只要改一下名字就可以了
一点反思:
git add <path>会将path下的文件加入的索引库中
这时候我们通过 git status 可以看到path目录的文件全部变成了stage状态
[gerrard@centos ]$ git add .
[gerrard@centos ]$ git status .
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
# (use "git push" to publish your local commits)
#
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: logs/access.log
# new file: logs/dev-error.log
# new file: logs/error.log
# new file: test/openresty-websocket-subpub.md
git 实际已经给了unstage的方法,只要git reset HEAD <path>就可以撤销了
[gerrard@centos ]$ git reset HEAD .
[gerrard@centos ]$ git status .
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
# (use "git push" to publish your local commits)
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# logs/
# test/openresty-websocket-subpub.md
nothing added to commit but untracked files present (use "git add" to track)
其实 对于只add解决冲突的文件的时候,我们应该执行
git add -u .
表示把中所有tracked文件中被修改过或已删除文件的信息添加到索引库。它不会处理untracted的文件
还是因为对git命令不熟悉,忙活了两小时,值得反思记录。
微信扫一扫,订阅我的博客动态^_^