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


128

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

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

我想还原该指针,以便主仓库和子模块再次同步。

我的第一个(可能是幼稚的)本能是说git reset --hard-似乎对其他所有事情都起作用。令我惊讶的是,它不适用于这种情况。

因此,我确定可以键入git diff,记下子模块指针曾经具有的SHA ID,然后进入子模块,然后git checkout [SHA ID]...但是肯定有一种更简单的方法吗?

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

Answers:


167

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

从子模块的联机帮助页:

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

运行此命令,一切应该很好:

git submodule update

4
不知何故,我需要添加--init。没有它,子模块将保持状态为(new commits)。即使我的子模块已经初始化。
Ambidex

@Ambidex是的,--init在所有这一切中,选项至关重要。由于我的子模块是通过https克隆的,因此系统提示我输入用户名和密码。我进入了两个文件夹,并设置了遥控器以使用ssh协议进行签出。
A-Dubb's

1
如果子模块提交哈希被修改和取消
登台,

可以添加--recursive,因此您无需转到所有子模块
Gaspa79,

21

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

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

另外,git submodule如果没有子模块命令,则将向您显示您指向的提交。如果提交不同步,则提交前面将带有-或+。

如果查看其中包含子模块的树,则可以看到该子模块被标记为commit,而不是其余的斑点或树。

要查看特定提交将什么指向子模块,可以执行以下操作:

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

然后,您可以通过将提交到日志等方式来查看提交或其他任何所需的内容(git-dirgit命令级别的选项使您可以不必通过cd进入子模块):

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

以下命令对我有帮助(我想忽略子模块以及模块中的任何更改):git子模块更新--init --recursive
Rajesh Goel,

6

我刚遇到的另一种情况是,您要丢弃的子模块中是否存在未分级的更改。git子模块更新不会删除该更改,也不会在父目录上git reset --hard。您需要转到子模块目录并执行git reset --hard。因此,如果我想完全放弃父级和子模块中未进行的变更,请执行以下操作:

在家长中:

git reset --hard

git submodule update

在子模块中:

git reset --hard

5

使用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”在提交时显示了sm2子模块,f68bed6但是sm2 在处具有HEAD 5b8d48f。子模块提交上f68bed6具有三个分支,可用于在子模块目录中检出。


感谢DAN,PERFECTO!
亚历克


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.