前言
在第一講中我們對Git進行了簡單的入門介紹,相信聰明的你已經了解Git的基本使用了。

這一講我們來進一步深入學習Git應用,着重介紹Git的一些常見操作,包括:刪除文件、比較文件、撤銷修改、修改注釋與查看幫助文檔。
一、刪除文件
1.git rm <file>
該命令用於刪除版本庫中的文件;刪除工作區和暫存區中的文件都會報錯:
- 若用該指令刪除工作區中的文件,會報找不到文件的錯誤:

- 若用該指令刪除暫存區中的文件,報如下錯誤:

所謂版本庫中的文件指的是:已經通過
commit指令提交的文件,而不是工作區中的文件(紅色),或暫存區中的文件(綠色)。
git rm完成了兩步操作:
- 第一步:將版本庫中的文件刪除;
- 第二步:將刪除操作納入暫存區(
stage)。如下圖所示,相當於執行了git add test.txt,隨后可直接提交,完成test.txt的刪除;

2.rm <file>
該命令用於刪除工作區和版本庫中的文件,不能刪除暫存區文件;
注意:沒有添加到
git倉庫中的本地文件,都屬於工作區文件。
- 刪除工作區中的文件時:

- 刪除版本庫中的文件時:

與git rm不同的是,該指令不會將刪除操作納入暫存區。需要先將刪除的test.txt納入暫存區,再提交到版本庫才能完成test.txt文件的刪除;
- 刪除暫存區中文件時:

從圖中可知rm命令只能刪除工作區中的test3.txt,不能刪除暫存區中的test3.txt;:
二、重命名文件
1.git mv <file1> <file2>
使用git命令git mv:
git mv test.txt test3.txt
將test.txt重命名為test3.txt;mv命令可理解為剪切的同時進行更名;

changes to be committed 表示該修改已經納入暫存區,可以進行提交操作;
一般綠色的文件(操作)表示已經提交到暫存區了,不用再進行
git add,可以直接進行提交(git commit)。
從上文可知git mv做了兩件事:
- 第一步:將文件
test.txt重命名為test3.txt; - 第二步:將重命名操作
test.txt -> test3.txt納入暫存區;
2.mv <file1> <file2>
使用系統命令mv:
mv test2.txt test3.txt
執行該語句后查看狀態git status:

發現工作區中多出兩步操作:
-
刪除文件
test2.txt; -
新建文件
text3.txt;
再使用git add test2.txt test3.txt 將操作提交到暫存區,通過git status查看狀態:

此時git立即就能識別出來這是一個文件重命名;
由此說明git mv進行了三步操作:
- 第一步:刪除工作區中重命名前的文件
test2.txt; - 第二步:在工作區中創建重命名后的文件
test3.txt; - 第三步:將上述的兩個操作提交到暫存區中;
即git mv 與 mv的區別相當於git rm 與 rm 之間的區別。
三、比較文件
1.本地文件 <-> 本地文件
diff file_a file_b
這是系統提供的比較命令,用於比較本地文件或已經提交到版本庫的文件。創建文件a和文件b,使用上述指令進行比較:

在 diff -u a b的輸出信息中:
加上參數
-u可以更詳細地顯示比較信息。
-
--- a表示a為原文件; -
+++ b表示b為目標文件; -
-1,3中-表示原文件即a,1表示原文件中的第一行,3表示到第3行。合起來的意思為:在原文件a中的1~3行; -
同理:
+1,3表示:目標文件b中的1~3行; -
數據前面有三種符號,分別表示不同的信息:
- 空格:表示該行在兩個文件中都存在,如上圖所示
AABB這一行文件a,b都有; -:表示原文件a去掉該行就能變為目標文件b;+:表示原文件a加上該行就能變為目標文件b;
所以整個輸出信息的意思為:
AABB這一行兩文件都有,只要原文件a去掉: - 空格:表示該行在兩個文件中都存在,如上圖所示
a1
a2
並加上:
b1
b2
就能變為目標文件b;
2.工作區 <- 暫存區
以下為git提供的比較命令,作用為:比較暫存區和工作區中的同一文件。並且:原始文件為暫存區中的文件,目標文件為工作區中的文件。示例如下:
git diff
首先,新建文件A.txt和B.txt,修改其內容並提交到暫存區:

