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

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

我进入我的子模块并输入 git checkout some_other_branch。我不知道我来自哪个提交。

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

我的第一个(可能是天真的)直觉是说 git reset --hard——这似乎适用于其他任何东西。令我惊讶的是,它在这种情况下不起作用。

所以我已经计算出我可以输入 git diff,注意子模块指针过去使用的 SHA ID,然后进入子模块和 git checkout [SHA ID]... 但是肯定有更简单的方法吧?

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

84081 次浏览

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

或者,如果希望子模块位于 top repo 指向的版本上,则执行 git submodule update --recursive。如果您刚刚克隆了,请添加 --init

此外,没有子模块命令的 git submodule将显示您所指向的提交。如果提交不同步,那么在提交前面会有一个-或者一个 + 。

如果您查看一个包含子模块的树,您可以看到子模块被标记为 commit,而其他的子模块则是 blobs 或 tree。

看看特定的提交点对子模块写了什么,您可以:

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

然后,如果您愿意,您可以通过将其传递到 log 等等来查看提交或其他任何内容(git 命令级别的 git-dir选项允许您跳过必须向下 cd 到子模块的操作) :

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

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

从子模块页面:

Update the registered submodules, i.e. clone missing submodules and
checkout the commit specified in the index of the containing
repository. This will make the submodules HEAD be detached unless
--rebase or --merge is specified or the key submodule.$name.update
is set to rebase or merge.

运行这个程序,一切都会很好:

git submodule update --init

您还可以添加 --recursive标志以遍历所有子模块。

使用“ superproject”文件夹中的 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)

“ superproject”在提交 f68bed6时显示 sm2子模块,但 sm2在 5b8d48f时显示它的 HEAD。子模块提交 f68bed6有三个分支,可用于子模块目录中的签出。

我刚才遇到的另一种情况是,子模块中存在一个要丢弃的非暂存更改。Git 子模块更新不会删除该更改,也不会在父目录上重置 git。您需要转到子模块目录并执行 git 重置(hard)。因此,如果我想完全放弃父模块和子模块中的非暂存更改,我将执行以下操作:

家长:

git reset --hard


git submodule update

子模组:

git reset --hard

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

 git submodule foreach git reset --hard

Https://kalyanchakravarthy.net/blog/git-discard-submodule-changes/

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

下面的命令帮助了我:

git submodule update --init --recursive

enter image description here

一个更新的可视化遍历-这里我的子模块指向-< strong > 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