git 線上回滾問題紀要

1. git revert 做用

  revert 用來取消置頂的提交的內容git

2. 前提說明

  當討論 revert 時,須要分兩種狀況,由於 commit 分爲兩種:spa

  • 一種是常規的 commit,也就是使用 git commit 提交的 commit;
  • 另外一種是 merge commit

  須要明確:在使用 git merge 合併兩個分支以後,你將會獲得一個新的 merge commit。merge commit 和普通 commit 的不一樣之處在於 merge commit 包含兩個 parent commit,表明該 merge commit 是從哪兩個 commit 合併過來的。code

  

  在上圖所示的紅框中有一個 merge commit,使用 git show 命令能夠查看 commit 的詳細信息blog

  ➜  git show bd86846
  commit bd868465569400a6b9408050643e5949e8f2b8f5
  Merge: ba25a9d 1c7036f

   這表明該 merge commit 是從 ba25a9d 和 1c7036f 兩個 commit 合併過來的。開發

  而常規的 commit 則沒有 Merge 行it

  ➜  git show 3e853bd
  commit 3e853bdcb2d8ce45be87d4f902c0ff6ad00f240a

 3. revert 常規 commit

  使用 git revert <commit id> 便可,git 會生成一個新的 commit,將指定的 commit 內容從當前分支上撤除。ast

4. revert merge commit

  revert merge commit 有一些不一樣,這時須要添加 -m 選項以表明此次 revert 的是一個 merge commitclass

  但若是直接使用 git revert <commit id>,git 也不知道到底要撤除哪一條分支上的內容,這時須要指定一個 parent number 標識出"主線",主線的內容將會保留,而另外一條分支的內容將被 revert。bug

  如上面的例子中,從 git show 命令的結果中能夠看到,merge commit 的 parent 分別爲 ba25a9d1c7036f,其中 ba25a9d 表明 master 分支(從圖中能夠看出),1c7036f 表明 will-be-revert 分支。須要注意的是 -m 選項接收的參數是一個數字,數字取值爲 1 和 2,也就是 Merge 行裏面列出來的第一個仍是第二個。im

  咱們要 revert will-be-revert 分支上的內容,即 保留主分支,應該設置主分支爲主線,操做以下:

  ➜ git revert -m 1 bd86846

5. revert 以後從新上線

  假設你本身分支 goudan/a-cool-feature 上開發了一個功能,併合併到了 master 上,以後 master 上又提交了一個修改 h,這時提交歷史以下:

  

   忽然,你們發現你的分支存在嚴重的 bug,須要 revert 掉,因而你們把 g 這個 merge commit revert 掉了,記爲 G,以下:

  

   而後你回到本身的分支進行 bug_fix,修好以後想從新合併到 master,直覺上只須要再 merge 到 master 便可

  

   i 是新的 merge commit。但須要注意的是,這 不能 獲得咱們指望的結果。由於 d 和 e 兩個提交曾經被丟棄過,如此合併到 master 的代碼,並不會從新包含 d 和 e 兩個提交的內容,至關於只有 goudan/a-cool-feature 上的新 commit 被合併了進來,而 goudan/a-cool-feature 分支以前的內容,依然是被 revert 掉了。

  因此,若是想恢復整個 goudan/a-cool-feature 所作的修改,應該先把 G revert 掉:

  

   其中 G' 是對 G 的 revert 操做生成的 commit,把以前撤銷合併時丟棄的代碼恢復了回來,而後再 merge 狗蛋的分支,把解決 bug 寫的新代碼合併到 master 分支。

  能夠通俗的來理解:相對你本身 G 是經過別人來遠程操做的 revert 操做,相對於別人來講此時的 master 分支已經不存在 d 和 e 兩個提交的內容,而你本身本地分支上並無進行 revert 操做,相對於其餘人來講你本地認爲 master 分支還保存有 d 和 e 提交的內容,若是直接合並的話會報錯,故須要你本身在本地直接 revert 操做,將 g 點聯繫釋放掉,和線上原始 master 分支保持乾淨完整的鏈路,這樣就能夠正常的 merge commit 了。

6. revert 和 reset 區別

  1. git revert 是用一次新的 commit 來回滾以前的 commit,git reset 是直接刪除指定的 commit。 
  2. 在回滾這一操做上看,效果差很少。可是在往後繼續 merge 之前的老版本時有區別。由於 git revert 是用一次逆向的 commit 「中和」 以前的提交,所以往後合併老的 branch 時,致使這部分改變不會再次出現,可是 git reset 是直接把某些 commit 在某個 branch 上刪除,於是和老的 branch 再次 merge 時,這些被回滾的commit應該還會被引入。 
  3. git reset 是把 HEAD 向後移動了一下,而 git revert 是HEAD繼續前進,只是新的 commit 的內容和要 revert 的內容正好相反,可以抵消要被 revert 的內容。
相關文章
相關標籤/搜索