A piece of Git

本文主要是對(duì)git-scm上的一篇博客的總結(jié)與補(bǔ)充,有說的不清楚的地方希望讀者能讀一下原博客

git的三個(gè)空間

在設(shè)計(jì)上,git將傳統(tǒng)的工作空間,也就是工作目錄,劃分為三個(gè)層次:

Paste_Image.png

由右往左分別為:工作目錄,暫存區(qū)和版本庫(kù)。中文翻譯版本眾多,我們就用它的英文版本好了。那么,平時(shí)我們工作于Working Directory,作出一部分修改后,我們會(huì)git add來將我們的修改暫存,也就是加入Index,最后使用git commit完成一次提交,也就是將當(dāng)前Index中的文件加入到版本庫(kù),并移動(dòng)HEAD指針指向當(dāng)前提交。如下圖:

git init
git add
git commit

git reset

git reset指令主要用來恢復(fù)文件,撤銷提交。

對(duì)整個(gè)工程使用reset

不指定特定文件時(shí)git reset指令會(huì)進(jìn)行如下3步操作:

  1. 修改HEAD(與其指向的分枝)指針,讓它(們)指向指定版本。這一步reset了版本庫(kù),僅影響到HEAD(與其指向的分枝)指針。
  2. 用指定版本的工程文件還原Index區(qū)。
  3. 用指定版本的工程文件還原Working Directory。

git reset命名后面帶的三種參數(shù)則分別表示reset過程進(jìn)展到上面的三個(gè)階段:

soft參數(shù)的reset僅進(jìn)行階段1
默認(rèn)參數(shù)(mixed)的reset進(jìn)行階段1和2
hard參數(shù)的reset進(jìn)行階段1,2和3,由于階段3不可逆,所以這條語(yǔ)句是危險(xiǎn)的

指定文件的reset

既然指定了reset特定文件,那就說明使用者的意圖不在于修改版本庫(kù),因此指定文件的reset命令都不會(huì)執(zhí)行階段1,也就是不會(huì)修改HEAD指針。實(shí)際上在指定文件的情況下,reset指令只會(huì)用版本庫(kù)中指定版本的文件還原Index區(qū)。

例子
實(shí)際應(yīng)用:撤銷git add的影響

git checkout

git checkout在功能上與reset命令很相似,但是二者確實(shí)是被設(shè)計(jì)用于不同場(chǎng)合的,下面來討論它們的區(qū)別。

不指定文件的checkout

效果上,不指定特定文件,git checkoutgit reset --hard幾乎完全一樣,區(qū)別在于:

  1. git checkout在對(duì)Working Directory進(jìn)行“安全檢查”。它會(huì)嘗試對(duì)你當(dāng)前Working Directory中的文件與指定checkout的版本進(jìn)行一次簡(jiǎn)單合并,如果在運(yùn)行git checkout之前,你改動(dòng)了工作區(qū)的文件,checkout操作不會(huì)覆蓋你當(dāng)前修改過的文件;而git reset --hard操作則僅僅簡(jiǎn)單粗暴的覆蓋整個(gè)工作區(qū)。所以git checkout操作是安全的。
  2. 我們知道HEAD作為頭指針實(shí)際上指向了版本庫(kù)當(dāng)中的分支指針,而分支指針才實(shí)際的指向某次提交,比如HEAD->master->8bcea這種結(jié)構(gòu)。git reset --hard命令實(shí)際是修改了上面例子中的master分支指針的指向;git checkout命令修改的則是HEAD指針的指向
reset與checkout

因此,checkout更多的用于分支切換非破壞性操作,而reset則用于還原破壞性操作。

指定文件的checkout

有沒有覺得剛剛在討論指定文件的reset操作時(shí),似乎漏了點(diǎn)功能?指定文件的reset只還原了Index區(qū),可是如何還原Working Directory?是的,指定文件的checkout操作可以還原當(dāng)前工作目錄。

也就是說,可以簡(jiǎn)單的理解為,指定文件的git checkout實(shí)現(xiàn)了指定文件的git reset --hard操作,它首先用特定文件還原Index區(qū),再還原Working Directory。

git revert

git revert命令可以被認(rèn)為是安全的reset操作。它會(huì)用指定版本的版本庫(kù)狀態(tài)在當(dāng)前的HEAD指針后面添加一個(gè)提交,并移動(dòng)HEAD指針。
也就是說,git會(huì)取出你指定的版本,“覆蓋”你的Working Directory,然后執(zhí)行:

git add .
git commit -m "Revert xxx"

這個(gè)操作的安全性在于:

  1. 不像reset那樣有可能修改提交歷史,而是增加了提交,符合git的設(shè)計(jì)思想,可逆操作。
  2. “覆蓋”Working Directory的過程與checkout指令類似,會(huì)進(jìn)行安全檢查。

下面是一個(gè)例子

Revert

git rm

*nix的軟件思想有一條是不做重復(fù)的工作,因此git rm/bin/rm功能是不同的:

  1. 默認(rèn)情況下,git rm會(huì)講文件同時(shí)從版本庫(kù)、Index和Working Directory刪除
  2. 加上--cached參數(shù)時(shí),rm操作會(huì)保留Working Directory中的文件,而將其它兩個(gè)區(qū)域中的指定文件刪除。

而刪除文件操作在git中也有安全限制,因此,如果Index或Working Directory中的指定文件與版本庫(kù)中的校驗(yàn)和不一致,git rm操作就會(huì)報(bào)錯(cuò),而-f參數(shù)可以指定強(qiáng)制刪除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容