一、前言
目前在开发一个QT项目,需要搭配师兄的一个仓库代码进行使用。考虑到后续可能需要对这个子仓库代码进行更新,所以最好是让主仓库也可以跟踪这个子仓库的代码。
二、实现方法比较
实现子仓库Git跟踪的方式、优缺点介绍如下:
- Git子模块(Submodule)
- 优点
- 明确的仓库分离:子模块保持独立的版本控制,清晰显示为外部依赖
版本精确锁定:主仓库引用子模块的特定提交,确保所有人使用完全相同的版本
存储效率:主仓库只存储子模块的引用和路径,不包含子模块的实际内容
独立更新:子模块可以单独进行更新和版本控制,不会影响主仓库
权限分离:适合团队分工,不同人负责不同模块的场景
- 明确的仓库分离:子模块保持独立的版本控制,清晰显示为外部依赖
- 缺点
- 使用复杂性:需要学习额外的Git命令,操作流程较复杂
克隆步骤增加:其他人克隆项目时需要额外的步骤初始化子模块 (--recursive 选项)
更新不自动:子模块不会自动更新到最新版本,需要手动更新
历史追踪困难:难以查看包含子模块变更的完整项目历史
- 使用复杂性:需要学习额外的Git命令,操作流程较复杂
- Git子树(Subtree)
- 优点
- 单一仓库体验:对于使用者来说,就像在操作单一仓库
完整性:克隆主仓库时自动包含所有子树内容,不需要额外步骤
历史完整:可以在主仓库中查看包含子树的完整历史
简单使用:对大多数团队成员来说,不需要了解子树的存在
向后兼容:可以与不了解子树的开发者协作
- 单一仓库体验:对于使用者来说,就像在操作单一仓库
- 缺点
- 仓库体积增大:主仓库包含子树的全部内容,增加了仓库大小
双向同步复杂:向原始子仓库贡献更改的流程较复杂
合并冲突风险:当子树和主仓库同时修改时,可能产生复杂的合并冲突
历史混合:子树的提交历史会混入主仓库的历史
- 仓库体积增大:主仓库包含子树的全部内容,增加了仓库大小
三、Git子模块(Submodule)的使用方式
我目前选择Git子模块(Submodule)来进行子仓库的更新,Git子树(Subtree)的使用方式后续会编写博客进行记录。
1. 移除当前嵌入式仓库并添加为子模块
已知子仓库位于主仓库根目录的 lib/AIEngine/proj_ai_engine
步骤1:移除缓存中的嵌入式仓库(不会删除代码,只是删除缓存)
# 确保在主仓库根目录下
git rm --cached lib/AIEngine/proj_ai_engine
步骤2:添加子模块
# 使用子仓库的远程URL添加子模块
git submodule add <子仓库URL> lib/AIEngine/proj_ai_engine
步骤3:提交更改
git add .gitmodules lib/AIEngine/proj_ai_engine
git commit -m "Add proj_ai_engine as a submodule"
此时在主仓库的根目录下面就会有一个.gitmodules存在了。
2. 跟踪子仓库的分支,以“remotes/origin/feature/windows-support”分支为例子
步骤1:进入子模块目录
# 确保在主仓库根目录下
cd lib/AIEngine/proj_ai_engine
步骤2:拉取远程分支(如果本地没有)
首先,我们需要确认本地是否存在 feature/windows-support
分支。 如果不存在,我们需要从远程拉取。
git fetch origin
现在你可以看到 origin/feature/windows-support
分支。
步骤3:创建并检出本地分支 (如果不存在)
如果本地不存在 feature/windows-support
分支,则需要基于远程分支创建并检出该分支:
git checkout -b feature/windows-support origin/feature/windows-support
如果本地已经存在 feature/windows-support
分支,直接检出即可:
git checkout feature/windows-support
步骤4:设置跟踪关系
现在确保 feature/windows-support
分支已经检出,设置本地分支跟踪远程分支 origin/feature/windows-support
:
git branch --set-upstream-to=origin/feature/windows-support feature/windows-support
解释:
git branch --set-upstream-to=origin/feature/windows-support feature/windows-support
: 这条命令将本地的feature/windows-support
分支设置为跟踪远程的origin/feature/windows-support
分支。 这意味着当你执行git pull
时,它会从origin/feature/windows-support
获取最新的更改。
步骤5:返回主仓库根目录
cd ../../.. #返回主仓库根目录
步骤6:暂存并提交主仓库的更改
git add .
git commit -m "Submodule lib/AIEngine/proj_ai_engine tracks feature/windows-support"
详细解释:
- 进入子模块: 确保你在正确的子模块目录下。
- 拉取远程分支:
git fetch origin
拉取最新的远程分支信息,确保你知道有哪些可用的远程分支。 - 创建并检出本地分支:
git checkout -b feature/windows-support origin/feature/windows-support
创建一个新的本地分支feature/windows-support
,并将其指向远程的origin/feature/windows-support
。 如果本地分支已经存在,则直接检出。 - 设置跟踪关系:
git branch --set-upstream-to=origin/feature/windows-support feature/windows-support
是关键步骤,它告诉 Git,本地的feature/windows-support
分支应该跟踪哪个远程分支。 - 提交更改: 提交主仓库的更改,这些更改记录了子模块所跟踪的特定提交(该提交对应于子模块中
feature/windows-support
分支的HEAD
时刻)。
克隆后的操作:
当其他开发者克隆你的主仓库后,他们需要执行以下步骤:
git submodule init
git submodule update --init --recursive
或者更简洁的:
git submodule update --init --recursive
git submodule update --init --recursive
会初始化并更新子模块。 由于你在子模块内部设置了跟踪关系,所以当子模块被更新时,它会自动检出 feature/windows-support
分支,并跟踪远程的 origin/feature/windows-support
分支。
总结:
关键在于在子模块内部设置本地分支跟踪远程分支的关系。 这样,当其他开发者克隆你的仓库并更新子模块时,他们也会自动跟踪相同的远程分支。 .gitmodules
文件主要用于记录子模块的基本信息(路径、URL),而分支跟踪关系由子模块自身的 .git/config
文件管理。