git的reset和checkout的區別

在講git的reset和checkout的區別以前,不得不說說HEAD、Index、Working Directory三個區域。git

HEAD、Index、Working Directory

Git裏有三個區域很重要緩存

  1. HEAD 指向最近一次commit裏的全部snapshot
  2. Index 緩存區域,只有Index區域裏的東西才能夠被commit
  3. Working Directory 用戶操做區域

下圖解釋了這三個區域的狀態的變化過程:spa

圖片描述

初始狀態

當你checkout分支的時候,git作了這麼三件事情code

  1. 將HEAD指向那個分支的最後一次commit
  2. 將HEAD指向的commit裏全部文件的snapshot替換掉Index區域裏原來的內容
  3. 將Index區域裏的內容填充到Working Directory裏

因此你能夠發現,HEAD、Index、Working Directory這個時候裏的內容都是如出一轍的。blog

注意:通常會誤解爲,Index中的內容是空的,只有git add後纔會有東西。實際上不是,Index裏一直是有東西的。圖片

因此,Git的全部操做就是對這三個區域的狀態(或內容)的操做。開發

Changed

若是你在Working Directory裏修改了文件,git會發現Working Directory裏的內容和Index區域裏的內容不一致了。get

這個時候git status的結果是:同步

# Changes not staged for commit:

Staged

一個文件僅僅changed是不能被commit的,Git要求只能提交Index裏的東西。it

因此須要git add。這個命令的意思是,把Changed的文件的內容同步到Index區域裏。這樣Working Directory和Index區域的內容就一致了。這個過程被稱之爲stage

這個時候git status的結果是:

# Changes to be committed:

Committed

最後,你就能夠提交了

git commit

這樣,就把HEAD的狀態和Index以及Working Directory造成一致了。

reset

reset是用來修改提交歷史的,想象這種狀況,若是你在2天前提交了一個東西,忽然發現此次提交是有問題的。

這個時候你有兩個選擇,要麼使用git revert(推薦),要麼使用git reset。

圖片描述

上圖能夠看到git reset是會修改版本歷史的,他會丟棄掉一些版本歷史。

而git revert是根據那個commit逆向生成一個新的commit,版本歷史是不會被破壞的。

已經push到遠程倉庫的commit不容許reset

上面已經講了,git reset是會丟棄掉commit的。

若是commit已經被push到遠程倉庫上了,也就意味着其餘開發人員就可能基於這個commit造成了新的commit,這時你去reset,就會形成其餘開發人員的提交歷史莫名其妙的丟失,或者其餘災難性的後果。

所以,一旦commit已經被push到遠程倉庫,那麼是堅定不容許去reset它的。

不帶文件參數的reset

前面章節已經說道Git有三個區域,Git的全部操做其實是在操做這三個區域的狀態(或內容)。

git reset配合不一樣的參數,對這三個區域會產生不一樣的影響。

reset實際上有3個步驟,根據不一樣的參數能夠決定執行到哪一個步驟(--soft, --mixed, --hard)。

  1. 改變HEAD所指向的commit(--soft)
  2. 執行第1步,將Index區域更新爲HEAD所指向的commit裏包含的內容(--mixed)
  3. 執行第一、2步,將Working Directory區域更新爲HEAD所指向的commit裏包含的內容(--hard)

注意

–mixed是默認參數,也就是說執行reset的時候不給就認爲是--mixed

下表說明了三種形式的git reset所產生的不一樣效果。

target表明想要將git指向到哪一個commit

working index HEAD target         working index HEAD
----------------------------------------------------
  A       B     C    D     --soft   A       B     D
                           --mixed  A       D     D
                           --hard   D       D     D
                           --merge (disallowed)

working index HEAD target         working index HEAD
----------------------------------------------------
  A       B     C    C     --soft   A       B     C
                           --mixed  A       C     C
                           --hard   C       C     C
                           --merge (disallowed)

帶文件參數的reset

上面講到的git reset實際上不帶參數的,若是帶上文件參數,那麼效果會是怎樣的?

  1. HEAD不會動
  2. 將那個commit的snapshot裏的那個文件放到Index區域中

須要注意的是帶文件參數的git reset沒有--hard, --soft這兩個參數。只有--mixed參數。

unstage

下面這兩個命令是同樣的,都是reset到HEAD上。

git reset file.txt
git reset --mixed HEAD file.txt

這個例子的意義在於,unstage file,仔細想想是否是這樣?當你把一個文件stage到Index區域裏後後悔了,那麼只須要把Index區域裏的這個文件恢復到最近一次commit的狀態(也就是HEAD),那就至關於unstage了。

恢復到歷史版本

下面這個命令就是將某個文件恢復到歷史版本上。

reset eb43bf file.txt

這個例子的意思在於,把某個文件恢復到Index區域裏,而後直接commit,這樣就等於把這個文件恢復到歷史版本了,這樣依賴你都不須要去改動Working Directory了。

checkout

前面講到checkout是會修改HEAD的指向,變動Index區域裏的內容,修改Working Directory裏的內容。

這看上去很像reset --hard,但和reset --hard相比有兩個重要的差異

  1. reset會把working directory裏的全部內容都更新掉
  2. checkout不會去修改你在Working Directory裏修改過的文件
  3. reset把branch移動到HEAD指向的地方
  4. checkout則把HEAD移動到另外一個分支

第二個區別可能有點難以理解,舉例來講:假設你有兩個分支master和develop,這兩個分支指向不同的commit,咱們如今在develop分支上(HEAD指向的地方)

若是咱們git reset master,那麼develop就會指向master所指向的那個commit。

若是咱們git checkout master,那麼develop不會動,只有HEAD會移動。HEAD會指向master。看圖:

圖片描述

帶文件參數

當執行git checkout [branch] file時,checkout幹了這件事情:

  1. 更新了index區域裏file文件的內容
  2. 更新了working directory裏file文件的內容

總結reset和checkout

head    index   work dir  wd safe
Commit Level
reset --soft [commit]    REF     NO      NO        YES
reset [commit]           REF     YES     NO        YES
reset --hard [commit]    REF     YES     YES       NO
checkout [commit]        HEAD    YES     YES       YES

File Level
reset (commit) [file]    NO      YES     NO        YES
checkout (commit) [file] NO      YES     YES       NO

「head」一列中的「REF」表示該命令移動了HEAD指向的分支引用,而「HEAD」則表示只移動了HEAD自身。 特別注意 「wd safe?」 一列,YES表示不會懂你在work dir的修改,NO表明會動你在work dir的修改。

相關文章
相關標籤/搜索