git檔案管理與索引,深入理解工作原理

語言: CN / TW / HK

前言

這一夜,註定是個不眠之夜,小白和cangls的對話已然進入了白熱化。小白孜孜不倦的諮詢關於git方面的知識,對索引越來越感興趣。小白以前存的小電影檔案可以進行版本的對比,探索哪個版本畫質更好。

小白:cangls,我最近有點疑惑。

cangls:具體是哪些方面呢?

小白:最近有些需求,我需要對檔案進行版本管理控制,但是有些問題百思不得其解。

cangls:版本管理啊,這個我可熟悉呢,最近也在總結系列文章。看了之後,相信會對你有所幫助。

Linus Torvalds在Git郵件列表裡曾說如果不先了解索引的目的,你就不能完全領會Git的強大之處。

本文為個人Git系列文章第二彈,git進階內容之不得不瞭解的檔案管理與索引。Git的索引不包含任何檔案內容,它僅僅追蹤你想要提交的那些內容。當執行git commit命令的時候,Git會通過檢查索引而不是工作目錄來找到提交的內容。雖然git在底層為了我們處理了很多事情,但記住索引和它的狀態也很重要。在任何時候都可以通過git status命令來查詢索引的狀態。

正文

VCS的經典問題之一就是檔案重新命名會導致它們丟失對檔案歷史記錄的追蹤。而Git即使經過重新命名,也仍然能保留歷史資訊。在實際的工作使用中,貌似Git系統處理檔案重新命名的方式更優越一點點。因為啊,git有多種方式處理重新命名一個檔案(比如:使用git rm配合git add、git mv),而以往的程度還不足以確保SVN知道所有的情況。但是,還沒有能完美處理重新命名的檔案系統。

一、git檔案分類

1、git檔案分類

git將所有檔案分為3類:已追蹤的、被忽略的和未追蹤的,如下圖所示。

graph TD git中的檔案分類 --> 已追蹤的Tracked git中的檔案分類 --> 被忽略的Ignored git中的檔案分類 --> 未追蹤的Untracked

1.1、已追蹤的(Tracked)

已追蹤的檔案是指 已經在版本庫中的檔案 ,或者是 已經暫存到索引中的檔案 。如果想將新檔案newfile新增到為已追蹤(Tracked)的檔案,執行 git add newfile 命令即可。例如暫存index.html檔案。

git add index.html

1.2、被忽略的(Ignored)

被忽略的檔案必須 在版本庫中被明確申明為不可見或被忽略 ,即使它可能會在你的工作目錄中出現。一個軟體專案通常會有很多倍忽略的檔案(使用過SVN開發Java的小夥伴就很熟悉了,通過提交時我們可以選擇忽略哪些固定的檔案不提交)。普通被忽略的檔案包含臨時檔案、個人筆記、編譯器輸出檔案以及構建專案過程中自動生成的大多數檔案等等。 Git維護一個預設忽略檔案列表 ,也可以配置版本庫來識別其它檔案。

1.3、未追蹤的(Untracked)

未追蹤的檔案是指那些不在前兩類中的檔案。Git把工作目錄下的所有檔案當成一個集合,減去已追蹤的檔案和被忽略的檔案,剩餘部分最為未被追蹤的檔案(Untracked)。

這裡測試,初始化了一個名為test目錄的倉庫,原本包含了一個demo-1-0.0.1-SNAPSHOT.jar檔案。但是我沒有將其暫存或者是新增到版本庫中,就是如下你看到的顯示未追蹤的檔案(Untracked files)。

$ git status
HEAD detached at bd156ab
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        demo-1-0.0.1-SNAPSHOT.jar

nothing added to commit but untracked files present (use "git add" to track)

為了演示說明, 重新初始化了一個sky工作目錄 。通過建立一個全新的工作目錄和版本庫並處理一些檔案來測試驗證這些不同類別的檔案。

