使用Git你後悔過嗎?

使用Git你後悔了嗎?

人總會有犯錯的時候,值得感激的是Git容許你在任什麼時候候反悔,而且將對應信息從歷史記錄中抹除,這樣的歷史記錄每每看起來行雲流水,使人賞心悅目,嚴謹的提交信息是對他人的一種尊重。git

改變最近的一次提交

git commit --amend

若是你想改變上一個commit的提交信息與文件內容,便可使用--amend命令,它容許你將暫存區的修改合併到上一個commit,從而生成一個新的commit,您也能夠僅適用它來修改commit message。shell

須要注意的是,若是已經將commit到遠程庫,不建議使用ammend命令,由於這樣會修改掉最近一次commit的hash值,只能強制推送才能push上去,若是你的commit已經同步到了其餘倉庫或別人已經拉取以前的提交,這樣強推上去就會產生衝突。this

重置某一次提交內容

git revert [<commit>]

若當某一次的提交內容致使一些錯誤發生,一般會進行還原操做,此時revert就派上用場了,它會生成一條新的commit,將指定的commit中包含的更改進行還原。3d

revert是一個十分禮貌的命令,對於多人協做的項目來說,是十分有用的,由於它會保持HEAD指針在不斷的前進,不會產生意想不到的衝突。指針

將最近幾個提交合併爲一個

git rebase -i [<start_commit>] [<end_commit>]

在推送到遠程分以前,爲了保持邏輯清晰可回溯步驟,咱們須要會進行許多個小的提交,而到推送到遠程庫的時候,更但願將其彙總爲一個feat提交,這時命令就派上了用場。rest

首先咱們來初始化一個git倉庫:code

mkdir gittest && cd gittest && git init
touch a && git add * && git commit -m 'a'
touch b && git add * && git commit -m 'b'
touch c && git add * && git commit -m 'c'
touch d && git add * && git commit -m 'd'

這時執行git log可獲取到如下信息:排序

commit b9843274e87455a87b16802ebb2b48cf8cb67175 (HEAD -> master)
    d
commit dc681aadc81491c3d2b2cb2f8ca1d66586f65903
    c
commit db9dc842b6c854b7175c03c7fd50bf08a262cfcb
    b
commit 3bc7dbe4ddfad85606e6dd39c6583d8fa7b353b7
    a

爲了將b、c合成爲一個提交,咱們須要選取最近3個提交進行才行,須要注意的是指定兩個commit範圍時區間爲前開後閉區間(],若是省略第二個end_commit則會指向HEAD指針,所以如下三個命令是等效的:索引

  • git rebase -i HEAD~3
  • git rebase -i 3bc7dbe4ddfad85606e6dd39c6583d8fa7b353b7
  • git rebase -i 3bc7dbe4ddfad85606e6dd39c6583d8fa7b353b7 b9843274e87455a87b16802ebb2b48cf8cb67175

這時會彈出一個交互界面:rem

pick 3a13544 b
pick 3b3d704 c
pick 9205e1b d

# Rebase 97b2217..9205e1b onto 97b2217 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

註釋裏已經包含了一切你須要知道的信息,在這裏仍是簡單的描述下:

  • 命令會從上到下執行,按時間的前後順序進行合併commit
  • 提交可被從新排序,在這裏可交互b與c的順序後保存退出,打印的commit信息即爲:a -> c -> b -> d
  • 若刪除某行,可移除對應的整個提交內容
  • 命令有如下不一樣的模式:

    • pick:保留該commit(縮寫:p)
    • reword:保留該commit,但我須要修改該commit的註釋(縮寫:r)
    • edit:保留該commit, 但我要停下來修改該提交(不只僅修改註釋)(縮寫:e)
    • squash:將該commit和前一個commit合併(縮寫:s)
    • fixup:將該commit和前一個commit合併,但我不要保留該提交的註釋信息(縮寫:f)
    • exec:執行shell命令(縮寫:x)
    • drop:我要丟棄該commit(縮寫:d)

在選取範圍時,咱們每每會指定一個start_commit,那麼若是commit爲第一個提交呢?由於命令爲前開區間,這時候就沒法選取了,只能經過--root指定:git rebase -i --root

以上命令儘可能都本身嘗試一遍。

回退到指定版本

git reset [<mode>] [<commit>]

首先應該理清HEAD、暫存區、工做區三者的關係再去使用reset命令。使用reset回退版本一般是經過移動HEAD指針的指向來實現的,HEAD是當前分支引用的指針,它老是指向該分支上的最後一次提交。當HEAD指針發生變化時,有幾種模式能夠選擇:

  • --soft,暫存區與工做區都不會重置,只會重置掉提交。此模式不改變暫存區與工做區的文件內容,僅僅是將HEAD指針位置邊了,這樣全部在reset指定的提交以後的提交都會被撤銷,文件更改集中放在了暫存區。
  • --mixed,重置暫存區,但不會重置工做區。reset會用HEAD指向的快照去更新暫存區的內容,只保留工做區的文件,簡單的說,回到了git add以前。
  • --hard,同時重置暫存區和工做區。它會完全棄用以後的提交,且不可撤銷。

總結

文章只是涉及一些淺顯的用法,但願在玩轉重寫Git時,您也應該掌握:

  1. 理解Head、Index、Working Directory,即頭部索引、暫存區、工做目錄之間的聯繫。
  2. 使用git reflog隨時對進行的操做進行撤銷。
  3. 理清chekout與reset的區別。
  4. 多多練習rebase各類命令操做。

以上只是拋磚引玉,最重要的是能知道本身在作什麼,清楚操做帶來的影響

參考資料

相關文章
相關標籤/搜索