Git初始化
創(chuàng)建版本庫以及第一次提交
本章主要學(xué)習(xí):git init、git add和git commit
git --version //獲取git當(dāng)前版本
設(shè)置Git的環(huán)境變量,這是一次性的設(shè)置。即這些設(shè)置會在全局文件(用戶主目錄下的.gitconfig)或系統(tǒng)文件(/etc/gitconfig)中做永久的記錄。
-
告訴Git當(dāng)前用戶的姓名和郵件地址,配置的用戶名和郵件地址將在版本庫提交時(shí)作為提交者的用戶名和郵件地址。
注意下面的兩條命令不要照抄照搬,而是用您自己的用戶名和郵件地址代替這里的用戶名和郵件地址,否則您的勞動(dòng)成果(提交內(nèi)容)可要算到作者的頭上了。
$ git config --global user.name "Jiang Xin" $ git config --global user.email jiangxin@ossxp.com執(zhí)行下面的命令,刪除Git全局配置文件中關(guān)于user.name和user.email的設(shè)置:
$ git config --unset --global user.name $ git config --unset --global user.email -
設(shè)置一些Git別名,以便可以使用更為簡潔的子命令。
-
如果擁有系統(tǒng)管理員權(quán)限(可以執(zhí)行sudo命令),希望注冊的命令別名能夠被所有用戶使用,可以執(zhí)行如下命令:
$ sudo git config --system alias.br branch $ sudo git config --system alias.ci "commit -s" $ sudo git config --system alias.co checkout $ sudo git config --system alias.st "-p status" -
也可以運(yùn)行下面的命令,只在本用戶的全局配置中添加Git命令別名:
$ git config --global alias.st status $ git config --global alias.ci "commit -s" $ git config --global alias.co checkout $ git config --global alias.br branch
-
終端中輸入:
git init會在當(dāng)前目錄下初始化git倉庫,即:創(chuàng)建了隱藏目錄/{path}/.git。
.git版本庫目錄所在的目錄,稱為工作區(qū)。-
假如在這個(gè)目錄創(chuàng)建文件
hello.txt,那么現(xiàn)在在git的工作區(qū)出現(xiàn)了這個(gè)文件,但是文件還沒有添加進(jìn)入工作區(qū)。終端中輸入:git add hello.txt將這個(gè)文件進(jìn)行標(biāo)記(后面會提到,即:放入暫存區(qū)),繼續(xù)輸入git commit -m "說明描述",將文件添加進(jìn)本地的版本庫中。-
git add hello.txt這個(gè)只是標(biāo)記一個(gè)文件如果文件非常多如果這樣一個(gè)一個(gè)的添加未免有些麻煩,可以使用git add .來進(jìn)行批量操作。
-
Git暫存區(qū)
當(dāng)我們在工作去修改了文件之后,我們是不能直接將工作區(qū)的文件直接提交到本地的版本庫中的,在git中有一個(gè)被稱之為暫存區(qū)的文件,這相當(dāng)于是工作區(qū)與本地版本庫中的中間狀態(tài)(這里稱之為狀態(tài)其實(shí)也不合適,但是我也找不到用什么詞好)。當(dāng)我們在工作區(qū)的文件進(jìn)行了修改之后,將修改的文件add進(jìn)暫存區(qū),然后執(zhí)行commit,這樣就會將工作區(qū)的變動(dòng)存入版本庫中。
-
工作區(qū)中修改了文件
object.h- 執(zhí)行
git status -s精簡的狀態(tài)輸出
$ git status -s M object.h - 執(zhí)行
-
執(zhí)行命令
git add object.h,到這一步修改的文件只被提交到在暫存區(qū)。- 這時(shí)執(zhí)行
git diff會發(fā)現(xiàn)沒有輸出,因?yàn)檫@是對比的暫存區(qū)和版本庫中文件的差異。 - 執(zhí)行
git diff HEAD,將當(dāng)前工作區(qū)和HEAD(當(dāng)前版本庫的頭指針)進(jìn)行比較,會發(fā)現(xiàn)有差異。這個(gè)差異才是正常的,因?yàn)樯形凑嬲峤幻础?/li> - 執(zhí)行
git status -s精簡的狀態(tài)輸出與執(zhí)行g(shù)it add之前的精簡狀態(tài)輸出相比,有細(xì)微的差別
$ git status -s M object.h1. 雖然都是 M(Modified)標(biāo)識,但是位置不一樣。在執(zhí)行g(shù)it add命令之前,這個(gè)M位于第二列(第一列是一個(gè)空格),在執(zhí)行完git add之后,字符M位于第一列(第二列是空白)。 2. 位于第一列的字符M的含義是:版本庫中的文件和處于中間狀態(tài)——提交任務(wù)(提交暫存區(qū),即stage)中的文件相比有改動(dòng)。 3. 位于第二列的字符M的含義是:工作區(qū)當(dāng)前的文件和處于中間狀態(tài)——提交任務(wù)(提交暫存區(qū),即stage)中的文件相比也有改動(dòng)。 - 這時(shí)執(zhí)行
-
此時(shí)繼續(xù)修改本地文件
object.h- 執(zhí)行
git status -s精簡的狀態(tài)輸出,下面表示:不但版本庫中最新提交的文件和處于中間狀態(tài) —— 提交任務(wù)(提交暫存區(qū), stage)中的文件相比有改動(dòng),而且工作區(qū)當(dāng)前的文件和處于中間狀態(tài) —— 提交任務(wù)(提交暫存區(qū), stage)中的文件相比也有改動(dòng)。
$ git status -s MM welcome.txt- 不帶任何選項(xiàng)和參數(shù)調(diào)用
git diff顯示工作區(qū)最新改動(dòng),即工作區(qū)和提交任務(wù)(提交暫存區(qū),stage)中相比的差異。 - 將工作區(qū)和HEAD(當(dāng)前工作分支)相比(
git diff HEAD),會看到更多的差異。 - 通過參數(shù)
--cached或者--staged參數(shù)調(diào)用git diff命令,看到的是提交暫存區(qū)(提交任務(wù),stage)和版本庫中文件的差異。
- 執(zhí)行
-
現(xiàn)在執(zhí)行
git commit -m "備注"- 執(zhí)行
git status -s精簡的狀態(tài)輸出。此時(shí)第一列的M沒有了,表示暫存區(qū)-版本庫之間的變動(dòng)沒有了,因?yàn)闀捍鎱^(qū)中的內(nèi)容被提交到了版本庫。但是第二個(gè)M還在,表示工作區(qū)的內(nèi)容和暫存區(qū)之間還存在差異,需要將工作區(qū)的改動(dòng)add進(jìn)入暫存區(qū)。
$ git status -s M welcome.txt - 執(zhí)行

