Git(6)-- 記錄每次更新到倉庫(git clone、status、add、diff、commit、rm、mv命令詳解)

2021AY發表於2021-08-18

@

1、克隆現有倉庫:git clone

還是以之前做好的為例:

git clone git@github.com:2021AY/testfirst.git

在這裡插入圖片描述

現在我們的機器上有了一個 真實專案 的 Git 倉庫,並從這個倉庫中檢出了所有檔案的 工作副本。通常,你會對這些檔案做些修改,每當完成了一個階段的目標,想要將記錄下它時,就將它提交到到倉庫。

工作目錄下的每一個檔案都不外乎這兩種狀態:已跟蹤 或 未跟蹤。已跟蹤的檔案是指那些被納入了版本控制的檔案,在上一次快照中有它們的記錄,在工作一段時間後,它們的狀態可能是未修改,已修改或已放入暫存區。簡而言之,已跟蹤的檔案就是 Git 已經知道的檔案。

工作目錄中除已跟蹤檔案外的其它所有檔案都屬於未跟蹤檔案,它們既不存在於上次快照的記錄中,也沒有被放入暫存區。初次克隆某個倉庫的時候,工作目錄中的所有檔案都屬於已跟蹤檔案,並處於未修改狀態,因為 Git 剛剛檢出了它們, 而你尚未編輯過它們。

編輯過某些檔案之後,由於自上次提交後你對它們做了修改,Git 將它們標記為已修改檔案。工作時,你可以選擇性地將這些修改過的檔案放入暫存區,然後提交所有已暫存的修改,如此反覆。

在這裡插入圖片描述

2、檢查當前檔案狀態 :git status

可以用 git status 命令檢視哪些檔案處於什麼狀態。 如果在克隆倉庫後立即使用此命令,會看到類似這樣的輸出:
在這裡插入圖片描述
這說明你現在的工作目錄相當乾淨。換句話說,所有已跟蹤檔案在上次提交後都未被更改過。 此外,上面的資訊還表明,當前目錄下沒有出現任何處於未跟蹤狀態的新檔案,否則 Git 會在這裡列出來。 最後,該命令還顯示了當前所在分支,並告訴你這個分支同遠端伺服器上對應的分支沒有偏離。 現在,分支名是“main”,這是預設的分支名。

在專案下建立一個新的 Excel.xlsx 檔案。 如果之前並不存在這個檔案,使用 git status 命令,你將看到一個新的未跟蹤檔案:在這裡插入圖片描述
在狀態報告中可以看到新建的 Excel.xlsx 檔案出現在 Untracked files 下面。 未跟蹤的檔案意味著 Git 在之前的快照(提交)中沒有這些檔案;Git 不會自動將之納入跟蹤範圍,除非你明明白白地告訴它“我需要跟蹤該檔案”。 這樣的處理讓你不必擔心將生成的二進位制檔案或其它不想被跟蹤的檔案包含進來。

3、跟蹤新檔案:git add

使用命令 git add 開始跟蹤一個檔案。 所以,要跟蹤 Excel.xlsx檔案,執行:git add Excel.xlsx
此時再執行 git status 命令,會看到 Excel.xlsx 檔案已被跟蹤,並處於暫存狀態:
在這裡插入圖片描述
只要在 Changes to be committed 這行下面的,就說明是已暫存狀態。 如果此時提交,那麼該檔案在你執行 git add 時的版本將被留存在後續的歷史記錄中。 git add 命令使用檔案或目錄的路徑作為引數;如果引數是目錄的路徑,該命令將遞迴地跟蹤該目錄下的所有檔案。

4、暫存已修改的檔案:git add

