[譯] 修改 Git 錯誤的高明方法

玉兒Qi發表於2019-02-25

在軟體開發的世界,有無窮無盡的方法能夠把事情搞得一團糟:錯刪東西,程式碼混亂,提交資訊寫錯了字,這些都僅僅是冰山一角。

幸運的是,當我們使用版本控制時,Git 提供給我們了一個很完美的安全網。當然啦,不是我們倆需要它,因為我們從來不犯錯的,對吧?嗯嗯當然當然。但是為了他人的利益,我們還是一起來看看那些可以拯救我們的 Git “撤回”工具。

修改最後提交

搞砸一次提交非常容易。經典的場景包括:提交資訊裡寫了錯字。其他的?還有忘記將修改新增到臨時區(staging area)。還有很多時候,我們忽然意識到程式碼中有錯誤 —— 但是當然是在點選了提交的確認鍵之後。

幸運的是,Git 讓修改最後一次提交這件事出乎意料的簡單。假如我們剛剛確認了下面這個命令:

git commit -m "Massage full of typohs"
複製程式碼

並且(好像這個拼寫錯誤還沒那麼糟糕)假如我們還忘記了新增某個已經修改的檔案到臨時區。我們可以使用如下兩行命令修正這兩個錯誤:

git add forgotten-changes.js
​​git commit --amend -m "A sensible message"
複製程式碼

神奇之處就在於 --amend​ 標識:當我們跟著 commit 命令使用它的時候,Git 將會修改最後一次提交 —— 新增臨時區的修改,並替換為新的說明資訊。

但是有一點需要提示:只能在沒有推送到遠端倉庫的提交上使用 --amend。原因是 Git 會用修改了的版本取代原來的,有錯誤的提交。這之後,看上去就像是原來的提交從來沒有過。是的,這種方式用來處理錯誤很好,但是必須是當我們還沒有將過這個錯誤釋出到遠端倉庫的時候。

撤銷本地修改

每個人都有類似的經歷:用了一早晨的時間尋找解決辦法,但是最後只好承認這幾個小時就是在浪費時間。必須從頭開始了,並且要撤銷大部分(或者所有)的程式碼。

但是這其實是使用 Git 的初衷之一 —— 它能讓你不用害怕破壞了什麼,而可以隨意的嘗試不同的方法。

讓我們來看一個例子:

git status
​​  modified: about.html
​​  deleted:  imprint.html
​​  modified: index.html
複製程式碼

現在我們假設,這些修改就是在前文說的浪費時間的場景。我們需要撤銷 about.html 的修改並且恢復已經刪除的 imprint.html。我們現在想要的就是,丟棄這些檔案當前的更改 —— 但是保留 index.html 中的超讚的已經寫好的程式碼。這時,git checkout​ 命令就能夠有所幫助。但是,我們需要像這樣指明是哪些檔案:

git checkout HEAD about.html imprint.html
複製程式碼

這行命令將 about.html 和 imprint.html 恢復到了最後提交的狀態。哎,我們可以不用熬夜來撤銷它們了!

我們可以更進一步,可以在一個修改過的檔案裡僅丟棄特定幾行程式碼,而不是恢復整個檔案!我必須承認,在命令列完成這項任務比較複雜,但使用 像 Tower 這樣的 Git 桌面客戶端 則是一個很好的方法:

[譯] 修改 Git 錯誤的高明方法

在程式碼真的糟透了的時候,我們就想掏出一把大槍:

git reset --hard HEAD
複製程式碼

這次我們不是僅僅使用 checkout​ 恢復指定的檔案,而是重置了所有修改過的副本。換句話說,reset 將所有專案檔案恢復到了最後一次提交的狀態。和 --amend 類似,使用 checkout​ 和 reset​ 的時候需要牢記:使用這些命令丟棄的本地修改無法恢復!它們還從來沒有被提交到倉庫中,所以不能被恢復也是合理的。請確認你真的想要刪除它們,因為刪除了就沒法找回了!

撤銷並還原更早的提交

很多情況下,我們一段時間後才意識到程式碼的錯誤,而它已經被提交到倉庫裡很久了。

[譯] 修改 Git 錯誤的高明方法

我們如何才能刪除掉這個錯誤的提交呢?答案是在大多數場景下,我們其實不應該這樣做。就算是“撤銷”內容的時候,通常情況下 Git 並沒有真的刪除資料。它通過新增新的資料來修正內容。用這個例子,我們來看看它是如何工作的:

git revert 2b504bee
複製程式碼

通過對這個提交執行 git revert,我們並沒有刪除任何東西。相反的是:

[譯] 修改 Git 錯誤的高明方法

Git 自動建立了一個新的提交來撤銷錯誤提交所造成的修改。所以,如果我們一開始有三個提交,然後試圖修正中間的那個,那麼我們就會有四個提交了,新增的那個用來修改 revert 的目標提交。

恢復專案之前的版本

另一個情境是我們希望恢復到專案之前的版本。我們不是僅僅撤銷提交歷史中的一個特定的版本,而是想讓時間倒流,直接退回到這個版本。 ​​
在下面的場景中,我們宣告“C2”之後的所有提交都是不需要的。我們想要回到“C2”這次提交的狀態,它之後的提交統統刪除:

[譯] 修改 Git 錯誤的高明方法

根據我們已經講述過的內容,我想你已經(至少部分)熟悉了所需的命令:

git reset --hard 2b504bee
複製程式碼

這個命令通知了 git reset 我們想要返回的提交的 SHA-1 雜湊值。C3 和 C4 提交將會從專案歷史中消失。 ​​ 如果你在使用 Git 客戶端,例如 Tower,提交專案的右鍵選單中的 git revertgit reset 兩者都可以使用:

[譯] 修改 Git 錯誤的高明方法

刪除提交,恢復刪除的分支,處理衝突等等

當然,軟體專案中還有很多其他會把事情搞砸的方式。但是幸運的是,Git 提供了很多工具來撤銷錯誤。

如果你想要學習本篇文章提到的場景中的更多的內容,或者其他題目,例如如何在分支之間移動提交,刪除舊提交,恢復刪除的分支,或者優雅的處理衝突,看一下專案 "Git 急救包",它是我和其他一些 Tower 團隊的人建立的。這是一份完全免費的教程,包括了 17 個視訊以及一份很方便的備忘單,你可以下載並儲存到你的裝置上。

[譯] 修改 Git 錯誤的高明方法

同時,祝你撤銷得愉快!

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章