Synopsisgit
git reset
, git checkout
, git revert
是git
工具箱中最經常使用的工具.它們都用來撤銷代碼倉庫中的某些更改,而前兩個命令不只能夠做用於提交,還能夠做用與特定的某個文件.shell
git倉庫由上圖三個部分組成,__Working Directory__ 工做目錄, Staged Snapshot 緩存區, Commit History 提交歷史.緩存
git reset
, git checkout
的參數決定了它們的做用域.若是沒有包含文件路徑,這些操做對於全部的提交生效,這一節探討提交層面的操做,git revert
沒有文件層面的操做.安全
在提交層面,reset將一個分支的末端(HEAD)指向另外一個提交歷史.這能夠用來移除當前分支的一些提交.好比,下面的這兩條命令讓_hotfix_分支向後回退了兩次提交.bash
git checkout hotfix git reset HEAD~2
如今hotfix分支末端的兩次提交變成了懸掛提交.也就是說,下次Git進行垃圾回收的時候,這兩個提交將被刪除.換句話說,若是你提交了錯誤的代碼,想要抹除掉本身已經提交的內容,你能夠用git reset
來丟掉你已經提交的代碼,可是默認不會修改你的工做區的代碼,因此回退以後你的工做區代碼沒有任何變化,可是git status
會變化.工具
走一遍流程:spa
git init
初始化一個倉庫
code
echo "init commit" >> README.md
作用域
git status
查看倉庫狀態
rem
git add .
跟蹤文件並提交至緩衝區
git commit -m 'init commit'
提交修改
按照上述流程再增長一個提交,下面直接寫shell
代碼
echo "first commit" >> README.md git add . git commit -m 'first commit'
下面是當前倉庫的狀態圖
提交歷史的狀態
git reset HEAD~1
回退代碼
此時的倉庫的狀態變成了這樣:
緩衝區和提交歷史區域的代碼所有被丟棄,倉庫的狀態也發生了改變.此時提交歷史是這樣的:
末尾的一次提交變成了懸掛提交.
除了默認的丟棄掉緩衝區和提交歷史的代碼,git reset
還有其餘的選項決定該命令的做用範圍.
--soft
工做目錄的代碼和緩衝區的代碼都不會改變 能夠稱之爲軟撤銷
--mixed
默認的方式,只會保留工做目錄的代碼
--hard
丟棄掉工做目錄,緩衝區,提交歷史中的代碼,能夠稱之爲硬撤銷
這些標記經常和git reset
一塊兒使用,--mixed
在你不想徹底捨棄本身的代碼,--hard
在你想徹底的丟棄本身的代碼.
注意: 當你傳入除HEAD之外的提交歷史的時候要格外當心,由於git reset
操做會重寫你的提交歷史,這意味着你以前的提交找不回來了,若是在公共分支上面這樣作,會致使其餘人的提交代碼丟失,切忌在公共分支上面這樣作.
這個應該是最經常使用的命令了,當傳入一個分支名是,git能夠切換到那個分支.
git checkout hotfix
上訴命令從當前分支切換到hotfix
分支,git只不過是將HEAD的指向切換到hotfix的末端,而後更新工做目錄.由於這個操做可能會覆蓋當前工做目錄的內容,因此git在切換以前會強制要求你提交當前工做目錄或者是緩衝區中的修改,否則在checkout
的時候這些修改將會丟失.和git reset
不一樣的是,git checkout
並無修改這些分支.僅僅是切換了HEAD的引用.
除了分支之外,你還能夠傳入提交的引用來checkout
到任意的提交.這和checkout
到任意的分支是同樣的: 切換HEAD的引用到特定的提交.好比,下面這條命令會checkout
到當前提交的祖父分支:
git checkout HEAD~2
這對於查看當前分支的歷史記錄很是重要.但若是你當前的HEAD沒有任何分支的引用,那麼這會形成HEAD的分離.這是很是危險的,若是你接着提交新的提交,而後切換到其餘分支以後就沒有辦法回到以前添加的那些提交.所以,在爲分離的HEAD添加新的提交以前你應該建立一個新的分支.
Revert撤銷一個提交的同時會建立一個新的提交。這是一個安全的方法,由於它不會重寫提交歷史。好比,下面的命令會找出倒數第二個提交,而後建立一個新的提交來撤銷這些更改,而後把這個提交加入項目中。
git checkout hotfix git revert HEAD~2
未完待續 2017.5.26