iT邦幫忙

2025 iThome 鐵人賽

DAY 19
0
Software Development

深入一點點認識 Git系列 第 19

Day 19-深入一點點認識 Git:兩種不讓檔案被 Git 追蹤的方式:.gitignore 與 .git/info/exclude

  • 分享至 

  • xImage
  •  

如果希望某個檔案不要被 git 追蹤,共有兩種方式,一種是讓協作的所有成員都知道這個檔案不要被追蹤,就放在 .gitignore;另一種是只在自己的本機端不要被追蹤,可放在 .git/info/exclude(我們終於要來看 .git/info/ 裡面的東西啦!)

本文將進行以下實驗,探討兩者差別:
https://ithelp.ithome.com.tw/upload/images/20250919/20178513Xl24C1fHSk.png

簡單說明如下:

  1. 把左下角 code/ 有被 git 追蹤的檔案推到 GitHub。
  2. 把剛剛推到 GitHub 的檔案都拉到另一目錄 another_code/;在 another_code/ 新建剛剛沒被推上 GitHub、但 code/ 有的檔案。
  3. another_code/ 有被 git 追蹤的檔案推到 GitHub。
  4. 在原本目錄 code/ 把當前 GitHub 上的檔案拉下來。

透過這些實驗,我們將能感受到 .gitignore 與 .git/info/exclude 的差別。

前置準備

先透過以下指令,在經過 git initcode/ 資料夾中,準備兩個想被忽略的檔案。

echo "Ignore in .gitignore" > ignore_gitignore.txt

再來是想被 .git/info/exclude 忽略的檔案:

echo "Ignore in exclude" > ignore_exclude.txt

ignore_gitignore.txt 要被加進 .gitignore 中:

echo "ignore_gitignore.txt" > .gitignore

ignore_exclude.txt 則是要被放在 .git/info/exclude 中:

echo "ignore_exclude.txt" > .git/info/exclude

另外做一個沒有要被忽略的檔案為對照組:

echo "Normal" > normal.txt

這時整體資料夾結構長這樣:

code/
├── .git/
│   ├── hooks/
│   ├── info/
│   │     └── exclude    # 內文含"ignore_exclude.txt"
│   └── ...
│
├── .gitignore           # 內文為"ignore_gitignore.txt"
├── ignore_exclude.txt   # 內文為"Ignore in exclude"
├── ignore_gitignore.txt # 內文為"Ignore in .gitignore"
└── normal.txt           # 內文為"Normal"

實驗一:把 code/ 有被 Git 追蹤的檔案推到 GitHub

現在透過以下指令,把 code/ 所有檔案都加到預存區:

git add .

使用 git status 檢查,會發現 .gitignorenormal.txt 被放到預存區、被 git 追蹤:
https://ithelp.ithome.com.tw/upload/images/20250919/20178513bBYubGgHRb.png

相較之下,被寫在 .git/info/excludeignore_exclude.txt 與被寫在 .gitignoreignore_gitignore.txt 則沒有被追蹤。

後續再形成一個 commit:

git commit -m "Initial commit"

再輸入推到 GitHub:

git push -u <GitHub repo URL>

可發現只有 .gitignorenormal.txt 兩個剛剛在預存區的檔案有被推上去:
https://ithelp.ithome.com.tw/upload/images/20250919/20178513jPDlAgQiSx.png

實驗二:把 GitHub 上的檔案拉到另一目錄 another_code/

現在在另外一臺電腦(或者同一臺電腦 code/ 以外的地方)把這個 GitHub 倉儲拉下來:

git clone <GitHub repo URL>

註:使用 git clone 會讓新目錄名稱與 GitHub 上的倉儲相同,為 Day19,但我在本機端改名為 another_code/。

這時在新電腦或新目錄中,結構如下:

another_code/            # 從Day19改名為another_code
├── .git/
│   ├── hooks/
│   ├── info/
│   │     └── exclude    # 內文「不」含"ignore_exclude.txt"
│   └── ...
│
├── .gitignore           # 內文為"ignore_gitignore.txt"
└── normal.txt           # 內文為"Normal"

