我有一个带有Git子模块的项目。它来自ssh://…URL,在提交a上,提交B已经被推到那个URL,我想让子模块检索提交,并更改它。

现在,我的理解是git子模块更新应该这样做,但它没有。它不做任何事情(没有输出,成功退出代码)。这里有一个例子:

$ mkdir foo
$ cd foo
$ git init .
Initialized empty Git repository in /.../foo/.git/
$ git submodule add ssh://user@host/git/mod mod
Cloning into mod...
user@host's password: hunter2
remote: Counting objects: 131, done.
remote: Compressing objects: 100% (115/115), done.
remote: Total 131 (delta 54), reused 0 (delta 0)
Receiving objects: 100% (131/131), 16.16 KiB, done.
Resolving deltas: 100% (54/54), done.
$ git commit -m "Hello world."
[master (root-commit) 565b235] Hello world.
 2 files changed, 4 insertions(+), 0 deletions(-)
 create mode 100644 .gitmodules
 create mode 160000 mod
# At this point, ssh://user@host/git/mod changes; submodule needs to change too.
$ git submodule init
Submodule 'mod' (ssh://user@host/git/mod) registered for path 'mod'
$ git submodule update
$ git submodule sync
Synchronizing submodule url for 'mod'
$ git submodule update
$ man git-submodule 
$ git submodule update --rebase
$ git submodule update
$ echo $?
0
$ git status
# On branch master
nothing to commit (working directory clean)
$ git submodule update mod
$ ...

我也尝试过git fetch mod,它似乎做了一个取回(但不可能,因为它不提示密码!),但git日志和git显示否认新提交的存在。到目前为止,我只是在rm-ing模块并重新添加它,但这在原则上是错误的,在实践中也很乏味。


当前回答

如果你不知道主机分支,这样做:

git submodule foreach git pull origin $(git rev-parse --abbrev-ref HEAD)

它将获得主Git存储库的一个分支,然后为每个子模块提取相同的分支。

其他回答

处理包含子模块的git项目最简单的方法是总是添加

--recurse-submodules 

在每个git命令的末尾 例子:

git fetch --recurse-submodules

另一个

git pull --update --recurse-submodules

等等……

git子模块update命令实际上告诉git,您希望每个子模块都检出在超项目索引中已经指定的提交。如果您希望将子模块更新为远程可用的最新提交,则需要直接在子模块中执行此操作。

总结一下:

# Get the submodule initially
git submodule add ssh://bla submodule_dir
git submodule init

# Time passes, submodule upstream is updated
# and you now want to update

# Change to the submodule directory
cd submodule_dir

# Checkout desired branch
git checkout master

# Update
git pull

# Get back to your project root
cd ..

# Now the submodules are in the state you want, so
git commit -am "Pulled down update to submodule_dir"

或者,如果你是个大忙人:

git submodule foreach git pull origin master

@Jason在某种程度上是正确的,但不完全正确。

更新 更新已注册的子模块, 即克隆缺失子模块和 方法中指定的提交 包含存储库的索引。 这将使子模块HEAD为 分离,除非——rebase或——merge是 指定或键 子模块。美元的名字。Update设置为 重组或合并。

因此,git子模块update确实签出,但它是提交到包含存储库的索引中。它根本不知道上游的新提交。所以去你的子模块,获得你想要的提交,并在主存储库中提交更新后的子模块状态,然后更新git子模块。

主项目指向子模块应该所在的特定提交。Git子模块update尝试检查每个已初始化的子模块中的提交。子模块实际上是一个独立的存储库——仅仅在子模块中创建一个新的提交并推送是不够的。您还需要显式地在主项目中添加子模块的新版本。

所以,在你的情况下,你应该在子模块中找到正确的提交-让我们假设这是master的提示:

cd mod
git checkout master
git pull origin master

现在回到主项目,阶段子模块并提交:

cd ..
git add mod
git commit -m "Updating the submodule 'mod' to the latest version"

现在推送你的主项目的新版本:

git push origin master

从这一点开始,如果有人更新了他们的主项目,那么他们的git子模块update将更新子模块,假设它已经初始化。

简单地获取子模块:

git submodule update --init --recursive

现在继续将它们更新到最新的主分支(例如):

git submodule foreach git pull origin master