Git 子模組問題

問題描述

在 GitHub 上查看專案時,發現前後端子目錄(voting-system-bevoting-system-fe)顯示為特殊的連結圖示,而非普通資料夾。點擊這些連結後無法正常訪問內容。

可以看到圖案跟普通的資料夾不一樣!

問題原因

這種情況發生是因為這些子目錄被設定為 Git 子模組(submodules)。子模組是 Git 的一個功能,讓你可以在一個 Git 儲存庫中包含其他 Git 儲存庫。

當我們一開始將前後端專案 clone 到總專案目錄中時,實際上建立了子模組引用,這些引用指向前後端專案的特定 commit(預設分支上的最新 commit,通常就是 main 或 master 上的最新 commit)。這導致:

  1. 前後端專案各自更新後,總專案不會自動更新

  2. 這些子目錄中有自己的 .git 目錄,所以在總專案中修改前後端程式碼時,這些變更不會被總專案的 Git 追蹤

解決方案

有兩種解決方法:

方法一:正確初始化和使用子模組

如果希望保持子模組結構(前後端各自獨立版控,同時總專案可以引用它們),需要正確初始化和更新子模組:

# 初始化子模組
git submodule init

# 更新子模組,拉取對應的實際內容
git submodule update

後續要更新子模組時,可以使用:

# 更新所有子模組到遠端最新版本
git submodule update --remote

方法二:將前後端程式碼移出主儲存庫,用腳本管理

如果不想使用子模組功能,而是將前後端程式碼直接從總專案中移除:

# 刪除子模組引用
git rm --cached voting-system-be
git rm --cached voting-system-fe

# 如果存在 .gitmodules 檔案,也需要刪除對應項目

# 然後添加以下到 .gitignore
 voting-system-be/
 voting-system-fe/

注意:執行第二個方法後,前後端目錄會從檔案系統中消失,因為它們是作為子模組引用而非實際檔案存在的。不過不用擔心,可以再次 clone 前後端專案把程式碼拉回來,也可以透過腳本來執行 clone。

子模組操作的額外說明

添加子模組

git submodule add <儲存庫URL> <本地路徑>

例如:

git submodule add https://github.com/your-org/voting-system-be.git voting-system-be

克隆包含子模組的專案

# 克隆主專案
git clone <主專案URL>

# 初始化和更新子模組
cd <主專案目錄>
git submodule init
git submodule update

或者一步完成:

git clone --recursive <主專案URL>

更新特定子模組

cd <子模組目錄>
git pull origin main
cd ..
git add <子模組目錄>
git commit -m "更新子模組"

刪除子模組

完整刪除子模組的步驟:

# 1. 取消暫存子模組路徑
git rm --cached <子模組路徑>

# 2. 刪除子模組相關目錄
rm -rf <子模組路徑>

# 3. 刪除 .gitmodules 中的相關部分
# 編輯 .gitmodules 檔案,移除該子模組的區段

# 4. 刪除 .git/config 中的相關部分
# 編輯 .git/config 檔案,移除該子模組的區段

# 5. 刪除 .git 目錄中的子模組目錄
rm -rf .git/modules/<子模組路徑>

# 6. 提交變更
git add .gitmodules
git commit -m "移除子模組 <子模組路徑>"

子模組優缺點

優點

  1. 可以在單一專案中管理多個獨立的程式碼庫

  2. 每個子模組都可以有自己的版本歷史和分支

  3. 主專案可以精確控制使用的子模組版本

  4. 適合前後端分離的專案架構

缺點

  1. 子模組不會自動更新,需要手動更新

  2. 操作較為複雜,需要團隊成員都了解子模組概念

  3. 容易造成混淆,特別是當子模組的改動需要同步到主專案時

  4. 子模組的目錄結構改變時可能會導致問題

Last updated