跟原本的目錄相比,主要有兩個差別:

  1. .git/info/exclude:不再有原本目錄寫在裡面的 ignore_exclude.txt
  2. 原本就被放在 .gitignore,沒有被 git 追蹤的 ignore_exclude.txt 不在裡面。

在新目錄 another_code/ 中手動加上原本被忽略的檔案

如果我們在 another_code/ 中,手動加上被放在 .gitignore 的檔案:

echo "Ignore in .gitignore again" > ignore_gitignore.txt

另加上原目錄中被放在 .git/info/exclude 的檔案:

echo "Ignore in exclude again" > ignore_exclude.txt

如果這時候再把所有檔案加進預存區:

git add .

會發生什麼狀況呢?
https://ithelp.ithome.com.tw/upload/images/20250919/20178513ruicS62YO1.png

ignore_exclude.txt 居然被加進去了!

實驗三:把 another_code 中有被 Git 追蹤的檔案都推到 GitHub

如果再下 commit:

git commit -m "Add ignore_exclude.txt"

接著推上 GitHub:

git push -u <repo URL>

這時候觀察 GitHub 倉儲:
https://ithelp.ithome.com.tw/upload/images/20250919/201785130yNv8PJvbz.png

ignore_exclude.txt 被推上去了!綜合實驗二、三可發現:在 another_code/ 裡,沒寫在 .gitignoreignore_exclude.txt 是不會被忽略的。

實驗四:回到 code/,把目前 GitHub 最新版本拉下來

那如果原目錄去 git pull 呢?
https://ithelp.ithome.com.tw/upload/images/20250919/20178513SkRz3gYz7G.png

ignore_exclude.txt 有被拉下來,而且還蓋過了原目錄中 ignore_exclude.txt 的內容!
https://ithelp.ithome.com.tw/upload/images/20250919/20178513h3WKVqu7zA.png

但如果在原目錄 code/ 又改了這份 ignore_exclude.txt 檔案:

echo "hello" > ignore_exclude.txt

然後再把全部檔案加到預存區:

git add .

這份被寫在 .git/info/exclude 的檔案會被加進去嗎?
https://ithelp.ithome.com.tw/upload/images/20250919/20178513N1CWAD4SUt.png

咦?怎麼有?趕緊來看看 code/ 裡的 .git/info/exclude 到底是不是還有這份檔案?
https://ithelp.ithome.com.tw/upload/images/20250919/20178513mTz8kt9YB1.png

居然有,可是怎麼會沒效呢?

這是因為不管是 .gitignore 或 .git/info/exclude 都只對「尚未被 git 追蹤的檔案」有效,當我們在原目錄 git pull 時,拉到的 ignore_exclude.txt 已經是被 git 追蹤的狀態,所以就算被寫在 .git/info/exclude,也還是有被持續追蹤的。

在下一篇文章中,我們將以這兩者中較為常用的 .gitginore 為例,探討到底什麼樣的情況會讓檔案被 git 追蹤,以及被追蹤後,要如何讓其被退追蹤。

小結

由上述的實驗,我們可以比較出:

  • 列在 .gitignore 中的檔案,經 git pushgit clone/pull 到其他目錄後,同名檔案依然可保持不被 git 追蹤。
  • 列在 .git/info/exclude 中的檔案,只在本機不會被 git 追蹤,經 git pushgit clone/pull 到其他目錄後,這些同名檔案就會被追蹤。

這兩者都只對「尚未被 git 追蹤」的檔案有效,因此,如果某檔案於本機中有被放在 .git/info/exclude、但後來拉下來的 GitHub 倉儲也有同名檔案,表示該檔案已被 git 追蹤,拉到本機之後,即便 .git/info/exclude 仍寫著這檔案名稱,此檔案還是會繼續被追蹤。

同樣的道理在 .gitignore 也適用,我們將在下篇文章詳細探討。

參考資料

  1. When would you use .git/info/exclude instead of .gitignore to exclude files?
  2. Exclude files from git without committing changes to .gitignore 🙅
  3. Git 學習手冊#5 忽略清單:ignoring files

上一篇
Day 18-深入一點點認識 Git:git cherry-pick 到底怎麼搬 commit 的?
下一篇
Day 20-深入一點點認識 Git:不是把檔案都塞進 .gitignore 就可確保其不被追蹤
系列文
深入一點點認識 Git22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言