在這個(gè)圖中,可以看到部分Git命令是如何影響工作區(qū)和暫存區(qū)(stage,亦稱index)的。下面就對這些命令進(jìn)行簡要的說明,而要徹底揭開這些命令的面紗要在接下來的幾個(gè)章節(jié)。
- 圖中左側(cè)為工作區(qū),右側(cè)為版本庫。在版本庫中標(biāo)記為index的區(qū)域是暫存區(qū)(stage,亦稱index),標(biāo)記為master的是master分支所代表的目錄樹。
- 圖中可以看出此時(shí)HEAD實(shí)際是指向master分支的一個(gè)“游標(biāo)”。所以圖示的命令中出現(xiàn)HEAD的地方可以用master來替換。
- 圖中的objects標(biāo)識的區(qū)域?yàn)镚it的對象庫,實(shí)際位于.git/objects目錄下,會在后面的章節(jié)重點(diǎn)介紹。
- 當(dāng)對工作區(qū)修改(或新增)的文件執(zhí)行g(shù)it add命令時(shí),暫存區(qū)的目錄樹被更新,同時(shí)工作區(qū)修改(或新增)的文件內(nèi)容被寫入到對象庫中的一個(gè)新的對象中,而該對象的ID被記錄在暫存區(qū)的文件索引中。
- 當(dāng)執(zhí)行提交操作(git commit)時(shí),暫存區(qū)的目錄樹寫到版本庫(對象庫)中,master分支會做相應(yīng)的更新。即master最新指向的目錄樹就是提交時(shí)原暫存區(qū)的目錄樹。
- 當(dāng)執(zhí)行g(shù)it reset HEAD命令時(shí),暫存區(qū)的目錄樹會被重寫,被master分支指向的目錄樹所替換,但是工作區(qū)不受影響。
- 當(dāng)執(zhí)行g(shù)it rm –cached <file>命令時(shí),會直接從暫存區(qū)刪除文件,工作區(qū)則不做出改變。
- 當(dāng)執(zhí)行g(shù)it checkout .或者git checkout – <file>命令時(shí),會用暫存區(qū)全部或指定的文件替換工作區(qū)的文件。這個(gè)操作很危險(xiǎn),會清除工作區(qū)中未添加到暫存區(qū)的改動(dòng)。
- 當(dāng)執(zhí)行g(shù)it checkout HEAD .或者git checkout HEAD <file>命令時(shí),會用HEAD指向的master分支中的全部或者部分文件替換暫存區(qū)和以及工作區(qū)中的文件。這個(gè)命令也是極具危險(xiǎn)性的,因?yàn)椴坏珪宄ぷ鲄^(qū)中未提交的改動(dòng),也會清除暫存區(qū)中未提交的改動(dòng)。
Git重置
重置命令(git reset)是Git最常用的命令之一,也是最危險(xiǎn),最容易誤用的命令。來看看git reset命令的用法。
用法一: git reset [-q] [<commit>] [--] <paths>...
用法二: git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]
HEAD^代表HEAD的父提交
$ git reset --hard HEAD^
這條命令就相當(dāng)于將master重置到上一個(gè)老的提交上
- 終端中執(zhí)行
touch new-commit.txt命令,會在工作區(qū)創(chuàng)建一個(gè)名為new-commit的文件 - 此時(shí),工作區(qū)將會保存之前存在的文件和剛才創(chuàng)建的文件。繼續(xù)執(zhí)行
git reset --hard HEAD^。由于之前創(chuàng)建的文件沒有保存到倉庫中,所以執(zhí)行這條命令后HEAd所指向的master分支會重置到前一次提交并且工作區(qū)的文件也一起被重置了。
Ps. 實(shí)際上使用這個(gè)命令的時(shí)候,有的時(shí)候文件的內(nèi)容是會回到前一個(gè)版本,但是新增的文件不會刪除,但是還有的時(shí)候新增的文件也會刪除。我也不知道為什么,還請知道?的大神指點(diǎn)一波,還是說是我自己弄錯(cuò)了?。。。哈哈哈哈

