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

时间:2011-10-24 22:13:15

标签: git git-submodules

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

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

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

我的第一个(可能是天真的)本能是说git reset --hard - 这似乎适用于其他一切。令我惊讶的是,它不适合这种情况。

所以我发现我可以输入git diff,注意子模块指针曾经拥有的SHA ID,然后进入子模块git checkout [SHA ID] ...但是肯定必须是一种更简单的方法吗?

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

7 个答案:

答案 0 :(得分:138)

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

从子模块联系人页面:

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

答案 1 :(得分:18)

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

或者,如果您希望子模块位于顶部仓库指向的版本上,请执行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>)

答案 2 :(得分:4)

在“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上有三个分支,可用于子模块目录中的签出。

答案 3 :(得分:4)

我遇到的另一个案例是,如果要丢弃的子模块中存在未分级的更改。 git子模块更新不会删除该更改,也不会在父目录上git reset --hard。您需要转到子模块目录并执行git reset --hard。因此,如果我想完全放弃父节点和子模块中的非分段更改,我会执行以下操作:

在家长中:

@Override
public int filterOrder() {
    return 10;
}

@Override
public boolean shouldFilter() {
    RequestContext ctx = RequestContext.getCurrentContext();

    if ((ctx.get("proxy") != null) && ctx.get("proxy").equals("foo")) {
        return true;
    }
    return false;
}

在子模块中:

git reset --hard

git submodule update

答案 4 :(得分:1)

这里的答案在某种程度上并没有解决我对子模块的具体问题,所以万一你也遇到过这种情况,请尝试以下方法......

 git submodule foreach git reset --hard

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

答案 5 :(得分:0)

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

以下命令对我有帮助:

git submodule update --init --recursive

答案 6 :(得分:0)

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 commits 刷新。

-Subproject commit 8c3fd8bac3e5a54a20e860fc163d6e67cc03c623
+Subproject commit 0045ea50f1b9710ffde3ab2a9a18c0d4c97bfaed

enter image description here

问题排查

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

enter image description here