如何将 Git 子模块指针恢复到存储在包含存储库中的提交?

问题描述 投票:0回答:7

我的主 git 存储库中有一个 git 子模块。据我了解,主存储库存储一个 SHA 值(某处...),指向它“链接到”的子模块的特定提交。

我进入我的子模块并输入

git checkout some_other_branch
。我不知道我来自哪个提交。

我想恢复该指针,以便主存储库和子模块再次同步。

我的第一个(可能是天真的)本能是说

git reset --hard
- 这似乎适用于其他一切。令我惊讶的是,它不适用于这种情况。

所以我发现我可以输入

git diff
,记下子模块指针曾经具有的 SHA ID,然后进入子模块和
git checkout [SHA ID]
...但肯定有更简单的方法吗?

由于我仍在学习 git 子模块,如果有我不知道的概念单词,请随时纠正我的术语。

git git-submodules
7个回答
223
投票

您想要更新子模块,使其与父存储库认为应该的内容同步。 这就是更新命令的用途:

来自子模块手册页:

更新已注册的子模块,即克隆缺失的子模块并
签出包含的索引中指定的提交
存储库。这将使子模块 HEAD 分离,除非
--rebase 或 --merge 指定或关键子模块.$name.update
设置为变基或合并。

运行这个,一切都应该很好:

git submodule update --init

您还可以添加

--recursive
标志来递归所有子模块。


24
投票

要更改子模块指向的提交,您需要在子模块中签出该版本,然后返回到包含的存储库,添加并提交该更改。

或者,如果您希望子模块位于顶级存储库指向的版本上,请执行

git submodule update --recursive
。如果您刚刚克隆,请添加
--init

此外,没有子模块命令的

git submodule
将显示您指向的提交。如果不同步,提交前面会有 - 或 +。

如果您查看其中包含子模块的树,您可以看到该子模块被标记为

commit
,而不是其余的 blob 或树。

要查看特定提交指向子模块的内容,您可以:

git ls-tree <some sha1, or branch, etc> Submodule/path

然后,如果您愿意,可以通过将其传递到日志等来查看提交或其他任何内容(git 命令级别的

git-dir
选项允许您跳过 cd 到子模块):

git --git-dir=Submodule/path log -1 $(<the above statement>)

10
投票

我刚刚遇到的另一种情况是,如果子模块中存在您想要丢弃的未暂存的更改。

git submodule update
不会删除该更改,父目录上的
git reset --hard
也不会删除该更改。 您需要转到子模块目录并执行
git reset --hard
。 因此,如果我想完全放弃父模块和子模块中未暂存的更改,我会执行以下操作:

家长:

git reset --hard

git submodule update

在子模块中:

git reset --hard

6
投票

在“超级项目”文件夹中使用

git ls-tree HEAD
查看子模块最初所在的提交。然后切换到子模块目录并使用
git log --oneline --decorate
查看原始提交位于哪个分支。最后,
git checkout original-commit-branch

使用我设置的一些测试目录,命令可能如下所示:

$ git --version
git version 1.7.4.1
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   sm2 (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git ls-tree HEAD
100644 blob 76813a07ae558db274cefc6d903ec24323fdeb0d    .gitmodules
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    main
160000 commit 7c5889497938cd5699a9234a98ee93947e52b1ed  sm1
160000 commit f68bed61cba6f94cef57554f2cf46a45a4a0d337  sm2
$ cd sm2
$ git log --oneline --decorate
5b8d48f (HEAD, foo1) foo1.1
f68bed6 (origin/master, origin/HEAD, master) Initial commit.
$ git checkout master
Switched to branch 'master'
$ cd ..
$ git status
# On branch master
nothing to commit (working directory clean)

“超级项目”在提交时显示了 sm2 子模块

f68bed6
但 sm2 的 HEAD 位于
5b8d48f
。子模块提交
f68bed6
上有三个分支,可用于在子模块目录中签出。


6
投票

我想忽略子模块和我的模块中的任何更改

以下命令帮助了我:

git submodule update --init --recursive

6
投票

这里的答案不知何故没有解决我与子模块的具体问题,所以如果它也发生在你身上,请尝试以下...

 git submodule foreach git reset --hard

-2
投票

enter image description here

更新的视觉演练 - 这里我的子模块指向 - 8c3fd8b 转到这个文件夹会很简单......

git checkout master
error: pathspec 'master' did not match any file(s) known to git

在子模块中,例如。运行需要 stylegan2-ada 文件夹

git checkout main
git pull

这解决了我的问题(暂时)

最后一步是在父存储库中提交更改。跟踪的更改会自动出现 - 而且我不需要创建文件 - 只需通过单击 vscode 中的 + 并推送即可暂存文件更改。

在这里你可以非常清楚地看到 git 提交令人耳目一新。

-Subproject commit 8c3fd8bac3e5a54a20e860fc163d6e67cc03c623
+Subproject commit 0045ea50f1b9710ffde3ab2a9a18c0d4c97bfaed

enter image description here

故障排除

请注意,有一个 .gitsubmodule 文件指向相应的 git 远程存储库。

enter image description here

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.