團隊開發中經常遇到錯誤刪除文件,錯誤提交等情況,那么使用Git該如何正確的進行撤銷和恢復呢?
一.增補提交
git commit –C HEAD –a --amend
-C表示復用指定提交的提交留言,這個例子中是HEAD,實際上可以指定其他有效的提交名稱。
如果參數是小寫的-c,就會打開預先設置好的編輯器,以便在已有的提交留言基礎上編輯修改。
增補提交只能針對最后一個提交,如果想更正好幾個提交之前的某個錯誤,則須使用git revert這個命令。
二.反轉提交
反轉已經提交的改動,使用git revert命令,此命令通過在版本庫中創建一個“反向的”新提交來抵消原來提交的改動。
通常Git會立即提交反轉結果,但是也可以通過參數-n告訴Git先不要提交,這用於反轉多個提交非常有用,運行多個git revert –n命令,Git會暫存所有的變更,然后做一次性提交。
做反轉操作的時候必須提供提交名稱,反轉總是按照從新到舊點的倒序來操作的,即最后的提交最先反轉,這樣可以避免一些不必要的沖突。
三.復位
命令git reset可以在復位版本庫后,暫存工作目錄樹中因復位產生的與版本庫的差異,以便提交。
git reset --soft 該命令撤消上一個commit,但保留add的文件,使得Git暫存所有的因復位帶來的差異,但不提交它。
之后,用戶可以修改這些內容再提交,或者干脆扔掉這些內容。
選項--hard要小心使用,該選項會從版本庫和工作目錄樹中同時刪除提交,--hard就好像版本庫中的刪除鍵,並且不可恢復。
git reset是以提交名稱作為參數的,默認值是HEAD,可以用^和~作為提交名稱的修飾符來指定某個版本。
HEAD^是指把版本庫復位到當前HEAD之前的那個節點上,把HEAD這個版本的修改扔到工作目錄樹中,
540ecb7~3是指要復位到540ecb7之前的三個節點上,即把該提交和之前的兩個提交(共三個提交)扔到工作目錄樹中。
git reset --hard HEAD^ 強制復位前一個提交。
git reset HEAD可以用來清除已經add到緩存區但是不想進一步提交的內容。
另一種方式是用git rm --cached,選項--cached表明是清除緩存區,然后不動工作目錄樹。
注意git checkout filename將會刪除該文件中所有沒有暫存和提交的改動,這個操作是不可逆的。
四.Git回復修改的場景
(1)如果不小心commit了一個不需要commit的文件,可以對其進行撤銷
先使用git log 查看 commit日志
commit 422bc088a7d6c5429f1d0760d008d86c505f4abe Author: test <test@gmail.com> Date: Tue Sep 4 18:19:23 2015 +0800 注釋-本次為錯誤提交 commit 8da0fd772c3acabd6e21e85287bdcfcfe8e74c85 Merge: 461ac36 0283074 Author: test <test@gmail.com> Date: Tue Sep 4 18:16:09 2015 +0800
找到需要回退的那次commit的 哈希值,使用下面的命令進行回退:
git reset --hard commit_id
注意--hard可以把已經add的文件也刪掉,謹慎使用。
(2)git如何恢復本地刪除的文件(還沒執行 git commit)
直接從本地把文件checkout出來就可以了,用不着從遠程服務器上pull下來,因為,所有的歷史版本你的本地都有的。
具體做法 git checkout file 同時恢復多個被刪除的文件:
git ls-files -d | xargs -i git checkout {}
(3)從Git倉庫中恢復已刪除的分支或丟失的commit
在使用Git的過程中,有時可能會有一些誤操作
比如:執行checkout -f 或 reset -hard 或 branch -d刪除一個分支
結果造成本地(遠程)的分支或某些commit丟失
這時,我們可以通過reflog來進行恢復,前提是丟失的分支或commit信息沒有被git gc清除
一般情況下,gc對那些無用的object會保留很長時間后才清除的
reflog是git提供的一個內部工具,用於記錄對git倉庫進行的各種操作
可以使用git reflog show或git log -g命令來看到所有的操作日志
恢復的過程很簡單:
1. 通過git log -g命令來找到我們需要恢復的信息對應的commitid,可以通過提交的時間和日期來辨別 <git reflog show>
2. 通過git branch recover_branch commitid 來建立一個新的分支
這樣,我們就把丟失的東西給恢復到了recover_branch分支上了
參考
《版本控制之道——使用Git》