#初始倉庫sky
$ git init
Initialized empty Git repository in D:/work/sky/.git/

#檢視狀態
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)

#輸入資料到sky倉庫的sky檔案中
echo "new data" >> sky
#再次檢視狀態,顯示一個未被追蹤的檔案sky
$ git status
On branch master
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        sky
nothing added to commit but untracked files present (use "git add" to track)

起初,目錄裡沒有檔案,已經追蹤的檔案和被忽略的檔案都是空的,因此未追蹤的檔案也是空的。一旦建立了一個sky檔案, git status 就會報告一個未追蹤的檔案。

編輯器和構建環境常常會在原始碼檔案周圍遺留一些臨時檔案。在版本庫中這些檔案通常是不應該被當做原始檔追蹤的。為了讓Git忽略目錄中的檔案,只需要將該檔名新增到一個特殊的檔案 .gitignore 中即可。手動建立一個測試的垃圾檔案test.o,然後放入.gitignore檔案中進行維護。如下是演示過程中的示例:

#手動建立一個測試的垃圾檔案
$ touch test.o
#檢視狀態,此時未新增到忽略檔案中進行維護
$ git status
On branch master
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        sky
        test.o
nothing added to commit but untracked files present (use "git add" to track)

#新增到忽略檔案.gitignore,然後檢視狀態與之前進行對比
$ echo test.o > .gitignore
$ git status
On branch master
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        sky
nothing added to commit but untracked files present (use "git add" to track)

通過上面的一系列操作,這樣test.o已經被忽略掉了,但是git status現在顯示出一個新的未追蹤的檔案 .gitignore 。雖然.gitignore檔案對Git有特殊的意義,但是它和版本庫中任何其它普檔案都是同樣管理的。除非將.gitignore檔案新增到索引中,否則Git仍然會將她當成未追蹤的檔案。下面將展示不同的方式來改變檔案的追蹤狀態,以及如何新增或者從索引中刪除她。

二、git add命令

回顧git add使用

#新增一個工作目錄test
$ mkdir test
#初始化化一個倉庫
git init
#暫存test.md檔案
git add test.md

注意:在暫存的過程中,你會發現 git diff 這個命令非常的有用。 這條命令可以顯示出兩組不同的差異 ,git diff顯示仍然留在工作目錄中且未暫存的變更; git diff --cached 顯示已經暫存且因此需要有助於下次提交的變更

1、git add用法,探尋原理

git add 命令的意義是將暫存一個檔案。以Git檔案分類而言,如果一個檔案是未追蹤的,那麼 git add 會將檔案的狀態轉化為 已追蹤狀態 。如果git add 作用一個目錄 ,那麼該目錄下的 所有檔案都會被遞迴為已追蹤狀態暫存起來 。接著之前的例子,繼續進行講解。

$ git status
On branch master
No commits yet
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        sky
nothing added to commit but untracked files present (use "git add" to track)
#將sky和.gitignore檔案暫存,檢視狀態對比
$ git add sky .gitignore
$ git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   .gitignore
        new file:   sky

第一條git status目錄顯示有兩個未追蹤的檔案, 並友好的提醒你要追蹤一個檔案 ,只需要使用 git add <file>... 命令即可。使用git add命令之後,暫存和追蹤sky以及.gitignore檔案,並準備在下次提交的時候新增到版本褲中。

在Git的物件模型方面,發出 git add 命令時對每個檔案的全部內容都將被複制到物件庫中,並且按檔案的SHA1名來索引。 暫存一個檔案也稱作為快取 (cacheing)一個檔案,或者是稱為 將檔案放入索引 ,其實上面已經看到了提示 --cached 。可以使用 git ls-files 命令檢視隱藏在物件模型下的檔案,並且可以找到那些暫存檔案的SHA1值。

$ git ls-files --stage
100644 85c292ca0717bb097b55af3b961c493190d1a4aa 0       .gitignore
100644 116c7ee1423b9a469b3b0e122952cdedc3ed28fc 0       sky

