You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何添加Git子模块时指定特定提交并记录到.gitmodules文件?

Git子模块固定特定提交的实现方法

核心需求

希望.gitmodules文件记录子模块的指定提交,且该提交不会自动变更,仅在主动执行类似git submodule --init <path2submodule_repo> --remote的操作时才更新。但查看git submodule手册后发现,git submodule add命令没有直接指定提交的选项,疑惑是否无法通过.gitmodules实现该需求。

git submodule命令手册(节选)

名称
       git-submodule - 初始化、更新或检查子模块

概要
       git submodule [--quiet] [--cached]
       git submodule [--quiet] add [<选项>] [--] <仓库> [<路径>]
       git submodule [--quiet] status [--cached] [--recursive] [--] [<路径>...]
       git submodule [--quiet] init [--] [<路径>...]
       git submodule [--quiet] deinit [-f|--force] (--all|[--] <路径>...)
       git submodule [--quiet] update [<选项>] [--] [<路径>...]
       git submodule [--quiet] set-branch [<选项>] [--] <路径>
       git submodule [--quiet] set-url [--] <路径> <新URL>
       git submodule [--quiet] summary [<选项>] [--] [<路径>...]
       git submodule [--quiet] foreach [--recursive] <命令>
       git submodule [--quiet] sync [--recursive] [--] [<路径>...]
       git submodule [--quiet] absorbgitdirs [--] [<路径>...]

描述
       检查、更新并管理子模块。

       关于子模块的更多信息,请参见 gitsubmodules(7)。

命令
       无参数时,显示现有子模块的状态。有多个子命令可用于对子模块执行操作。

       add [-b <分支>] [-f|--force] [--name <名称>] [--reference <仓库>] [--depth <深度>] [--] <仓库> [<路径>]
           将给定仓库作为子模块添加到当前项目(称为"超项目")的下一次提交变更集中。

           <仓库> 是新子模块的源仓库URL。可以是绝对URL,或者(如果以 ./ 或 ../ 开头)相对于超项目默认远程仓库的位置(请注意,若要指定与超项目 bar.git 相邻的仓库 foo.git,必须使用 ../foo.git 而非 ./foo.git——这符合相对URL的规则,因为Git中相对URL的解析与相对目录的解析方式相同)。

           默认远程是当前分支的远程跟踪分支对应的远程。如果不存在此类远程跟踪分支或HEAD处于分离状态,则假定"origin"为默认远程。如果超项目未配置默认远程,则超项目自身即为权威上游,此时使用当前工作目录。

           可选参数 <路径> 是克隆后的子模块在超项目中的相对位置。如果未指定<路径>,则使用源仓库的规范部分(例如"/path/to/repo.git"对应"repo","host.xz:foo/.git"对应"foo")。如果<路径>已存在且已是有效的Git仓库,则直接暂存提交而不进行克隆。除非使用--name指定逻辑名称,否则<路径>也会作为子模块在配置项中的逻辑名称。

           给定的URL会被记录到.gitmodules中,供后续克隆超项目的用户使用。如果URL是相对于超项目仓库的相对路径,则默认超项目和子模块仓库会保持相同的相对位置,仅需提供超项目的URL即可。git-submodule会通过.gitmodules中的相对URL正确定位子模块。

可行实现方式:手动切换到指定提交

git submodule add确实没有直接指定提交的选项,但可以通过先添加子模块、再切换到目标提交的方式实现需求,步骤如下:

  1. 添加子模块
git submodule add -f --name coq-projects/metalib https://github.com/plclub/metalib.git coq-projects/metalib
  1. 切换到子模块目录并检出指定提交
cd coq-projects/metalib
git checkout <提交哈希>

如果需要批量操作多个子模块,可使用:

git submodule foreach git checkout <提交哈希>

注意:URL中附加提交哈希无效

尝试在git submodule add的URL后添加#<提交哈希>是无效的,Git不会拉取指定的提交。实际操作示例如下:

(iit_synthesis) brando9~/proverbot9001 $ git submodule add -f --name coq-projects/metalib git+https://github.com/plclub/metalib.git#104fd9efbfd048b7df25dbac7b971f41e8e67897 coq-projects/metalib
Reactivating local git directory for submodule 'coq-projects/metalib'.

...

(iit_synthesis) brando9~/proverbot9001/coq-projects/metalib $ cd coq-projects/metalib
-bash: cd: coq-projects/metalib: No such file or directory
(iit_synthesis) brando9~/proverbot9001/coq-projects/metalib $ git checkout 104fd9efbfd048b7df25dbac7b971f41e8e67897
Note: switching to '104fd9efbfd048b7df25dbac7b971f41e8e67897'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 104fd9e Sync Makefile coq version with README/Docker
(iit_synthesis) brando9~/proverbot9001/coq-projects/metalib $ git status
HEAD detached at 104fd9e
nothing to commit, working tree clean

(注:上述操作中切换目录的错误是路径输入失误,不影响核心流程)

完成上述步骤后,超项目的Git会记录子模块当前的提交哈希,后续克隆该超项目的用户执行git submodule update时,会自动拉取该指定提交,且不会自动变更——除非主动执行git submodule update --remote这类触发更新的命令。

内容的提问来源于stack exchange,提问作者Charlie Parker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:05:15