Git新手教程-撤銷更改(七)

前言

在前面的文章中,咱們學習了標籤、分支、和合並。如今咱們將學習Git中另外的三個命令git commit --amend , git revert , git reset。下面簡單的介紹中幾個命令的功能:java

  • git commit --amend :能夠修改最後一次提交中的內容,加東西,加文件。修改 commit 信息。
  • git revert :能夠撤銷對應的 commit ,併產生一個新的 commit 。
  • git reset :能夠清除最近的 commit 。並不能任意刪除,須要按照順序。

git commit --amend

在平時的項目開發中,有時候咱們可能提交完相應文件後,才發現漏掉了幾個文件沒有添加,或者咱們 commit 消息並無書寫完整或有錯別字。那這個時候咱們該整麼辦呢?或許咱們會執行一個新的提交來添加咱們遺漏的內容,可是這樣一點都不優雅!!在Git中爲咱們提供了帶有 --amend 選項的提交來修改咱們最近的提交:git

amend 中文意思是修改、改善、改進。bash

git commit --amend
複製代碼

這裏你們可能仍是不是很明白,咱們看下面這個簡單的例子:less

撤銷更改1.png

在上述例倉庫中咱們建立了一個 commit ,該 commit 消息並無書寫完整。這個時候咱們想修改它,那麼咱們就可使用命令 git commit --amend ,當輸入該命令後,咱們能獲得以下彈窗:編輯器

你也可使用 git commit --amend -m + 提交信息 跳過編輯器,直接修改 commit 信息。ide

撤銷更改2.png

這個時候,咱們就能夠完善該 commit 信息,而後保存並離開。這裏我改爲了 刪除了多餘的語句 ,這時咱們再使用 git log 命令,咱們會發現咱們的 commit 消息已經被更改了。以下所示:學習

撤銷更改3.png

固然在上述例子中,咱們只是簡單的修改了 commit 信息,並無修改或添加一些新的文件,若是你修改或添加了新的文件,並想將這些修改的文件添加到最近的 commit 中去的話,那麼你可能要經歷如下步驟:spa

  • 編輯文件
  • 保存文件
  • 暫存文件 (git add)
  • 運行 git commit --amend

在實際的項目中,若是你想修改最近的 commit ,那麼你須要使用 git commit --amend 來更新最近的 commit ,而不是建立新的 commit 。ssr

git revert

在上述例子中,咱們知道了如何修改最近的 commit ,可是若是咱們想還原這個 commit 。那這個時候,咱們又該怎麼辦呢?咱們可使用 git revert 命令來告訴 Git 還原以前建立的commit,該命令使用的方式以下:3d

當你告訴 Git 還原(revert) 具體的 commit 時,git 會執行和 commit 中的更改徹底相反的更改。假設 commit A 添加了一個字符,若是 Git 還原 commit A,那麼 Git 將建立一個 新的 commit ,並刪掉該字符。若是刪掉了一個字符,那麼還原該 commit 將把該內容添加回來!

git revert <SHA-of-commit-to-revert>
複製代碼

仍是以上述例子來進行講解,好比咱們想還原下圖中紅色框中的 commit :

撤銷更改4.png

咱們可使用 git revert b71b40 ,須要注意的是使用該命令,默認會建立一個新的提交。以下圖所示:

這裏 b71b40 是對應 commit 的 SHA 的前七個字符,固然你也可使用完整的 SHA 。

撤銷更改5.png

通常狀況下,咱們可使用Git系統默認的 revert 信息。當咱們保存並退出後,再使用 git log 命令查看咱們的日誌提交記錄,咱們能獲得下圖:

撤銷更改6.png

git reset

git reset 簡介

在上述例子中,咱們學會了如何還原一個提交,可是若是咱們本是這個提交就是錯誤的,咱們並不想要這個提交,也不想倉庫記錄中包含 revert 的提交記錄。這個時候咱們又該怎麼辦呢?咱們可使用 git reset 命令來告訴 Git 重置 commit 。

重置(reset) 彷佛和 還原(revert) 類似,但它們實際上差異很大。還原會建立一個新的 commit,並還原或撤消以前的 commit。可是重置會清除 commit!

git reset 命令是少數幾個能夠從倉庫中清除 commit 的命令,若是某個 commit 再也不存在與倉庫中,它所包含的內容也會消失。不過不用擔憂,Git 會在徹底清除任何內容以前,持續跟蹤提交記錄大約30天,咱們能夠經過 git reflog 來查看倉庫中全部的改變。關於 git reflog 你能夠查看下方內容:

git reset 命令的使用

git reset 命令相比其餘 Git 命令功能要多一點,能夠用來:

  • 將 HEAD 和當前分支指針移到目標 commit。
  • 清除 commit 。
  • 將 commit 的更改移動到暫存區中。
  • 取消暫存 commit 的更改。

git reset 並不直接使用 commit 的 SHA ,而是使用特殊的 "祖先引用" 來告訴 Git 將 HEAD 指針移動到哪一個commit。咱們來看看這些特殊的符號。

  • ^ : 表示父 commit
  • ~ : 表示第一個父 commit

咱們能夠經過如下方式引用以前的 commit:

  • 當前 commit 的父 commit
HEAD^
HEAD~
HEAD~1
複製代碼
  • 當前 commit 的祖父 commit
HEAD^^
HEAD~2
複製代碼
  • 當前 commit 的曾祖父 commit
HEAD^^^
HEAD~3
複製代碼