在版本庫中大多數的日常變化可能只是簡單的編輯。但在任何編輯後,提交變更之前,請執行 git add 命令,用最新的版本檔案去更新索引。如果不這麼去做,你將會得到兩個不同版本的檔案: 一個在物件庫中是被索引引用 的, 另一個則在你的工作目錄下 。繼續之前的示例,改變sky檔案,使之有別與索引中的那個檔案,然後使用來自神祕的東方的韓天尊的無敵逃跑技能。開個玩笑,其實是命令git hash-object file(你幾乎不會直接呼叫她)來直接和輸出的這個新版本的SHA1雜湊值。

$ git ls-files --stage
100644 85c292ca0717bb097b55af3b961c493190d1a4aa 0       .gitignore
100644 116c7ee1423b9a469b3b0e122952cdedc3ed28fc 0       sky
#通過vim修改,新增了add new some data now
$ cat sky
new data
add new some data now
#使用命令計算SHA1雜湊值
$ git hash-object sky
e24bcd708d232113f9012a5ece0a64eb97f3921e

在略做修改之後,你會發現儲存在物件庫和索引中的那個檔案的 上一個版本的SHA1值是 116c7ee1423b9a469b3b0e122952cdedc3ed28fc 。然而在更新sky檔案後, 版本的SHA1值則變成了 e24bcd708d232113f9012a5ece0a64eb97f3921e 。接下來更新索引,使之包含檔案的最新版本。

$ git add sky
$ git ls-files --stage
100644 85c292ca0717bb097b55af3b961c493190d1a4aa 0       .gitignore
100644 e24bcd708d232113f9012a5ece0a64eb97f3921e 0       sky

現在索引有了更新後的檔案版本。簡單來概括: 檔案已經暫存 了,或者是 sky檔案在索引中 。在檔案索引中這種說法並不是很確切,因為實際上檔案存在物件庫中, 索引只是指向她而已 。看似無用的處理SHA1雜湊值和索引,卻帶來一個關鍵點:與其將 git add 看成是 新增這個檔案 ,不如看作是 新增這個內容

在任何情況下,最重要的是 要記住工作目錄下的檔案版本和索引中暫存的檔案版本可能是不同步的 。當提交的時候, git會使用索引中的檔案版本

三、git rm命令

回顧簡單用法,例如刪除test.md檔案(前提是已暫存了)

#刪除test.md檔案
git rm test.md

1、git rm命令的用法

git rm 命令自然是與 git add 相反的命令。她會在版本庫和工作目錄中同時刪除檔案。然而,由於刪除檔案比新增檔案問題更多(假如出現錯誤),git對移除檔案更多一些關注。

Git可以從索引或者同時從索引和工作目錄中刪除一個檔案。Git不會只從工作目錄中刪除一個檔案,普通的rm命令可用於這一目的。

從工作目錄和索引中同時刪除一個檔案, 並不會刪除該檔案在版本庫中的歷史記錄 。檔案的任何版本,只要是提交到版本庫中的歷史記錄中的一部分,就會留在物件庫裡並儲存歷史記錄。繼續上述的例子,引入一個不應該暫存的 意外檔案 ,看如何將其刪除。

#新增了一個意外檔案rdms
$ echo "random file data" > rdms
#提示:無法對Git認為是other的檔案執行git rm
#應該只是用rm rdms
$ git rm rdms
fatal: pathspec 'rdms' did not match any files

因為git rm也是一條 對索引進行操作的命令 ,所以對沒有新增到版本庫中或索引中的檔案是不起作用的。Git必須先認識到檔案才行,所以下面 偶然的暫存rdms檔案

#意外暫存rdms檔案
$ git add rdms
$ git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   .gitignore
        new file:   rdms
        new file:   sky

如果要將一個檔案由已暫存的轉化為未暫存的,可以使用 git rm --cached 命令。

#檢視SHA1雜湊值
$ git ls-files --stage
100644 85c292ca0717bb097b55af3b961c493190d1a4aa 0       .gitignore
100644 087d758bdee282174e3ba5905a5e463d3d7a88dc 0       rdms
100644 e24bcd708d232113f9012a5ece0a64eb97f3921e 0       sky
#刪除
$ git rm --cached rdms
rm 'rdms'
#此時對比刪除前的內容,發現rdms檔案已經不存在了
$ git ls-files --stage
100644 85c292ca0717bb097b55af3b961c493190d1a4aa 0       .gitignore
100644 e24bcd708d232113f9012a5ece0a64eb97f3921e 0       sky
#可以看出,加上--cached引數並不會刪除工作目錄中的檔案
$ ls
rdms  sky  test.o

git rm --cached 會刪除索引中的檔案並將其保留在工作目錄中,而 git rm 則會將檔案從索引和工作目錄中同時刪除。所以, 我額外的加了注意事項在文末 ,並予以說明。

如果想要移除一個已經提交的檔案,通過簡單的git rm filename命令來暫存這一請求。

#對暫存的檔案進行提交
$ git commit -m "add some files"
[master (root-commit) 82e23d4] add some files
 2 files changed, 3 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 sky
#將之前暫存的檔案sky移除暫存
$ git rm sky
rm 'sky'
#檢視狀態
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    sky

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        rdms

Git在刪除一個檔案之前,她會先進行檢查以確保工作目錄下該檔案的版本與當前分支中的最新版本(Git命令呼叫HEAD的版本)是匹配的。這個驗證會防止檔案的修改(由於你的編輯)意外丟失。

tips:還可以使用 git rm -f 來強制刪除檔案。強制就是明確授權,給你許可權放心大膽的刪除。即使從上次提交以來你已經修改了該檔案,還是會刪除她。

萬一真的想不留那個不小心刪除的檔案,只要在把她添加回來即可。

$ git add sky
$ git checkout HEAD--sky
#或者提交後採取如下命令找到對應的雜湊值,進行恢復,rev-list命令很實用,請拿起小本本記住她
$ git rev-list master
82e23d40959116ae55ca82ced231e0069d8fc229
$ git checkout 82e23d40959116ae55ca82ced231e0069d8fc229
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
  40eac09 delete some files
If you want to keep it by creating a new branch, this may be a good time
to do so with:
 git branch <new-branch-name> 40eac09
HEAD is now at 82e23d4 add some files

注意: rev-list 命令很實用, 請拿起小本本記住她

此處只是順帶的提一下。當我們刪除了一個檔案,此時想回退到歷史版本,可以使用git checkout 接上master分支的ID(SHA1)。如何找到ID值呢?這裡僅僅是簡單的介紹了一下 git rev-list 的用法,相信你會愛上她的。當然還可以加上引數--before,接指定的日期去查詢分支。

#查詢我的歷史版本檢視到雜湊值
$ git rev-list master
988df9ddbeb6b30d0bf5138f36219a8593df75e0
bd156ab27fc96e78e5515c39c05d4ecd6c36b9f0

#檢出歷史版本,根雜湊值恢復到上一個版本
$ git checkout bd156ab27fc96e78e5515c39c05d4ecd6c36b9f0

版本系統擅長恢復檔案的舊的版本。關於 git rm 命令就演示這麼多。

四、git mv命令

1、簡單描述使用

例如,使用git mv命令將test.md檔案重新命名為Readme.md,如下命令所示。

#重新命名一個檔案
git mv test.md Readme.md

git mv命令的另一作用是移動檔案位置,熟悉Linux命令的小夥伴肯定不會陌生。將test.md檔案由github目錄移動到gitee目錄。

#移動一個檔案的位置
git mv /github/test.md /gitee/

2、git mv詳細用法介紹

假設你需要移動或者重新命名檔案。可以對舊的檔案使用 git rm 命令,然後使用 git add 命令新增新檔案,或者直接使用 git mv 命令。給定一個版本庫,其中有一個test檔案,你想要將重新命名為newtest。下面一系列的命令就是等價的Git操作。

$ mv test newtest
$ git rm test
$ git add newtest
#上面三步操作等價於下面操作
$ git mv test newtest

無論哪種情況, Git都會在索引中刪除test的路徑名並新增newtest的路徑名 。至於test的原始內容,則仍然保留在物件庫中,然後才會將它與newtest重新關聯。看起來有點繞,其實仔細琢磨一下就好了。

在示例版本庫中找回test這個檔案,如下重新命名,然後提交變更。

$ git mv test newtest
$ git add newtest
$ git commit newtest -m "moved test to newtest"
[detached HEAD adc778e] moved test to newtest
 1 file changed, 1 insertion(+)
 create mode 100644 newtest

如果你碰巧檢查這個檔案的歷史記錄,你可能會不安的看到Git很明顯丟失了原始的test檔案的歷史記錄,只記得她從test從重新命名為當前檔名。

$ git log newtest
commit adc778e58db37977b39a541da4498607f12bc80b (HEAD)
Author: dywangk <[email protected]>
Date:   Mon Jan 17 20:35:56 2022 +0800
    moved test to newtest

其實,Git是記得全部歷史記錄的,但是顯示要限制與在命令中指定的檔名。 --follow 選項會讓Git在日誌中回溯並找到內容相關聯的整個歷史記錄。這裡就不貼程式碼記錄了,篇幅拉的太長了,可以自行修改測試。

$ git log --follow sky

VCS的經典問題之一就是檔案重新命名會導致它們丟失對檔案歷史記錄的追蹤。而Git即使經過重新命名,也仍然能保留歷史資訊。

五、追蹤重新命名註解

小白:cangls啊,我以前使用過svn,沒有用過Git,她們之間對重新命名有啥區別嗎?

cangls:當然有了,下面就給你科普一下。內容很長,雖然很乏味,但請耐心看完。

1、追蹤重新命名註解介紹

下面作為傳統版本控制系統的典型,SVN對檔案重新命名和移動做了很多追蹤工作。為什麼呢?這是由於它只追蹤檔案之間的差異才導致的。例如,如果移動一個檔案這本質上就相當於從舊檔案中刪除所有行,然後將它新增到新檔案中。但是任何時候,你哪怕就做一個簡單的重新命名,也需要再次傳輸和儲存檔案的全部內容,這將變得非常低效;想象一下重新命名一個擁有數以千計的檔案的子目錄,那該是多麼恐怖的一件事情。

為了緩解這種情況,SVN顯示追蹤每一次重新命名。如果你想將 test.txt 重新命名為 subdir/test.txt你必須對檔案使用svn mv ,而不能使用 svn rmsvn add 。否則,SVN將不能識別出這是一個重新命名,只能像剛才描述的那樣進行低效的刪除、新增步驟。

接著,要有追蹤重新命名這個特殊功能,SVN伺服器需要一個特殊協議來告訴她的客戶端, 請將test.txt移動到subdir/test.txt 。此外,每一個SVN客戶端必須確保該操作(相對罕見)執行的正確性。

另一方面, Git則不追蹤重新命名 。可以將text.txt移動到或者複製到任何地方,這麼做只會影響樹物件而已( 請記住樹物件儲存內容間的關係,而內容本身儲存在blob中 )。檢視兩顆樹間的差異,我們很容易發現叫 a30af53...的blob已經移到另一個新地方。即使你沒有明確檢查差異,系統中的每個部分都知道她已經有了那麼一個blob,不再需要她的另一個副本了。

在這種情況下,像在很多其它地方一樣,Git基於雜湊的簡單儲存系統簡化了許多其它RCS被難倒的或者選擇迴避的事情。

六、.gitignore檔案

在本文介紹暫存檔案的時候,就已經簡單的使用過gitignore檔案來忽略不相干的test.o檔案。在那個例子中,可以忽略任何檔案,只要將想要忽略的檔名加到同一目錄下的.gitignore檔案即可。此外可以通過將檔名新增到該版本庫頂層目錄下的.gitignore檔案中忽略她。

但是git還支援一種更為豐富的機制。 一個.gitignore檔案下可以包含一個檔名模式列表,指定哪些檔案要忽略 。.gitignore檔案格式如下:

  • 空行會被忽略,而已井號(#)開頭的行可以用於註釋。然而,如果#跟在其它文字後面,它就不表示註釋了。
  • 一個簡單的字面配置檔名匹配任何目錄中的同名檔案。
  • 目錄名由末尾的反斜線(/)標記。這能匹配同名的目錄和子目錄,但不匹配檔案或符號連結。
  • 包含shell萬用字元,如星號(*),這種模式可以擴充套件為shell通配模式。
  • 起始的感嘆號(!)會對該行其餘部分模式進行取反。此外,被之前模式排除但被取反規則匹配的檔案是要包含的。取反模式會覆蓋低優先順序的規則。

Git允許在版本庫中任何目錄下有.gitignore檔案。每個檔案都隻影響該目錄和其所有子目錄。.gitignore的規則也是級聯的:可以覆蓋高層目錄中的規則,只要在其子目錄包含一個取反模式(使用起始的“!”)。

為了解決帶多個.gitignore目錄的層次結構問題,也為了允許命令列對忽略檔案列表的增編,Git按照下列由高到底的有限順序:

  • 在命令列指定的模式;
  • 從相同目錄的.gitignore檔案中讀取的模式;
  • 上層目錄中的模式,向上進行。因此,當前目錄的模式能推翻上層目錄的模式,而最接近當前目錄的上層目錄的模式優於更上層的目錄模式;
  • 來自.git/info/exclude檔案的模式;
  • 來自配置變數core.excludefile指定的檔案中的模式。

因為在版本庫中.gitignore被視為普通檔案,所以在複製操作過程中它會被複制,並適用於你的版本庫的所有副本。 一般情況下,只有當模式普遍適用於派生的版本庫時,才應該將條目放入版本控制下的.gitignore檔案中

當然還有一種特殊情形,有一類檔案我需要忽略,但其中部分我需要追蹤,此時可以使用取反(!)。

七、Git中物件模型和檔案

到現在為止,你應該具備管理檔案的基本能力。儘管如此,在哪裡跟蹤啥檔案:在工作目錄、索引還是版本庫中,還是讓人困惑。通過圖形進行區分她們之間的區別。初始狀態,在工作目錄中包含file1和file2兩個檔案,分別為“foo”和“bar”。

4張圖繪製有點粗糙,後續會優化的。

1、示例圖1

除了工作目錄下的file1和file2之外,master分支還有一個提交,它記錄了與file1和file2內容完全一樣的“foo”和“bar”的樹。另外,該索引記錄兩個HSA1值 257cc5和5716ca,與那個兩個檔案分別對應。工作目錄、索引及物件庫都是同步一致的,沒什麼是髒的。

2、示例圖2

圖2顯示了在工作記錄中對file1編輯後的變化,現在它的內容包含“git”。索引和物件庫中沒有變化,但是工作目錄現在是髒的。

當使用 git add file1 來暫存file1的編輯時,一些有趣的變化發生了。如圖3所示。

3、示例圖3

git首先選取出工作目錄中file1的版本,為它的內容計算一個SHA1雜湊ID(04848c),然後把那個ID儲存在物件庫中。接下來,Git就會記錄在索引中的file1路徑名已更新為新的(04848c)SHA1值。

4、示例圖4

由於file2檔案內容未發生改變而且沒有任何 git add 來暫存file2,因此索引繼續指向原始的blob物件。此時你已經在索引暫存了file1檔案,而且工作目錄和索引是一致的。不過,就HEAD而言,索引是髒的,因為索引中的樹和在master分支的HEAD提交的樹在物件庫裡是不一樣的。最後,當所有變更暫存到版本庫中, git commit 的作用如圖4。圖4過程看著最為複雜,需要自己畫圖捋一捋。

如圖4所示,提交啟動了三個步驟。首先,虛擬樹物件(即索引)在轉換成一個真實的樹物件後,會以SHA1命名,然後存放到物件庫中。其次,用你的日誌訊息建立一個新的提交物件。新的提交將會指向新建立的樹物件以及前一個或父提交。最後,master分支的引用從最近一次提交移動到新建立的提交物件,成為新的master HEAD。

最終,一個有趣的細節是,工作目錄、索引和物件庫(由master分支的HEAD表示)再次同步,此時就變為一致了,就如同在圖1所示。

八、注意事項(重點)

1、git commit --all注意事項

1.1、回顧提交命令

此處分為未指定引數、指定-a引數、指定單個檔案三種情況。

#未指定引數
git commit -m "註釋"
#指定單個要提交的檔案
git commit /github/test.md -m "初次提交test.md檔案"
#或者提交全部(注意事項:導致暫存和未暫存以及未追蹤的檔案發生變化)
git commit -a -m "提交全部"

這裡補充一個git常用的命令git diff,檢視提交差異。使用之前提交的兩個全ID名並執行git diff,通過git log命令檢視ID值。

$ git diff 988df9ddbeb6b30d0bf5138f36219a8593df75e0 bd156ab27fc96e78e5515c39c05d4ecd6c36b9f0

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2b64487
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+初始化

1.2、注意事項

以前只是用來寫作,也沒多想,最多就寫個註釋就直接提交(commit )和推送(push)到遠端倉庫了。原本我思考過這樣一個問題,當我提交的時候不加引數也不指定提交的檔案,會有什麼影響。起初也是好奇,才翻閱了一些書籍發現有很多門道的。

後來,注意到了關於 git commit --all 注意事項。 commit -a 或者 -all 引數 會導致執行之前自動暫存所有未暫存的和未追蹤的檔案變化,包括從工作副本中刪除已追蹤的檔案

注意:如果不通過命令列直接提供日誌訊息,Git會啟動編輯器,並提示你寫一個。

2、git rm --cached注意事項

2.1、回顧刪除命令

#索引和工作目錄中都刪除
git rm test.md
#遞迴刪除test目錄
git rm -r test
#將檔案標記為未追蹤的,卻在工作目錄中仍然保留著一份副本(慎重使用)
git rm --cached test.md

2.2、注意事項

git add是加一個檔案暫存起來,與之相反的就是git rm是將一個檔案由暫存狀態移除暫存,並且 rm會將檔案從索引和工作目錄中都刪除 。使用 git rm --cached 命令 會將檔案標記為未追蹤的,卻在工作目錄中仍然保留著一份副本 ,這是很危險的。因為你也許會忘記之前自己做過了哪些操作,換句話來說是會忘記這個檔案是不再被追蹤的。 Git需要檢查工作檔案中的內容是最新的,使用這種方法則無視了這個檢查 ,從而增加了隱患。所用要 慎重使用git rm --cached命令

總結

以上就是此次文章的所有內容的,希望能對你的工作有所幫助。感覺寫的好,就拿出你的一鍵三連。如果感覺總結的不到位,也希望能留下您寶貴的意見,我會在文章中進行調整優化。

原創不易,轉載也請標明出處。不要改頭換面,請尊重原創。本文會不定期上傳到gitee或者github以及釋出到微信公眾平臺。 我的微信公眾號與其他平臺暱稱都一樣是龍騰萬里sky

by 龍騰萬里sky