加载中...

找回丢失的对象


译者注: 原书这里只有两个链接: Recovering Lost Commits Blog Post,  Recovering Corrupted Blobs by Linus

我根据第一个链接,整理了一篇博文,并把它做为原书补充。

在玩git的过程中,常有失误的时候,有时把需要的东东给删了。 不过没有关系,git给了我们一层安全网,让们能有机会把失去的东东给找回来。

Let's go!

准备

我们先创建一个用以实验的仓库,在里面创建了若干个提交和分支。 BTW:你可以直接把下面的命令复制到shell里执行。

  1. mkdir recovery;cd recovery
  2. git init
  3. touch file
  4. git add file
  5. git commit -m "First commit"
  6. echo "Hello World" > file
  7. git add .
  8. git commit -m "Greetings"
  9. git branch cool_branch 
  10. git checkout cool_branch
  11. echo "What up world?" > cool_file
  12. git add .
  13. git commit -m "Now that was cool"
  14. git checkout master
  15. echo "What does that mean?" >> file

恢复已删除分支提交

现在repo里有两个branch

  1. $ git branch
  2. cool_branch
  3. * master

存储当前仓库未提交的改动

  1. $ git stash save "temp save"
  2. Saved working directory and index state On master: temp save
  3. HEAD is now at e3c9b6b Greetings

删除一个分支

  1. $ git branch -D cool_branch
  2. Deleted branch cool_branch (was 2e43cd5).
  3. $ git branch
  4. * master

git fsck --lost-found命令找出刚才删除的分支里面的提交对象。

  1. $git fsck --lost-found
  2. dangling commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a

用git show命令查看一个找到的对象的内容,看是否为我们所找的。

  1. git show 2e43cd56ee4fb08664cd843cd32836b54fbf594a
  2. commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a
  3. Author: liuhui <liuhui998[#]gmail.com>
  4. Date: Sat Oct 23 12:53:50 2010 +0800
  5. Now that was cool
  6. diff --git a/cool_file b/cool_file
  7. new file mode 100644
  8. index 0000000..79c2b89
  9. --- /dev/null
  10. +++ b/cool_file
  11. @@ -0,0 +1 @@
  12. +What up world?

这个提交对象确实是我们在前面删除的分支的内容;下面我们就要考虑一下要如何来恢复它了。

使用git rebase 进行恢复

  1. $git rebase 2e43cd56ee4fb08664cd843cd32836b54fbf594a
  2. First, rewinding head to replay your work on top of it...
  3. Fast-forwarded master to 2e43cd56ee4fb08664cd843cd32836b54fbf594a.

现在我们用git log命令看一下,看看它有没有恢复:

  1. $ git log
  2. commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a
  3. Author: liuhui <liuhui998[#]gmail.com>
  4. Date: Sat Oct 23 12:53:50 2010 +0800
  5. Now that was cool
  6. commit e3c9b6b967e6e8c762b500202b146f514af2cb05
  7. Author: liuhui <liuhui998[#]gmail.com>
  8. Date: Sat Oct 23 12:53:50 2010 +0800
  9. Greetings
  10. commit 5e90516a4a369be01b54323eb8b2660545051764
  11. Author: liuhui <liuhui998[#]gmail.com>
  12. Date: Sat Oct 23 12:53:50 2010 +0800
  13. First commit

提交是找回来,但是分支没有办法找回来:

  1. liuhui@liuhui:~/work/test/git/recovery$ git branch
  2. * master

使用git merge 进行恢复

我们把刚才的恢复的提交删除

  1. $ git reset --hard HEAD^
  2. HEAD is now at e3c9b6b Greetings

再把刚删的提交给找回来:

  1. git fsck --lost-found
  2. dangling commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a

不过这回我们用是合并命令进行恢复:

  1. $ git merge 2e43cd56ee4fb08664cd843cd32836b54fbf594a
  2. Updating e3c9b6b..2e43cd5
  3. Fast-forward
  4. cool_file | 1 +
  5. 1 files changed, 1 insertions(+), 0 deletions(-)
  6. create mode 100644 cool_file

git stash的恢复

前面我们用git stash把没有提交的内容进行了存储,如果这个存储不小心删了怎么办呢?

当前repo里有的存储:

  1. $ git stash list
  2. stash@{0}: On master: temp save

把它们清空:

  1. $git stash clear
  2. liuhui@liuhui:~/work/test/git/recovery$ git stash list

再用git fsck --lost-found找回来:

  1. $git fsck --lost-found
  2. dangling commit 674c0618ca7d0c251902f0953987ff71860cb067

用git show看一下回来的内容对不对:

  1. $git show 674c0618ca7d0c251902f0953987ff71860cb067
  2. commit 674c0618ca7d0c251902f0953987ff71860cb067
  3. Merge: e3c9b6b 2b2b41e
  4. Author: liuhui <liuhui998[#]gmail.com>
  5. Date: Sat Oct 23 13:44:49 2010 +0800
  6. On master: temp save
  7. diff --cc file
  8. index 557db03,557db03..f2a8bf3
  9. --- a/file
  10. +++ b/file
  11. @@@ -1,1 -1,1 +1,2 @@@
  12. Hello World
  13. ++What does that mean?

看起来没有问题,好的,那么我就把它恢复了吧:

  1. $ git merge 674c0618ca7d0c251902f0953987ff71860cb067
  2. Merge made by recursive.
  3. file | 1 +
  4. 1 files changed, 1 insertions(+), 0 deletions(-)

备注

这篇文章主要内容来自这里:The illustrated guide to recovering lost commits with Git,我做了一些整理的工作。

如果对于文中的一些命令不熟,可以参考Git Community Book中文版

其实这里最重要的一个命令就是:git fsck --lost-found,因为git中把commit删了后,并不是真正的删除,而是变成了悬空对象(dangling commit)。我们只要把把这悬空对象(dangling commit)找出来,用git rebase也好,用git merge也行就能把它们给恢复。


还没有评论.