譯者注: 原書這里只有兩個鏈接:?[Recovering Lost Commits Blog Post](http://programblings.com/2008/06/07/the-illustrated-guide-to-recovering-lost-commits-with-git), ?[Recovering Corrupted Blobs by Linus](http://www.kernel.org/pub/software/scm/git/docs/howto/recover-corrupted-blob-object.txt)
我根據第一個鏈接,整理了一篇[博文](http://liuhui998.com/2010/10/22/recover_lost_commits_with_git/),并把它做為原書補充。
在玩git的過程中,常有失誤的時候,有時把需要的東東給刪了。 不過沒有關系,git給了我們一層安全網,讓們能有機會把失去的東東給找回來。
Let's go!
## 準備
我們先創建一個用以實驗的倉庫,在里面創建了若干個提交和分支。 BTW:你可以直接把下面的命令復制到shell里執行。
~~~
mkdir recovery;cd recovery
git init
touch file
git add file
git commit -m "First commit"
echo "Hello World" > file
git add .
git commit -m "Greetings"
git branch cool_branch
git checkout cool_branch
echo "What up world?" > cool_file
git add .
git commit -m "Now that was cool"
git checkout master
echo "What does that mean?" >> file
~~~
## 恢復已刪除分支提交
現在repo里有兩個branch
~~~
$ git branch
cool_branch
* master
~~~
存儲當前倉庫未提交的改動
~~~
$ git stash save "temp save"
Saved working directory and index state On master: temp save
HEAD is now at e3c9b6b Greetings
~~~
刪除一個分支
~~~
$ git branch -D cool_branch
Deleted branch cool_branch (was 2e43cd5).
$ git branch
* master
~~~
用`git fsck --lost-found`命令找出剛才刪除的分支里面的提交對象。
~~~
$git fsck --lost-found
dangling commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a
~~~
用git show命令查看一個找到的對象的內容,看是否為我們所找的。
~~~
git show 2e43cd56ee4fb08664cd843cd32836b54fbf594a
commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a
Author: liuhui <liuhui998[#]gmail.com>
Date: Sat Oct 23 12:53:50 2010 +0800
Now that was cool
diff --git a/cool_file b/cool_file
new file mode 100644
index 0000000..79c2b89
--- /dev/null
+++ b/cool_file
@@ -0,0 +1 @@
+What up world?
~~~
這個提交對象確實是我們在前面刪除的分支的內容;下面我們就要考慮一下要如何來恢復它了。
### 使用git rebase 進行恢復
~~~
$git rebase 2e43cd56ee4fb08664cd843cd32836b54fbf594a
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 2e43cd56ee4fb08664cd843cd32836b54fbf594a.
~~~
現在我們用git log命令看一下,看看它有沒有恢復:
~~~
$ git log
commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a
Author: liuhui <liuhui998[#]gmail.com>
Date: Sat Oct 23 12:53:50 2010 +0800
Now that was cool
commit e3c9b6b967e6e8c762b500202b146f514af2cb05
Author: liuhui <liuhui998[#]gmail.com>
Date: Sat Oct 23 12:53:50 2010 +0800
Greetings
commit 5e90516a4a369be01b54323eb8b2660545051764
Author: liuhui <liuhui998[#]gmail.com>
Date: Sat Oct 23 12:53:50 2010 +0800
First commit
~~~
提交是找回來,但是分支沒有辦法找回來:
~~~
liuhui@liuhui:~/work/test/git/recovery$ git branch
* master
~~~
### 使用git merge 進行恢復
我們把剛才的恢復的提交刪除
~~~
$ git reset --hard HEAD^
HEAD is now at e3c9b6b Greetings
~~~
再把剛刪的提交給找回來:
~~~
git fsck --lost-found
dangling commit 2e43cd56ee4fb08664cd843cd32836b54fbf594a
~~~
不過這回我們用是合并命令進行恢復:
~~~
$ git merge 2e43cd56ee4fb08664cd843cd32836b54fbf594a
Updating e3c9b6b..2e43cd5
Fast-forward
cool_file | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 cool_file
~~~
## git stash的恢復
前面我們用git stash把沒有提交的內容進行了存儲,如果這個存儲不小心刪了怎么辦呢?
當前repo里有的存儲:
~~~
$ git stash list
stash@{0}: On master: temp save
~~~
把它們清空:
~~~
$git stash clear
liuhui@liuhui:~/work/test/git/recovery$ git stash list
~~~
再用git fsck --lost-found找回來:
~~~
$git fsck --lost-found
dangling commit 674c0618ca7d0c251902f0953987ff71860cb067
~~~
用git show看一下回來的內容對不對:
~~~
$git show 674c0618ca7d0c251902f0953987ff71860cb067
commit 674c0618ca7d0c251902f0953987ff71860cb067
Merge: e3c9b6b 2b2b41e
Author: liuhui <liuhui998[#]gmail.com>
Date: Sat Oct 23 13:44:49 2010 +0800
On master: temp save
diff --cc file
index 557db03,557db03..f2a8bf3
--- a/file
+++ b/file
@@@ -1,1 -1,1 +1,2 @@@
Hello World
++What does that mean?
~~~
看起來沒有問題,好的,那么我就把它恢復了吧:
~~~
$ git merge 674c0618ca7d0c251902f0953987ff71860cb067
Merge made by recursive.
file | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
~~~
## 備注
這篇文章主要內容來自這里:[The illustrated guide to recovering lost commits with Git](http://programblings.com/2008/06/07/the-illustrated-guide-to-recovering-lost-commits-with-git/),我做了一些整理的工作。
如果對于文中的一些命令不熟,可以參考[Git Community Book中文版](http://gitbook.liuhui998.com/)
其實這里最重要的一個命令就是:git fsck --lost-found,因為git中把commit刪了后,并不是真正的刪除,而是變成了懸空對象(dangling commit)。我們只要把把這懸空對象(dangling commit)找出來,用[git rebase](http://gitbook.liuhui998.com/4_2.html)也好,用[git merge](http://gitbook.liuhui998.com/3_3.html)也行就能把它們給恢復。
- 1. 介紹
- 歡迎使用Git
- GIT對象模型
- Git目錄 與 工作目錄
- Git索引
- 2. 第一步
- 安裝Git
- 安裝與初始化
- 3. 基本用法
- 獲得一個Git倉庫
- 正常的工作流程
- 分支與合并@基礎
- 查看歷史 -Git日志
- 比較提交 - Git Diff
- 分布式的工作流程
- Git標簽
- 4. 中級技能
- 忽略某些文件
- rebase
- 交互式rebase
- 交互式添加
- 儲藏
- Git樹名
- 追蹤分支
- 使用Git Grep進行搜索
- Git的撤消操作 - 重置, 簽出 和 撤消
- 維護Git
- 建立一個公共倉庫
- 建立一個私有倉庫
- 5. 高級技能
- 創建新的空分支
- 修改你的歷史
- 高級分支與合并
- 查找問題的利器 - Git Bisect
- 查找問題的利器 - Git Blame
- Git和Email
- 定制Git
- Git Hooks
- 找回丟失的對象
- 子模塊
- 6. Git生態體系
- Git 與之 Windows
- 使用Git進行系統部署
- 與 Subversion 集成
- 從其他代碼管理工具遷移到Git
- 圖形化的Git
- Git倉庫托管
- Git的其它用法
- Git的腳本支持
- Git 與編輯器
- 7. 原理解析
- Git是如何存儲對象的
- 查看Git對象
- Git引用
- Git索引
- 打包文件
- 更底層的Git
- 傳輸協議
- 術語表