^~ 的區別主要體如今經過合併而建立的 commit 中。合併 commit 具備兩個父級。對於合併 commit,^ 引用用來表示第一個父 commit,而 ^2 表示第二個父 commit。第一個父 commit 是當你運行 git merge 時所處的分支,而第二個父 commit 是被合併的分支。

咱們看下面的例子,來一塊兒來理解:

可使用 git log --oneline --graph --all 來查看全部的分支信息。

顯示全部分支信息.png

由於 HEAD 指向 b71b405 commmit。

  • 那麼 f8d5383 commit 咱們能夠這樣表示:
    • HEAD^
    • HEAD~1
  • 那麼 9fdb3f6 commit 咱們能夠這樣表示:
    • HEAD^^2( ^2 表示合併分支上的父提交)
  • 那麼 48099db commit 咱們能夠這樣表示:
    • HEAD^^
    • HEAD~2

瞭解了祖先引用,如今咱們來了解 git reset 命令的使用:

git reset <reference-to-commit>
複製代碼

通常狀況下,使用該命令,咱們會添加以下選項:

  • --mixed (默認不指定任何選項)移動到工做目錄,不會暫存咱們的文件,工做內容與原來相同,可是SHA不一樣,由於時間戳不一樣。
  • --soft 移動到暫存區,這些改動仍然存在,並且已經暫存好了。
  • --hard 會刪除對應全部的提交的內容。

直接理解這些選項比較困難,下面咱們將結合圖片與實際例子來進行講解。

--mixed 例子

在下圖中,假如咱們的倉庫中已經有了以下提交 D、E、F、G、H,其中 master 指向最近的提交 HHEAD 指向 master

這個時候咱們若是使用 git reset --mixed HEAD~1 那麼會將 masterHEAD 將會指向前一個提交 G。同時 G 提交會移動到工做目錄中。以下圖所示:

注意,git reset --mixed HEAD~1 等同於 git reset --mixed HEAD^ ,也等同於 git reset HEAD~1 (git reset 命令默認選項爲 --mixed)。

rest_mixed演示.jpg

H 提交修改的文件被移動到到工做目錄後,文件的狀態都爲 modifed,也就是咱們須要從新添加到暫存區,而後進行 commit 。咱們繼續看下面的例子:

mixed_展現.png

在上述倉庫中有3個提交,其中 HEAD 指向 bb780f9 上的 master , 這個時候若是咱們運行 git reset HEAD~ 命令,會將 commit bb780f9 中的文件移動到工做目錄中,以下所示:

mixed_2.png

調用 git status 來查看咱們的倉庫狀態,咱們會發現使用 --mixed 選項,是不會暫存咱們的更改的,也就是不會將相應提交的文件放入暫存區中。

--soft 例子

當使用 --soft 選項時,不只會移動 masterHEAD 指針,還會將相應修改添加到暫存區中,以下所示:

reset_soft演示.jpg

咱們繼續查看下面的例子:

soft展現.png

--hard 例子

最後咱們再來看看 --hard 選項:

reset_hard演示.jpg

使用 --hard 將清除對應 commit 所做的更改,繼續查看下面的👇的例子:

hard展現.png

當使用了 --hard 選項後,發現倉庫中對應的提交消失了。

取消暫存區中的內容

當咱們直接使用 git resetgit reset HEAD時,表示清除暫存區中的 commit 。下面咱們來看這個例子:

edit
git add A.java B.java   (1)
git reset               (2)
複製代碼
  1. 咱們添加了兩個Java文件到暫存區中。
  2. 可是在後續中,咱們發現咱們還須要對這兩個文件進行修改,那麼咱們可使用 git reset 命令將這另個文件從暫存區中移除。固然咱們也可使用 git reset HEAD 命令,這兩個命令是等價的。

那麼若是咱們只想將 B.java 文件從暫存區中移除,那咱們又該怎麼辦呢?咱們可使用以下命令:

git reset HEAD B.java
複製代碼

固然在Git中支持多個文件的取消暫存,具體命令以下:

git reset HEAD <file>...
複製代碼

在上述命令中 <file>... 表明一個或多個文件。

IntelliJ IDEA or Android Sutdio 圖形化界面的使用

最後仍是回到咱們熟悉的圖形化界面的使用流程中。咱們來看看IDEA爲咱們提供了哪些便利吧。

使用 git commit --amend

在建立相應 commmit 時,咱們能夠勾選下圖中的 Amend commit 選項。以下所示:

ide_amend.png

上述操做與使用 git commit --amend 命令的效果同樣。

使用 git revert

經過依次點擊編譯器底部的Version Control->Log,而後選擇想要 revert 的 commit ,點擊鼠標右鍵,選擇 Revert Commit 就能夠啦~

ide_revert.png

使用 git reset

經過依次點擊編譯器底部的Version Control->Log,而後選擇想要 reset 的 commit ,點擊鼠標右鍵,選擇 Reset Current Branch to Here.. 就完成第一步啦~

ide_reset_1.png

固然在第二步中,咱們須要選擇 git reset 中的選項,在 IDEA 中提供了四種選項 Soft、Mixed、Hard、Keep ,以下所示:

ide_reset_2.png

在上圖中,咱們不熟悉的只有 --keep 選項,由於該選項在平時中的項目並不經常使用,因此這裏就不作更多介紹了,有興趣的小夥伴,能夠查看官方文檔中 git reset 中對其的介紹。

最後

站在巨人的肩膀上,才能看的更遠~

相關文章
相關標籤/搜索