上一篇:Git 2/4: 在 VS Code 啟用 Git?介紹 Git 版面基本操作
在上一篇教學裡,我們介紹了如何在 VS Code 裡使用 Git 的基本功能,以及透過 VS Code 內置的 Source Control 版面輕易地用 Git 管理我們的專案。
這次,我們來探討一個常見的 Git 問題:到底我們是否有方法去排除 Git 的索引?
為什麼我們需要排除某些檔案?
我們開始討論如何排除 Git 索引之前,先要討論一下為什麼我們要這樣做。
回到起初我們對版本管理(version control)的討論,我們使用 Git 或其他版本管理工具的最大原因,就是為了可以有效地管理 Python 專案檔案的修訂,使我們修改檔案的時候,可以有輕鬆還原檔案的機制。
可是,我們是否真的需要還原所有 Python 專案裡的檔案?還是我們可以巧妙地排除一些沒有還原價值的檔案,從而簡化我們的版本管理過程?
以下我們提出這個大原則,並一些平常會派出的檔案例子:
- 如果檔案 A 是衍生自專案的其他檔案,那麼我們可以排除檔案 A
- 如果檔案 A 是本地(local)編程環境下的需求,那麼我們可以排除檔案 A
例子 1:__pycache__ 位元組碼(bytecode)
您可能在 VS Code 編程的時候會見過「__pycache__」的文件夾出現在您的專案裡。
其實 __pycache__ 就是 Python 的位元組碼(bytecode)。簡單來說,每當我們運行 Python 的檔案時,電腦都需要把我們的 Python 代碼翻譯成位元(byte),即是 0 1 0 1 等電腦明白的語言。而如果我們每次運行 Python 檔案,電腦都進行一次這樣的翻譯,其實頗費時間的。
因為大多數 Python 編程師沒那個美國時間,所以 Python 暫存(cache)了這些已經翻譯的位元,使我們下一次運行同一個檔案時,可以省卻翻譯的時間。
可是,每當我們改變了 Python 檔案,這些 __pycache__ 的文件便需要被重新製作。因此,__pycache__ 是衍生於其他檔案的,我們應該要求 Git 排除索引。
例子 2:.venv 裡面的檔案
延伸閱讀:
另外一個例子就是 Python 虛擬環境所產生的檔案。還記得我們在之前的教學裡提及的 Python 虛擬環境嗎?
簡單來說,虛擬環境就像是一個專屬這個 Python 專案的拷貝。如果您細心留意,會發現在 .venv 的文件夾裡,會見到有一個名叫「site-packages」的文件夾,而這個文件夾包含了所有這個專案需用的 Python library 的檔案。
問題是,我們其實並不需要 Git 去索引每一個我們需用的 Python library 的實際代碼檔案,因為這些檔案可以十分簡單地從 pip 裡重新安裝。
還記得在 pip 的教學裡,我們提及 pip 可以安裝特定的 library 版本嗎(例如 pandas==1.4.2)?從版本管理的角度而言,更加重要的,是我們需要讓 Git 去紀錄我們使用了 Python library 的哪一個版本。
而這個紀錄了專案使用了哪一些 Python library 和這些 library 版本的檔案,當然就是我們經常提及的 requirements.txt 了!
因此,從檔案衍生的命題而言,我們應該要求 pip 略過 .venv 文件夾裡的檔案。取而代之的,是我們需要 Git 為 requirements.txt 索引,確保我們知道在專案的某一個時刻,我們在使用什麼的 library。
例子 3:授權憑證(credentials)
許多時候,我們在 Python 專案需要使用到某些 API 服務。而這些 API 服務需要我們提供一個授權憑證(credentials)以存取他們的服務。
在一些簡單的專案裡,我們可以直接在專案裡建立一個 .credentials 的文件夾,並把憑證資料(例如 API Key)儲存成 json 檔案。
問題是,這些的憑證資料其實沒有版本管理的價值。試想像這些 API Key 就像我們的電郵密碼,一旦我們更改了,舊的密碼便沒有用了。同樣道理,API Key 一旦更新了,即使我們把專案還原,還是沒有辦法使用舊的 API Key 存取 API 服務。
因此,從本地(local)編程環境下的需求來說,憑證檔案也是沒有版本管理的需要的。我們應該要求 Git 避免索引。
解決方法:.gitignore
我們回顧了這 3 個例子後,可以來學習一下解決這個問題的方法:.gitignore 檔案了!
根據 Git 官網,.gitignore 是一個讓我們決定在文件夾裡有什麼檔案需要被 Git 忽略的指示。
值得一提的,是我們可以在每一個子文件夾(subdirectory)定義一個 .gitignore 檔案。所以,這個 .gitignore 檔案其實是十分靈活(flexible)的,我們可以指定不同文件夾有不同的政策(policy)。
在 VS Code 開始使用 .gitignore
以下我們會示範在 VS Code 使用 .gitignore 去管理我們的 Git 索引。
首先我們在 VS Code 的 Source Control 版面啟用 Git 管理。如果您不知道如何在 VS Code 裡使用 Git,可以參考這裡:Git 2/4: 在 VS Code 啟用 Git?介紹 Git 版面基本操作
完成後,我們會見到如以下畫面一樣,Git 想索引許多個檔案。按一下「View as tree」把檔案歸類成每個文件夾,使我們更加方便區分不同的檔案。
為什麼 Changes 裡沒有 .venv?
來到這裡,您可能已經有一個疑問:為什麼在 Changes 裡沒有我們的虛擬環境 .venv 的文件夾?
如上圖一樣,如果我們會到 Explorer 的版面,會發現 .venv 的文件夾是唯一一個不是綠色的文件夾(綠色在這裡代表 Git 已索引的檔案/文件夾)。
我們仔細一看,在 .venv 文件夾裡原來早已有一個 .gitignore 的檔案。其實這個 .gitignore 的檔案在我們創建虛擬環境被一併製造了出來。
還記得我們在上面提及每一個子文件夾(subdirectory)可以定義一個 .gitignore 檔案?沒錯,這個在 .venv 裡面的 .gitignore 就是專屬 .venv 文件夾的 .gitignore 檔案,而它的內容不會影響到我們專案裡其他的檔案。
在這個 .gitignore 的檔案裡,我們見到只有簡單一行「*」。這代表我們要求 Git 避免對任何在 .venv 文件夾裡面的檔案索引。因此,您可以看到整個 .venv 檔案都是白色的,而非綠色的。
創建專案的 .gitignore 檔案
現在我們可以準備創建我們的專案(project-wide) .gitignore 檔案了!
如上面所說,我們在每個子文件夾(subdirectory)裡都可以創建專屬該文件夾的 .gitignore,例如剛才 .venv 的例子。但是,如果有一些檔案是每一個子文件夾都應該忽略的,那麼我們可以直接建立一個專案層次(project-wide)的 .gitignore 去處理這些檔案。
回到 VS Code 的 Source Control 版面,我們可以右選(right-click)最頂端的 __pycache__ 文件夾,並選擇「Add to .gitignore」:
回到 Explorer 版面,我們可以見到一個新的 .gitignore 檔案在我們的專案第一層(project root)出現了。
值得留意的是 .venv 裡的 .gitignore 仍然未有被改變,而且與新建的 .gitignore 是獨立的。新建的 .gitignore 就是我們提及的專案(project-wide).gitignore 檔案了。
以文件夾名稱選取檔案
經過以上的操作後,您可能會留意到,在 .gitignore 的檔案裡有的是每一個在專案第一層(root directory)的 __pycache__ 文件夾裡的檔案名稱。而且,從上圖可見,在 apps 和在 assets 裡面的 __pycache__ 仍然是綠色的,即 Git 仍然未有移除這些索引。
既然我們知道在專案任何的文件夾裡,我們都不希望索引 __pycache__ 的子文件夾,那麼我們是否可以直接以文件夾的名稱來排除檔案?
如果我們按上圖一樣,修改 .gitignore 去加入以下的一行,然後儲存:
__pycache__/
您會發現現在連在 apps 和 assets 文件夾裡面的 __pycache__ 也被排除了在 Git 的索引之外。
同樣道理,如果我們有其他我們不希望 Git 索引的文件夾,也可以用「文件夾名稱 /」的格式加入 .gitignore:
# 要從 Git 移除的文件夾 __pycache__/ .credentials/ .vscode/ .venv/
經過上圖的修改後,您會發現連 .credentails(本地的憑證)、.vscode(VS Code 專案的本地設定)也被排除在 Git 索引之外。
以檔案名稱選取檔案
如果您有細心留意,__pycache__ 文件夾裡的檔案文件格式都是 .pyc。
如上圖所示,如果我們只是排除了任何名叫 __pycache__ 的文件夾,那麼我們會少排除了在專案第一層的 app.pyc 檔案。這個檔案是 app.py 的暫存。
除了按文件夾去排除檔案以外,.gitignore 也容許我們排除特定的檔案。而其中一個方法就是排除所有有同樣文件格式的檔案。
如果我們按上圖一樣,修改 .gitignore 去加入以下的一行,然後儲存:
*.pyc
您會發現 app.pyc 也被排除在 Git 索引之外。比方說,我們需要排除所有 png 檔案,我們也可以在 .gitignore 裡加入「*.png」讓 Git 避免索引這些圖片。
當然,我們也可以直接指明檔案的名稱來要求 Git 停止索引特定的檔案,例如下圖這樣:
更多 .gitignore 的語法
以上我們提及的 .gitignore 語法已經包含了絕大多數會使用到 .gitignore 的情況。但如果您想再了解更多的 .gitignore 語法,可以到這個連結了解更多:gitignore 的語法
萬用的 .gitignore
其實網路上早已有許多不同版本的 .gitignore ,可以讓我們不用每次開啟新的專案時都重新設定一次。
相反,我們可以直接拷貝這些的 .gitignore 檔案到每一個專案,再按實際情況增加/減少這些規則。
我比較喜歡使用的是在 GitHub 裡集合不同網友,公認比較齊全和專為 Python 專案而設的 .gitignore 檔案:
結語
希望您在這一篇教學學會了使用 .gitignore 幫助您管理專案。下一篇我們會介紹如何從 VS Code 連結 GitHub,使用共享的 GitHub 服務管理專案!
其他文章:
- VSCode 1/5: macOS 最佳 Python 編程工具?豐富的插件商店?Visual Studio Code 安裝攻略
- VSCode 2/5: 設定虛擬環境 Virtual Env,管理 Python 專案!
- VSCode 3/5: 實戰篇!版面介紹、管理 Python 專案和多個 .py
- VSCode 4/5: 讓 pip 安裝和管理 Python Libraries,結合虛擬環境!
- VSCode 5/5: Jupyter Notebook 互動編程?實在太方便了
- Git 1/4: 甚麼是 Git/Github?為什麼需要專案版本管理?
- Git 2/4: 在 VS Code 啟用 Git?介紹 Git 版面基本操作