命令格式: git reset [–soft | –mixed | –hard ] [<commit>]
-
使用參數(shù)
--hard,如:git reset –hard <commit>和git reset --hard HEAD^。- 會執(zhí)行上圖中的1、2、3全部的三個(gè)動(dòng)作。
- 替換引用的指向。引用指向新的提交ID。
- 替換暫存區(qū)。替換后,暫存區(qū)的內(nèi)容和引用指向的目錄樹一致。
- 替換工作區(qū)。替換后,工作區(qū)的內(nèi)容變得和暫存區(qū)一致,也和HEAD所指向的目錄樹內(nèi)容相同。
- 會執(zhí)行上圖中的1、2、3全部的三個(gè)動(dòng)作。
-
使用參數(shù)
--soft,如:git reset –soft <commit>- 會執(zhí)行上圖中的操作1。即只更改引用的指向,不改變暫存區(qū)和工作區(qū)。
-
使用參數(shù)
--mixed或者不使用參數(shù)(缺省即為--mixed),如:git reset <commit>- 會執(zhí)行上圖中的操作1和操作2。即更改引用的指向以及重置暫存區(qū),但是不改變工作區(qū)。
命令:
git reset-
命令:
git reset HEAD- 僅用HEAD指向的目錄樹重置暫存區(qū),工作區(qū)不會受到影響,相當(dāng)于將之前用git add命令更新到暫存區(qū)的內(nèi)容撤出暫存區(qū)。引用也未改變,因?yàn)橐弥刂玫紿EAD相當(dāng)于沒有重置。
命令:
git reset – filename-
命令:
git reset HEAD filename- 僅將文件filename撤出暫存區(qū),暫存區(qū)中其他文件不改變。相當(dāng)于對命令git add filename的反向操作。
-
命令:
git reset –soft HEAD^- 工作區(qū)和暫存區(qū)不改變,但是引用向前回退一次。當(dāng)對最新提交的提交說明或者提交的更改不滿意時(shí),撤銷最新的提交以便重新提交。
- 在之前曾經(jīng)介紹過一個(gè)修補(bǔ)提交命令
git commit –amend,用于對最新的提交進(jìn)行重新提交以修補(bǔ)錯(cuò)誤的提交說明或者錯(cuò)誤的提交文件。修補(bǔ)提交命令實(shí)際上相當(dāng)于執(zhí)行了下面兩條命令。(注:文件.git/COMMIT_EDITMSG保存了上次的提交日志)
命令:
git reset HEAD^-
命令:
git reset –mixed HEAD^- 工作區(qū)不改變,但是暫存區(qū)會回退到上一次提交之前,引用也會回退一次。
-
命令:
git reset –hard HEAD^- 徹底撤銷最近的提交。引用回退到前一次,而且工作區(qū)和暫存區(qū)都會回退到上一次提交的狀態(tài)。自上一次以來的提交全部丟失。
Git檢出
重置命令(reset)一般用于重置暫存區(qū)(除非使用
--hard參數(shù),否則不重置工作區(qū))
檢出命令(checkout)主要是覆蓋工作區(qū)(如果
<commit>不省略,也會替換暫存區(qū)中相應(yīng)的文件)
檢出命令(git checkout)是Git最常用的命令之一,同樣也很危險(xiǎn),因?yàn)檫@條命令會重寫工作區(qū)。
用法一: git checkout [-q] [<commit>] [--] <paths>...
用法二: git checkout [<branch>]
用法三: git checkout [-m] [[-b|--orphan] <new_branch>] [<start_point>]
用法一的<commit>是可選項(xiàng),如果省略則相當(dāng)于從暫存區(qū)(index)進(jìn)行檢出。
- 第一種用法(包含了路徑<paths>的用法)不會改變HEAD頭指針,主要是用于指定版本的文件覆蓋工作區(qū)中對應(yīng)的文件。如果省略<commit>,會拿暫存區(qū)的文件覆蓋工作區(qū)的文件,否則用指定提交中的文件覆蓋暫存區(qū)和工作區(qū)中對應(yīng)的文件。
- 第二種用法(不使用路徑<paths>的用法)則會改變HEAD頭指針。之所以后面的參數(shù)寫作<branch>,是因?yàn)橹挥蠬EAD切換到一個(gè)分支才可以對提交進(jìn)行跟蹤,否則仍然會進(jìn)入“分離頭指針”的狀態(tài)。在“分離頭指針”狀態(tài)下的提交不能被引用關(guān)聯(lián)到而可能會丟失。所以用法二最主要的作用就是切換到分支。如果省略<branch>則相當(dāng)于對工作區(qū)進(jìn)行狀態(tài)檢查。
- 第三種用法主要是創(chuàng)建和切換到新的分支(<new_branch>),新的分支從<start_point>指定的提交開始創(chuàng)建。新分支和我們熟悉的master分支沒有什么實(shí)質(zhì)的不同,都是在refs/heads命名空間下的引用。