然后,在工作區中再次修改文件A.txt與B.txt的內容:

此時使用git diff進行比較:

在 git diff的輸出信息中:
-
--- a/A.txt:表示原文件為暫存區中的A.txt; -
+++ b/A.txt:表示目標文件為工作區中的A.txt; -
-1: 其中-表示原文件,1表示從第1行開始。由於暫存區中的A.txt文件(原文件)只有1行,所以將原來的(-1,1)簡寫為-1; -
+1,2:其中+表示目標文件,1,2表示工作區中的A.txt文件(目標文件)從第1行開始有2行; -
hello world:表示原文件和目標文件中都存在的內容; -
+hello java表示暫存區中的A.txt加上該行,就能變得與工作區中的A.txt一樣;
可以看到該指令是將同一文件的工作區版本與暫存區版本進行比較,各比各的,並不會將A.txt與B.txt進行比較。
3.工作區 <- 版本庫
以下指令作用為:比較版本庫和工作區中的同一文件。並且:原始文件為版本庫中的文件,目標文件為工作區中的文件。
git diff commit_id
用於比較指定commit id提交上的A文件和工作區中的A文件;
git diff HEAD
用於比較最新提交上的A文件和工作區中的A文件:
上面的
A文件僅為一個示例,以下同理。
如下圖所示,先初始化test.txt為:版本庫中的修改,然后進行一次提交;隨后在工作區中為test.txt添加工作區的修改;然后執行上述比較指令,從顯示出來的比較結果可知,工作區中的test.txt文件比最新一次提交的test.txt文件多了一行工作區中的修改內容。

4.暫存區 <- 版本庫
以下指令作用為:比較版本庫和暫存區中的同一文件,其中原始文件為版本庫中的文件,目標文件為暫存區中的文件:
git diff --cached commit_id
用於比較指定提交上的A文件和暫存區中的A文件;
git diff --cached
用於比較最新提交上的A文件和暫存區中的A文件。示例如下:

可以看到,暫存區中的A.txt文件比最新提交中的A.txt文件多了一行hello java;暫存區中的B.txt文件比最新提交中的B.txt文件多了一行hello java2。
5.總結
-
關於目標文件與原始文件的判定,遵循的順序為:工作區
<-暫存區<-版本庫(提交); -
上述比較指令的比較如下表所示:
指令 作用 原始文件 目標文件 diff <file1> <file2>比較兩個本地文件 本地文件/版本庫 本地文件/版本庫 git diff比較暫存區和工作區中的同一文件 暫存區 工作區 git diff commit_id比較指定 commit id提交上的A文件和工作區中的A文件版本庫 工作區 git diff HEAD比較最新提交上的 A文件和工作區中的A文件版本庫 工作區 git diff --cached commit_id比較指定提交上的 A文件和暫存區中的A文件版本庫 暫存區 git diff --cached比較最新提交上的 A文件和暫存區中的A文件版本庫 暫存區 表格中的
A文件僅為示例。
四、撤銷修改
主要是將已經納入暫存區的修改(綠色),先恢復到工作區(紅色),再恢復到修改前。比如撤銷git rm這一刪除操作:
1.將暫存區修改恢復到工作區(unstage)
也就是將對文件的修改操作由綠色變為紅色。
法一:git reset head <file>
如下圖所示,通過git rm刪除了版本庫中的test3.txt文件,並將該操作提交到了暫存區。隨后通過以上命令,將這一刪除操作恢復到了工作區;

法二:git restore --stage <file>
這里的參數--stage寫成--staged效果是一樣的,作用與法一相同:

2.撤銷工作區操作
比如撤銷工作區中對文件的修改、新增和刪除操作:
法一:git restore <file>
如下圖所示,在工作區中刪除了test3.txt文件。然后,通過上述指令撤銷了工作區中對test3.txt的刪除操作:

法二:git checkout -- <file>
作用與法一相同:

五、修改提交注釋與作者
1.修改最近一次提交信息
git commit --amend -m '修正信息'
如果寫錯了提交消息:

可以通過:git commit --amend -m '注釋' 來修改上一次的提交信息:(amend是修復的意思)

