前言
在第一講中我們對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
直接在命令窗口顯示常用的指令: