在 Git 中使用reset 可以讓當前分支回滾(reset)到任何一個歷史版本, 直接移除那以後的所有提交。但這更改了 Git 的歷史,Git 服務通常會禁止這樣做。 這便需要一個更安全的方式將代碼狀態回到歷史版本,同時不更改 Git 歷史。 

所謂  保護分支 ,就是指不允許改寫 Git 歷史的分支。在 Github 中對應的選項是  Force Pushes,該選項默認處於 Disallow 狀態。 

找到歷史版本

首先,通過git log 確認你要回滾到的版本的 commit hash。 例如,我們有 4 個版本其中後兩個是壞的,要回滾到 version 2,它對應的 commit hash 就是  4a50c9f : 

簽出歷史版本

為了便於操作,我們給這個版本一個分支名,比如  v2 : 

現在就已經位於  v2 分支啦,當前的 Git 記錄如下,比上一步只是多了一個分支名: 

假合併 master

為了不更改 Git 記錄,我們只能生成一個新的 Commit 讓代碼狀態回到 v2。 這意味着必須在 version 4 的基礎上進行,思路和手動操作無異。 但我們可以通過一個神奇的合併操作自動完成:

-s <strategy> 用來指定合併策略,ours 是遞歸合併策略的一種,即直接使用當前分支的代碼。  -s ours 合併的結果是產生了一個基於 master 的 Commit,但  HEAD 中的代碼與合併前完全相同 。 從 Git 記錄可以看到 version 2 和 version 4 進行了合併: 

但合併中完全採用了 version 2 的代碼,即合併前後 diff 為空:

至此我們已經產生了一個  代碼狀態與歷史版本完全一致,但基於 master 的一個 Commit 。 

push 到遠程

在產生可用的 Commit 後,可以從當前分支 v2 直接發往 origin/master:

更詳細的遠程倉庫操作可以參考遠程倉庫 一文。