現在我們來修改一個已被跟蹤的檔案。 如果你修改了一個名為 README.md 的已被跟蹤的檔案,然後執行 git status 命令,會看到下面內容:
在這裡插入圖片描述
檔案 README.md 出現在 Changes not staged for commit 這行下面,說明已跟蹤檔案的內容發生了變化,但還沒有放到暫存區。 要暫存這次更新,需要執行 git add 命令。 這是個多功能命令:可以用它開始跟蹤新檔案,或者把已跟蹤的檔案放到暫存區,還能用於合併時把有衝突的檔案標記為已解決狀態等。 將這個命令理解為“精確地將內容新增到下一次提交中”而不是“將一個檔案新增到專案中”要更加合適。 現在讓我們執行 git add 將“README.md”放到暫存區,然後再看看 git status 的輸出:
在這裡插入圖片描述
現在兩個檔案都已暫存,下次提交時就會一併記錄到倉庫。 假設此時,你想要在 README.md 裡再加條註釋。 重新編輯存檔後,準備好提交。 不過且慢,再執行 git status 看看:
在這裡插入圖片描述
怎麼回事? 現在 README.md 檔案同時出現在暫存區和非暫存區。 這怎麼可能呢? 好吧,實際上 Git 只不過暫存了你執行 git add 命令時的版本。 如果你現在提交,README.md 的版本是你最後一次執行 git add 命令時的那個版本,而不是你執行 git commit 時,在工作目錄中的當前版本。 所以,執行了 git add 之後又作了修訂的檔案,需要重新執行 git add 把最新版本重新暫存起來:

在這裡插入圖片描述

5、狀態簡覽: git status -s

git status 命令的輸出十分詳細,但其用語有些繁瑣。 Git 有一個選項可以幫你縮短狀態命令的輸出,這樣可以以簡潔的方式檢視更改。 如果你使用 git status -s 命令或 git status --short 命令,你將得到一種格式更為緊湊的輸出。

在這裡插入圖片描述
新建newfile.txt檔案,修改two.txt檔案並儲存後:
在這裡插入圖片描述
修改test.txt 並存檔後:
在這裡插入圖片描述
暫存test.txt後:
在這裡插入圖片描述
再次修改test.txt後:
在這裡插入圖片描述
新新增的未跟蹤檔案前面有 ?? 標記,新新增到暫存區中的檔案前面有 A 標記,修改過的檔案前面有 M 標記。 輸出中有兩欄,左欄指明瞭暫存區的狀態,右欄指明瞭工作區的狀態。例如,上面的狀態報告顯示: two.txt 檔案在工作區已修改但尚未暫存,而 Excel.xlsx 檔案已修改且已暫存。 test.txt 檔案已修,暫存後又作了修改,因此該檔案的修改中既有已暫存的部分,又有未暫存的部分。
在這裡插入圖片描述

6、忽略檔案:.gitignore

一般我們總會有些檔案無需納入 Git 的管理,也不希望它們總出現在未跟蹤檔案列表。 通常都是些自動生成的檔案,比如日誌檔案,或者編譯過程中建立的臨時檔案等。 在這種情況下,我們可以建立一個名為 .gitignore 的檔案,列出要忽略的檔案的模式。 來看一個實際的 .gitignore 例子:

$ cat .gitignore
*.[oa]
*~

第一行告訴 Git 忽略所有以 .o.a 結尾的檔案。一般這類物件檔案和存檔檔案都是編譯過程中出現的。
第二行告訴 Git 忽略所有名字以波浪符(~)結尾的檔案,許多文字編輯軟體(比如 Emacs)都用這樣的檔名儲存副本。 此外,你可能還需要忽略 logtmp 或者 pid 目錄,以及自動生成的文件等等。
要養成一開始就為你的新倉庫設定好 .gitignore 檔案的習慣,以免將來誤提交這類無用的檔案。

檔案 .gitignore 的格式規範如下:

  • 所有空行或者以 # 開頭的行都會被 Git 忽略。
  • 可以使用標準的 glob 模式匹配,它會遞迴地應用在整個工作區中。
  • 匹配模式可以以(/)開頭防止遞迴。
  • 匹配模式可以以(/)結尾指定目錄。
  • 要忽略指定模式以外的檔案或目錄,可以在模式前加上歎號(!)取反。

所謂的 glob 模式是指 shell 所使用的簡化了的正規表示式。 星號(*)匹配零個或多個任意字元;[abc] 匹配任何一個列在方括號中的字元 (這個例子要麼匹配一個 a,要麼匹配一個 b,要麼匹配一個 c); 問號(?)只匹配一個任意字元;如果在方括號中使用短劃線分隔兩個字元, 表示所有在這兩個字元範圍內的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的數字)。 使用兩個星號(**)表示匹配任意中間目錄,比如 a/**/z 可以匹配 a/za/b/za/b/c/z 等。

我們再看一個 .gitignore 檔案的例子:

# 忽略所有的 .a 檔案
*.a 