git commit --amend
當需要為最近一次提交添加大量注釋時,可以直接使用該指令進入vim編輯器編輯:


這樣的好處是:錯誤的提交和修正后的提交經過該命令修正后,只變為一次提交,而不是兩次提交;
git commit --amend --author 'Name<email>'
用於修改最近一次提交的配置信息,包含作者和注釋信息。執行命令時會進入vim編輯器編輯注釋信息:

修改前該分支上最近兩次的提交信息為:

修改后的最近兩次提交信息為:

可以看到成功地改變了最新一次提交的作者和提交注釋。
注意:修改提交注釋的同時,雖然提交的內容相同,但是提交前后的
commit_id是不同的,說明創建了一個新提交替換了原來需要修正的提交。如下圖中的提交5與提交3所示:
2.修改特定提交信息
如圖所示,在test分支進行了四次提交。現在我們想要修改第三次提交的提交信息:

git rebase -i commit_id
通過以上指令可以進入rebase交互模式,並顯示commit_id之后的提交信息。比如:若命令中的commit_id為第一次提交的commit_id,那么就會顯示第2~4次的提交信息。這里我們需要修改第三次提交的信息,只需要將它指定為第二次提交的commit_id即可。執行以下命令,進入vim編輯器:
git rebase -i 678e0

在這個界面中,我們可以通過將pick參數修改為其他rebase提供的參數,從而對第三次錯誤提交進行修改。有兩個參數可以實現這一目的:
這里涉及到
vim編輯器的使用方式:
shift + A為插入命令,可進入vim編輯器的編輯模式;- 編輯完成后,先按
ESC回到vim編輯器的命令行模式,再輸入:wq表示保存並退出編輯器;
reword參數
該參數的意思是:直接修改設置了該參數的提交的提交注釋。這里應該將第三次提交的pick參數改為reword:

通過:wq保存並退出,隨后再次進入vim編輯器,這次是修改設置了reword參數的提交的提交注釋:

將它改為正確的提交信息:

通過:wq保存並退出vim編輯器,完成錯誤提交信息的修改,再次查看歷史提交信息:

可以發現:錯誤的提交信息得到了糾正,並且這次提交及其之后的提交的commit_id都發生了變化。說明git新創建了對應數目的提交,並對原有提交進行了覆蓋,但是內容沒有發生變化;
事實上:
rebase的含義為變換基准,git rebase -i commit_id中的commit_id所指的提交節點就是新的基准點。該基准點之后的提交都會被git新創建的,內容一樣的新提交所覆蓋。rebase指令之后會詳細介紹。
edit參數
該參數也可以達到上述效果,只不過稍微多了幾個步驟。這個參數的意思是:停下rebase進程,編輯添加了該參數的提交,編輯完之后,通過調用git rebase --continue繼續進行rebase;具體如下:
將添加了錯誤提交信息的提交的pick參數改為edit參數:

通過:wq保存並退出:

可以看到,edit參數將rebase操作停了下來。根據提示,可以通過:
git commit --amend
進入vim編輯器,修改當前提交的注釋信息:

修改完后,通過:wq保存並退出vim編輯器。再調用:
git rebase --continue
繼續進行rebase操作,由此完成錯誤提交信息的修改:

此時查看test分支的提交歷史,會發現錯誤的提交信息得到了更正,並且與上reword參數一樣,創建了新的提交,對原有提交進行了覆蓋,同樣內容也不發生變化:

git rebase -i HEAD~n
通過上述指令也可以進入rebase交互模式,其中n表示需要顯示的最近n次提交記錄。比如通過以下指令,顯示test分支最近的三次提交記錄:
git rebase -i HEAD~3

進入rebase的交互界面之后,后續的操作和結果都與第一種方法一樣,這里就不再贅述了。
六、獲取幫助
1.git help config
該命令會打開git安裝目錄下的git-config幫助文檔:

文檔中詳細地顯示了相關操作指令的使用:

2.git config --help
效果與上述一樣,都是彈出同樣的幫助網頁;
3.man git-config
man為linux中自帶的幫助文檔,也可以查看幫助;
4.git
直接在命令窗口顯示常用的指令:


