# 前言

上一篇文章,我們已經學會使用 git status 來查看檔案狀態,不過 git status 呈現的檔案狀態,好像不是只有 暫存 (stage)未暫存 (unstage) 這麼簡單。

這篇文章我們來更細部的探討 Git 中,資料會出現的狀態。

預告一下:
文章預計會說明四個名詞定義,最後還會證明其中兩個名詞 未追蹤 等於 未暫存,整篇內容可能會讓新手看完覺得頭很暈!

如果你畏懼字詞解釋的話,可以直接滑到文章最底端,看結論。

# 已追蹤 (Tracked) 、未追蹤 (Untracked),已暫存 (Staged)、未暫存 (Unstaged)

執行 git status 指令時,會發現 Git 將 新增加的檔案 描述成 未追蹤的檔案 (Untracked files)。

可是不對阿…
加入暫存區的檔案叫做 已暫存,那我還沒把檔案加入暫存區,為什麼叫做 未追蹤,不直接叫 未暫存

在實際開始解釋之前,說明一個可能比較抽象的觀念:
我們說 git add 是把檔案放到暫存區的行為,而這個 暫存區 是真的有這東西,他座落於 .git 資料夾裡面,是一個名叫 index (索引) 的檔案。
Alt text

而「索引」到底是不是真的像購物車一樣,下單後會「清空資料」? 其實 「不是」

在 Git 中,能在加入索引之後,又移出索引的資料,只有 還沒 commit 過的資料 才能做到。
沒commit 的檔案可以移出索引示意圖

否則,只要 commit 過的檔案,資料永遠會紀錄在 索引 裡面。

檔案進了 Git 就跟得罪方丈一樣,想走沒那麼容易!- 高見龍 (龍哥)《為你自己學 Git》

如果你還沒因為 暫存區 又叫 索引 這件事混淆的話,那我們繼續看下去:

# 未追蹤 (Untracked) 、追蹤 (Tracked) 的定義

  1. 未追蹤的檔案 (Untracked files):所有 不在索引 的檔案。
  2. 已追蹤的檔案 (Tracked files):所有 存在於索引 的檔案。

同時,已追蹤 的檔案,可以再區分成 未暫存暫存

# 未暫存 (Unstaged)、暫存 (Staged) 的定義

  1. 未暫存的檔案 (Unstaged files):索引的內容工作目錄的內容 不一致 的檔案
  2. 已暫存的檔案 (Staged files):索引的內容作目錄的內容 一致 的檔案

了解定義之後,我們可以回頭來看工作目錄中,可能會有的檔案狀態:

# 工作目錄可能會出現的檔案狀態整理

在工作目錄中操作檔案,以及執行會更動索引資料的指令 (註 1) 時,都會使檔案狀態發生變化。

下文整理 (註 2) 一下我們在開發與版控時,工作目錄的檔案可能會出現的狀態,這裡更動索引資料的指令,以最常使用的 git add 為例:

  1. 執行 git add 之前:
  • 新增檔案 (尚未列入追蹤的檔案) :未追蹤
  1. 執行 git add 之後:
  • 新增檔案 (已經加入索引的檔案) :已追蹤 / 暫存
  • 修改檔案 (已經加入索引的檔案) :已追蹤 / 暫存
  • 刪除檔案 (已經加入索引的檔案) :已追蹤 / 暫存
  1. 執行 git commit 之後又進行異動:
  • 修改檔案 (尚未加入索引的檔案) :已追蹤 / 未暫存
  • 刪除檔案 (尚未加入索引的檔案) :已追蹤 / 未暫存

用上面列的這三種區域來看的話,當檔案被 commit 過後,編輯這些檔案再 commit 一版的行為,就是不停的讓檔案在 第三區第二區 的狀態不斷循環。

註 1. 在 Git 中,並不只有 git addgit commit 兩個指令會影響到檔案狀態,舉凡一切會去異動索引資料的指令,都會影響檔案在 Git 中的狀態,例如 resetrebase 等。

註 2. 原始資料整理自保哥的文章

# 常見問題

# 「未追蹤」的檔案算不算「未暫存」的檔案?

廣義來說,算。

記得 Fork GUI 介面中,工作目錄剛新增的那些 未追蹤檔案 出現的位置在哪嗎?

沒錯,竟然是未暫存區 (Unstaged)!

如果你已經忘記了,我附個圖:
暫存,未暫存示意圖
(p.s. 朋友希望 Fork 的畫面能跟背景色有對比,預計之後都會以深色系來截圖)

再列一次兩個名詞的定義:

  • 「未追蹤」檔案:尚未紀錄到索引 的檔案。
  • 「未暫存」檔案:索引工作目錄 資料「 不一致 」 的檔案。

有了定義,我們就可以來證明這兩者是不是相同的意思。

試證明: 「未追蹤」 檔案等於 「未暫存」 檔案:

  1. 因為 「未追蹤」 檔案是 「尚未紀錄到索引」 的檔案,所以 「索引」 不會有 「未追蹤」 的資料。
  2. 雖然 「索引」 沒有 「未追蹤」 檔案,但如果出現 「未追蹤」 的檔案,表示工作目錄有檔案。
  3. 由第二點推論出 「未追蹤」 的檔案在 「索引與工作目錄」 兩個位置的資料 「不一致」
  4. 由於 「索引與工作目錄」 記錄的資料 「不一致」 的檔案,稱為 「未暫存」 的檔案。

得證: 「未追蹤」 檔案等於 「未暫存」 檔案。

# 總結

我們在使用 Git 版控,都是持續更改檔案狀態的行為,了解 Git 對檔案狀態的分類,可以在未來面對不同情境時,知道下一步該如何操作,不會手忙腳亂。

如果因為這篇文章的各種狀態,以及看完證明題後搞得頭暈腦脹, 然後不想再跟我這種數學系的人說話 ,在初學 Git 的階段,先記得一件事情就好:

要執行 commit 之前,通通先 add 過吧!