git 之 reset 操作

Overview

涉及Git一些日常操作 :)

基礎知識

《Pro Git》至少了解branch,commit的概念,及基本的原理

Git 工作區、暫存區和版本庫

Overview

暫存區(stage, index)是 Git 最重要的概念之一

  • 工作區: 你的目錄下面的文件們
  • 暫存區: 由.git/index保存引用,.git/object保存對象的區域
  • 版本庫: 倉庫

Relations

Why stage before commit

  • Split work into separate commits  分開提交,比如當只想提交一部分時
  • Don't break the build  不影響項目構建

HEAD

這樣的引用標識符——它看起來並不像一個普通的引用——其實並不包含 SHA-1 值,而是一個指向另外一個引用的指針。內容如下

 

 

HEAD~n

表示從當前HEAD指向的commit開始數的第幾個(參見git log HEAD或git log)

從0開始計數,git log中第一個commit 表示HEAD~0

reset

下面這段話非常重要

 

複製代碼
git reset [<mode>] [<commit>]
This form resets the current branch head to <commit> and possibly updates the index
(resetting it to the tree of <commit>) and the working tree depending on <mode>.
!!!!!! If <mode> is omitted, defaults to "--mixed". The <mode> must be one of the following:

–soft
Does not touch the index file nor the working tree at all (but resets the head to <commit>,
just like all modes do). This leaves all your changed files “Changes to be committed”,
as git status would put it.

–mixed
Resets the index but not the working tree (i.e., the changed files are preserved but not marked for
commit) and reports what has not been updated. This is the default action.

–hard
Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded.

–merge
Resets the index and updates the files in the working tree that are different between <commit> and HEAD,
but keeps those which are different between the index and working tree (i.e. which have changes which
have not been added). If a file that is different between
<commit> and the index has unstaged changes,
reset is aborted.

In other words, --merge does something like a git read-tree -u -m <commit>, but carries forward unmerged
index entries.

–keep
Resets index entries and updates files in the working tree that are different between <commit> and HEAD.
If a file that is different between
<commit> and HEAD has local changes, reset is aborted.

!!!If you want to undo a commit other than the latest on a branch, git-revert(1) is your friend.

複製代碼

 

將當前的branch head重置到某個commit上面,這可能會影響index(暫存)區域。
默認情況下使用--mixed形式`

下面是各個形式的差別

注意,暫時只關注soft, mixed, hard,另外還有兩種是merge和keep

working index HEAD target         working index HEAD
----------------------------------------------------
 A       B     C    D     --soft   A       B     D
                          --mixed  A       D     D
                          --hard   D       D     D

 

撤銷上次add的,(但不想改變工作目錄下面的代碼)

git reset HEAD (該命令會改變index與HEAD,使得文件狀態變成unstage)

如下圖所示:默認情況下,HEAD可以不寫。

該命令可以完整的寫法是git reset HEAD~0 --mixed

解釋爲重定向到這次的提交

working index HEAD target         working index HEAD
----------------------------------------------------
 A       B     C    C     --mixed   A       C     C

 

另外,從上面看來,值得注意的是以下寫法是等同的

  • git reset
  • git reset HEAD
  • git reset HEAD~0

撤銷上次commit的,(但不想改變工作目錄下面的代碼)

git reset HEAD~1 --mixed

解釋爲重定位到上次提交

(該命令會改變index與HEAD,使得文件狀態變成unstage)

working index HEAD target         working index HEAD
----------------------------------------------------
 A       B     C    D     --mixed   A       D     D

 

如果想完全忽略這次commit編輯的內容

1. 可以繼續使用 git checkout – . 清除所有與index(此時index已經等於上次commit)不同的改變

2. 或者直接使用 git reset HEAD~1 --hard

revert

簡單來說,執行某次commit操作的逆向操作,並且提交(默認提交)。

發佈回滾

回滾有兩種可能

  • 回滾線上項目正在使用的代碼
  • 回滾版本控制器中主線的源代碼

通常情況下,QA大叫出事啦出事啦,回滾回滾。意思是線上項目的回滾而非代碼的回滾。(當然最好還是問清楚是不是這樣)

源代碼真的要回滾嗎?

主線源代碼回滾,能做是能做,但比較麻煩。所以先case by case考察一下必要性。線上回滾,並不意味着源代碼一定要回滾。下面這些情況就不用回滾:

  • 線上回滾後,查出並不是因爲源代碼有問題。下次不用改源代碼,再發一遍rtag就好啦。
  • 下次線上發佈,是在修正前次失敗的發佈中的錯誤後,發佈前次失敗的發佈想發佈的內容。

只有當要修正前次失敗的發佈中的錯誤需要較長時間,而同時又有其他new feature或bug fix着急上線時,才需要主線上的源代碼回滾。

是reset還是revert

不論是使用reset還是使用revert都會帶來不同程度的麻煩

Reset比revert會帶來更多地麻煩。情況會非常複雜。

我們系統中使用revert。

已經merge master的開發分支,只需要繼續merge master即可(此次回滾完全不可見)

當前開發(正在發佈的),需要merge master之後 revert掉master上revert的那次commit

reference

  1. Git 工作區、暫存區和版本庫
  2. What is the benefit of git's two-stage commit process (staging)?
  3. What does 'stage' mean in git?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章