-
命令:
git checkout branch檢出branch分支。要完成如圖的三個(gè)步驟,更新HEAD以指向branch分支,以branch指向的樹更新暫存區(qū)和工作區(qū)。
命令:
git checkout-
命令:
git checkout HEAD匯總顯示工作區(qū)、暫存區(qū)與HEAD的差異。
-
命令:
git checkout – filename用暫存區(qū)中
filename文件來覆蓋工作區(qū)中的filename文件。相當(dāng)于取消自上次執(zhí)行git add filename以來(如果執(zhí)行過)本地的修改。 -
命令:
git checkout branch – filename維持
HEAD的指向不變。將branch所指向的提交中的filename替換暫存區(qū)和工作區(qū)中相應(yīng)的文件。注意會將暫存區(qū)和工作區(qū)中的filename文件直接覆蓋。 -
命令:
git checkout – .或?qū)懽?git checkout .注意:
git checkout命令后的參數(shù)為一個(gè)點(diǎn)(“.”)。這條命令最危險(xiǎn)!會取消所有本地的修改(相對于暫存區(qū))。相當(dāng)于將暫存區(qū)的所有文件直接覆蓋本地文件,不給用戶任何確認(rèn)的機(jī)會!
Git恢復(fù)進(jìn)度
使用git stash
命令git stash可以用于保存和恢復(fù)工作進(jìn)度
命令git stash可以將當(dāng)前的工作狀態(tài)保存到git棧,在需要的時(shí)候再恢復(fù)
-
命令:
git stash保存當(dāng)前工作進(jìn)度。會分別對暫存區(qū)和工作區(qū)的狀態(tài)進(jìn)行保存。
-
命令:
git stash list顯示進(jìn)度列表。此命令顯然暗示了
git stash可以多次保存工作進(jìn)度,并且在恢復(fù)的時(shí)候進(jìn)行選擇。 -
命令:
git stash pop [–index] [<stash>]- 如果不使用任何參數(shù),會恢復(fù)最新保存的工作進(jìn)度,并將恢復(fù)的工作進(jìn)度從存儲的工作進(jìn)度列表中清除。
- 如果提供<stash>參數(shù)(來自于git stash list顯示的列表),則從該<stash>中恢復(fù)。恢復(fù)完畢也將從進(jìn)度列表中刪除<stash>。
- 選項(xiàng)--index除了恢復(fù)工作區(qū)的文件外,還嘗試恢復(fù)暫存區(qū)。
-
命令:
git stash apply [–index] [<stash>]除了不刪除恢復(fù)的進(jìn)度之外,其余和git stash pop命令一樣。
-
命令:
git stash drop刪除指定的一個(gè)進(jìn)度,默認(rèn)刪除最新的進(jìn)度,使用方法如git stash drop stash@{0}
-
命令:
git stash clear刪除所有存儲的進(jìn)度
-
命令:
git stash show顯示stash的內(nèi)容具體是什么,使用方法如 git stash show stash@{0}