git reset詳解

HEAD

HEAD也是不少初學者會搞不清楚的一個概念 說穿了也很簡單 就是git

你的目前branch的最新的commit
假設這是目前的git log, HEAD指向master的最新的commitspa

因此今天你下了git checkout b1
HEAD就會指向你checkout的那個branch的tip翻譯

但有個例外 由於checkout並不僅能夠指定branch 還能夠指定一個commit 因此當你checkout <commit>
clipboard.pngcode

他的意思是說 嘿 既然你指定的是commit 我就生一個暫時的branch給你 你如今的確在一個branch上 只是這個branch沒有名字 你能夠立刻checkout -b 生出一個branch 也能夠commit在這個沒有名字的branch上面
clipboard.pngip

再說一次 HEAD就是你的目前branch的最新的commit 即便這個branch可能沒有名字開發

git reset

git reset [ –soft | –mixed | –hard] <commit>

git reset <commit> 的意思就是 把HEAD移到<commit>rem

這是如今repo的狀況
clipboard.pngget

D在stage裡面, E在working裡it

我習慣想像成這樣 紅色就是還沒進staging 綠色就是還沒commit
clipboard.pngast

這裡的repo是指local的 不是remote的 別忘了一個鐵則 Working >= Staging >= Repo

這樣具體化以後 以後的解釋會簡單不少

再說一次 git reset <commit> 的意思就是 把HEAD移到<commit> 就是把你如今這個branch的最新的commit移到你指定的commit

soft就是隻動repo
mixed就是動repo還有staging(這個是默認參數)
hard就是動repo還有staging還有working

你只要知道這三種用法就能夠

如今的State是S0 由於等一下會一直回到如今的state, S0的HEAD在Repo的C

SOFT

soft 就是隻動repo

這樣子 staging裡面就會有c和d, working 裡e同樣

git reset --soft <B commit>

clipboard.png

HEAD會跑到repo的B

MIXED/DEFAULT

狀態回到S0

mixed就是動repo還有staging

這樣子 staging裡面就什麼都沒有, working 裡c,d,e

git reset --mixed <B commit>

clipboard.png

HEAD會跑到repo的B

HARD

狀態回到S0

hard就是動repo還有staging還有working

這樣子 staging裡面就什麼都沒有, working 裡什麼都沒有

git reset --hard <B commit>

clipboard.png

HEAD會跑到repo的B

git reset第二種用法

git reset <commit> [--] <file>

第二種的用法只是第一種的一個特例 就是前面的soft/mixed/hard不能指定 使用默認的mixed

而後後面能夠指定單獨的file

(先不要管[--])這個用法就是你能夠只針對一個file作出這個指令

git reset --mixed <commit>

至於--(double hyphen) 是避免有些人會把檔案名稱取的跟branch名稱同樣 或是你有個檔案就叫作"HEAD" 你就必須用 -- HEAD 而不是隻用HEAD 但基本上你不胡搞 你是不須要用到這個的

還有一件事 若是你commit不給 default就是HEAD, 若是你file不給 default就是整個資料夾

恭喜走出十里坡
基本上git reset已經講完了 你看到一個git reset的command你就知道執行下去會發生什麼事 但看到command知道會發生什麼事只是學git的第一步而已 你要知道什麼時候要用這個command纔是高手 如下說明常遇到 須要用git reset的例子

擴展閱讀(實例說明)

Unstage
有沒有看到那精美的

(use "git reset HEAD ..." to unstage)

爲什麼能夠呢 由於default是–mixed 因此白話文就是把HEAD移到HEAD(就是不要動的意思) 而後staging跟著變 這就表明把staging的狀態跟HEAD的狀態搞成同樣

因此要是從S0下這個指令

git reset HEAD d
會變這樣
clipboard.png

雖然會變成這樣是由於staging變得跟repo同樣 但你用git status看一下
clipboard.png

感受會像是d從staging變到working去了 因此結果看起來像是"unstage"

固然你要unstage全部的file就是

git reset HEAD
觸類旁通 你要unstage並且要把他們從working拿掉 就是

git reset --hard HEAD
Undo commit
這大概是首屈一指常見的問題 stackoverflow上問如何undo last commit的這題有一萬多個讚 事實上也很簡單 本來狀態是這樣
clipboard.png
下這個指令後

git reset --soft HEAD~
就變這樣 輕鬆
clipboard.png

在錯的branch上開發
還有一個蠻常見的狀況 你要開發前要先跟遠端的origin/master sync, sync完後你忘記換到本身的feature branch而是直接在master上開發 寫了兩個commit後忽然發現寫錯branch 該怎麼辦呢

如今狀況是這樣
clipboard.png

git branch feature_branch
複製一個新的branch 變成這樣
clipboard.png

git reset --hard origin/master
clipboard.png

git checkout feature_branch
clipboard.png

Squash commit
另外一個用法 也是我寫這篇文章的緣由 是我上禮拜要check in個人code進prod的時候 我必須把我全部local的commit變成一個commit 咱們組的Tech lead問我說該怎麼作 我跟他說 嘿嘿我知道 用git interactive rebase 他說那個比較麻煩 要選來選去 只要下一個簡單的git reset就能夠 我才大徹大悟 原來以前作學問沒有讀通 把簡單的事搞複雜了

假設如今要把CDE squash成一個commit push到remote 如今狀態是這樣
clipboard.png

這時候下個精美的

git reset --soft HEAD~3
就會變這樣
clipboard.png

那事實上上面那張跟下面那張是同一件事
clipboard.png

再下個git commit就搞定了

最後一題
最後來考一下這題 看你們是否是真的懂 當心是個陷阱題

這是如今的State:
clipboard.png

請問下完這個command以後

git reset --hard HEAD~1
會變成什麼樣子呢

(A)
clipboard.png
(B)
clipboard.png
(C)
clipboard.png

答案是B 你答對了嗎?

via:來源翻譯自jyt0532 的 Git reset

相關文章
相關標籤/搜索