掌握Git撤銷操作,隨心所欲控制文件狀態
本文主要討論和撤銷有關的 git 操作。目的是讓讀者在遇到關于撤銷問題時能夠方便迅速對照執行解決問題,而不用去翻閱參數繁多的 git 使用說明。
一開始你只需了解大致功能即可,不必記住所有命令和具體參數。事實上,如果沒有經過反復多次的操作,這些沒血沒肉的命令是很難被全部記清楚的,就算現在記住了,也會很快遺忘(天賦異稟,過目不忘者除外)。建議讀者在遇到特定問題時對照場景操作,多用幾次自然就記住了。
首先,我們再看看上一篇文章中的這張圖:
git 命令和文件狀態轉換
這張圖能讓你一目了然的看到各種命令產生的效果。其中箭頭移動方向可以理解成文件版本的復制方向。根據箭頭的指向,我們能清楚的看到每個操作所產生的影響。幾乎所有的git操作也就是讓文件在這三個工作區域內移動,列如:
- git add files 工作目錄下files復制 ->暫存區;
- git checkout files 暫存區files復制 -> 工作目錄;
- git commit 暫存區內的文件作為一個版本保存 -> 版本庫。
為了使本文更具實用性,讓我們來結合上圖,通過實際項目中可能遇到的問題,以 Q&A 的形式來逐一討論,當你遇到相似問題時可以迅速找到解決方法。
-
Q: git add之后如何撤銷?
TL;DR [1] 答案: 可以使用 git reset 撤銷 所有 暫存區域文件。使用git reset file 來撤銷特定的文件。該命令只是把暫存區內容移除,不會覆蓋工作目錄中已經修改過的同名文件。
考慮這個場景,你正在為你的項目添加一個新功能,快完成時,你打算暫存起來,測試好了再 commit,于是你使用:
git add home.js把涉及新功能改動的文件 home.js 暫存起來。此時你突然接到一個很緊急的 bug,需要立刻修復,你在一通 debug 之后成功 fix 了 bug,于是把涉及該 bug 的更新添加到暫存區:
git add main.js common.js在準備使用 git commit 提交改動之前,你習慣性看看暫存區有哪些文件會被提交,于是你使用 git status 發現暫存區有三個文件:
home.js main.js common.js很顯然,你此時只想提交關于 bug 的修改部分文件,如果此時使用 git commit 會把關于其他功能的修改一起提交。那如何移走暫存區域home.js?很簡單,只要執行 git reset 即可移除:
git reset home.js之后執行 git commit 來提交這次 bug 修復所引起的改動。
當然,如果你打算先提交新功能改動之后再提交 bug 修復內容,你可以先使用
git reset main.js common.js 取消暫存區 bug 修改相關文件,再執行
git commit -
Q: 如何丟棄工作目錄的更改?
答案:使用 git checkout file 。 注意 ,該操作不可逆,一旦被執行,你的改動都會消失,一般情況下只有你非常確定不需要工作目錄下的最新改動內容才會這么做。 該命令會用暫存區的 file 內容覆蓋掉工作目錄的 file 文件內容。如果這個文件沒有加入暫存區(或者說暫存區該 file 內容和Git倉庫內容相同),執行該命令后,工作目錄中該文件版本將和Git倉庫最近一次提交版本相同。舉例:
git checkout home.js注意,如果你正好有個 branch 名字叫 home.js, git checkout 會checkout 一個 branch,此時你可以加上 -- 來用來表明這是個文件。
git checkout -- home.js如果你想直接用最新的git倉庫文件同時覆蓋掉暫存區和工作目錄內容可以使用(參見前文圖示):
git checout HEAD -- files -
Q: 如何丟棄本地倉庫的 commit 內容?
git reset --soft HEAD~1執行上述操作會撤銷最后一次 commit 產生的效果并且保留 working directory 你所改動的內容。
git reset --hard HEAD~1
執行上述操作會撤銷最后一次 commit 產生的效果并且 覆蓋 working directory 你所改動的內容。慎用,你一天的工作可能就此付之一炬,出了問題不能懶我(無辜狀)。如果想取消最近N次的 commit 內容,只要把上面的1換成相應的數字即可。
-
Q: 如何獲取Git服務器上最新內容?
經常拉取新內容,可以減少 code merge。只要簡單的執行 git pull 即可。注意還有一個類似的命令是 git fetch,二者的區別簡單來說是:
git pull = git fetch + git merge
最后總結關于撤銷操作的要點
操作 | 撤銷 |
---|---|
git add file | git reset 重置暫存區內容,使得暫存區版本和倉庫版本一致 git reset file 重置某一個文件的暫存狀態,產生效果也就是把該文件從暫存區移除 |
修改了工作區文件 | git checkout -- files 用暫存區版本 覆蓋 工作區文件 git checout HEAD -- files 用git倉庫最近版本 覆蓋 工作區文件 |
git commit | git reset --soft HEAD~1 撤銷最近一次 commit 且不刪除工作區改動 git reset --hard HEAD~1 撤銷最近一次 commit 且強制同步工作區版本到這 commit 改動之前狀態 |
參考文獻
來自:http://www.jianshu.com/p/4ebbff227b87