# 跟蹤所有的 lib.a,即便你在前面忽略了 .a 檔案  
!lib.a 

# 只忽略當前目錄下的 TODO 檔案,而不忽略 subdir/TODO  
/TODO

# 忽略任何目錄下名為 build 的資料夾  
build/
 
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt  
doc/*.txt

# 忽略 doc/ 目錄及其所有子目錄下的 .pdf 檔案
doc/**/*.pdf

GitHub 有一個十分詳細的針對數十種專案及語言的 .gitignore 檔案列表:https://github.com/github/gitignore

7、檢視已暫存和未暫存的修改:git diff

如果 git status 命令的輸出對於你來說過於簡略,而你想知道具體修改了什麼地方,可以用 git diff 命令。 稍後我們會詳細介紹 git diff,你通常可能會用它來回答這兩個問題:當前做的哪些更新尚未暫存? 有哪些更新已暫存並準備好下次提交? 雖然 git status 已經通過在相應欄下列出檔名的方式回答了這個問題,但 git diff 能通過檔案補丁的格式更加具體地顯示哪些行發生了改變。

假如再次修改 README.md 檔案後暫存,然後編輯 test.txt 檔案後先不暫存, 執行 status 命令將會看到:
在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述
要檢視尚未暫存的檔案更新了哪些部分,不加引數直接輸入 git diff,此命令比較的是工作目錄中當前檔案和暫存區域快照之間的差異。 也就是修改之後還沒有暫存起來的變化內容。
在這裡插入圖片描述
若要檢視已暫存的將要新增到下次提交裡的內容,可以用 git diff --staged 命令。 這條命令將比對已暫存檔案與最後一次提交的檔案差異:
在這裡插入圖片描述
請注意,git diff 本身只顯示尚未暫存的改動,而不是自上次提交以來所做的所有改動。 所以有時候你一下子暫存了所有更新過的檔案,執行 git diff 後卻什麼也沒有,就是這個原因。

像之前說的,暫存 README.md 後再編輯,可以使用 git status 檢視已被暫存的修改或未被暫存的修改。

修改README.md
在這裡插入圖片描述
暫存README.md

在這裡插入圖片描述
暫存README.md後再修改:
在這裡插入圖片描述
此時我們的環境(終端輸出)看起來如下:
在這裡插入圖片描述
現在執行 git diff 看暫存前後的變化:(綠色為尚未暫存的)
在這裡插入圖片描述
然後用 git diff --cached 檢視已經暫存起來的變化( --staged--cached 是同義詞):(綠色是已經暫存的)
在這裡插入圖片描述

Git Diff 的外掛版本: 使用 git diff 來分析檔案差異,也可以使用圖形化的工具或外部 diff 工具來比較差異。 可以使用git difftool 命令來呼叫 emergevimdiff 等軟體(包括商業軟體)輸出 diff 的分析結果。 使用 git difftool --tool-help 命令來看你的系統支援哪些 Git Diff 外掛。

8、提交更新:git commit

現在的暫存區已經準備就緒,可以提交了。 在此之前,請務必確認還有什麼已修改或新建的檔案還沒有 git add 過, 否則提交的時候不會記錄這些尚未暫存的變化。 這些已修改但未暫存的檔案只會保留在本地磁碟。 所以,每次準備提交前,先用 git status 看下,你所需要的檔案是不是都已暫存起來了, 然後再執行提交命令 git commit

$ git commit

在這裡插入圖片描述

這樣會啟動你選擇的文字編輯器來輸入提交說明:
在這裡插入圖片描述
可以看到,預設的提交訊息包含最後一次執行 git status 的輸出,放在註釋行裡,另外開頭還有一個空行,供你輸入提交說明。 你完全可以去掉這些註釋行,不過留著也沒關係,多少能幫你回想起這次更新的內容有哪些。

Git(4)-- 如何退出 git log 和 git commit 狀態

退出編輯器時,Git 會丟棄註釋行,用你輸入的提交說明生成一次提交。

另外,你也可以在 commit 命令後新增 -m 選項,將提交資訊與命令放在同一行,如下所示:git commit -m "FIRST time commit"

在這裡插入圖片描述
好,現在你已經建立了第一個提交! 可以看到,提交後它會告訴你,當前是在哪個分支(main)提交的,本次提交的完整 SHA-1 校驗和是什麼(7fa71a1),以及在本次提交中,有多少檔案修訂過,多少行新增和刪改過。

請記住,提交時記錄的是放在暫存區域的快照。 任何還未暫存檔案的仍然保持已修改狀態,可以在下次提交時納入版本管理。 每一次執行提交操作,都是對你專案作一次快照,以後可以回到這個狀態,或者進行比較。

9、跳過使用暫存區域:git commit -a

儘管使用暫存區域的方式可以精心準備要提交的細節,但有時候這麼做略顯繁瑣。 Git 提供了一個跳過使用暫存區域的方式, 只要在提交的時候,給 git commit 加上 -a 選項,Git 就會自動把所有已經跟蹤過的檔案暫存起來一併提交,從而跳過 git add 步驟:
git commit -a -m "skip add commit"
在這裡插入圖片描述
看到了嗎?提交之前不再需要 git add 檔案“testdiff.txt”了。 這是因為 -a 選項使本次提交包含了所有修改過的檔案。 這很方便,但是要小心,有時這個選項會將不需要的檔案新增到提交中。

10、移除檔案:git rm

要從 Git 中移除某個檔案,就必須要從已跟蹤檔案清單中移除(確切地說,是從暫存區域移除),然後提交。 可以用 git rm 命令完成此項工作,並連帶從工作目錄中刪除指定的檔案,這樣以後就不會出現在未跟蹤檔案清單中了。

如果只是簡單地從工作目錄中手工刪除檔案,執行 git status 時就會在 “Changes not staged for commit” 部分(也就是 未暫存清單)看到:

在這裡插入圖片描述

在這裡插入圖片描述
然後再執行 git rm 記錄此次移除檔案的操作:
在這裡插入圖片描述
下一次提交時,該檔案就不再納入版本管理了。 如果要刪除之前修改過或已
經放到暫存區的檔案,則必須使用強制刪除選項 -f(即 force 的首字母)。 這是一種安全特性,用於防止誤刪尚未新增到快照的資料,這樣的資料不能被 Git 恢復。

在這裡插入圖片描述
另外一種情況是,我們想把檔案從 Git 倉庫中刪除(亦即從暫存區域移除),但仍然希望保留在當前工作目錄中。 換句話說,你想讓檔案保留在磁碟,但是並不想讓 Git 繼續跟蹤。 當你忘記新增 .gitignore 檔案,不小心把一個很大的日誌檔案或一堆 .a 這樣的編譯生成檔案新增到暫存區時,這一做法尤其有用。 為達到這一目的,使用 --cached 選項:

在這裡插入圖片描述

git rm --cached testdiff.txt

在這裡插入圖片描述
git rm 命令後面可以列出檔案或者目錄的名字,也可以使用 glob 模式。比如:

$ git rm log/\*.log

注意到星號 * 之前的反斜槓 \, 因為 Git 有它自己的檔案模式擴充套件匹配方式,所以我們不用 shell 來幫忙展開。 此命令刪除 log/ 目錄下副檔名為 .log 的所有檔案。 類似的比如:

$ git rm \*~

該命令會刪除所有名字以 ~ 結尾的檔案。

11、移動(重新命名)檔案:git mv file_from file_to

git mv 命令用於移動或重新命名一個檔案、目錄或軟連線。

不像其它的 VCS 系統,Git 並不顯式跟蹤檔案移動操作。 如果在 Git 中重新命名了某個檔案,倉庫中儲存的後設資料並不會體現出這是一次改名操作。 不過 Git 非常聰明,它會推斷出究竟發生了什麼。
要在 Git 中對檔案改名,可以這麼做:git mv file_from file_to

它會恰如預期般正常工作。 實際上,即便此時檢視狀態資訊,也會明白無誤地看到關於重新命名操作的說明: git mv test.txt testnew.txt
在這裡插入圖片描述
其實,執行 git mv 就相當於執行了下面三條命令:

$  mv test.txt testnew.txt
$ git rm test.txt
$ git add testnew.txt

如此分開操作,Git 也會意識到這是一次重新命名,所以不管何種方式結果都一樣。 兩者唯一的區別是,mv 是一條命令而非三條命令,直接用 git mv 方便得多。 不過有時候用其他工具批處理重新命名的話,要記得在提交前刪除舊的檔名,再新增新的檔名。

在這裡插入圖片描述

相關文章