348

我有一个 git 子模块(RestKit),已添加到我的仓库中。

我不小心更改了其中的一些文件,我想回到源版本。为了做到这一点,我试图跑

Mac:app-ios user$ git submodule update RestKit

但正如您在此处看到的,这不起作用,因为它仍然是“修改后的内容”:

Mac:app-ios user$ git status
...
#   modified:   RestKit (modified content)

甚至

Mac:app-ios user$ git submodule update -f RestKit 

不会还原本地修改的文件。
如何重置该子模块的内容?

4

14 回答 14

334

如果要对所有子模块执行此操作,而无需更改目录,则可以执行

git submodule foreach git reset --hard

您还可以使用递归标志应用于所有子模块:

git submodule foreach --recursive git reset --hard
于 2013-07-26T01:58:28.977 回答
298

比所有以前的答案更安全的方法:

git submodule deinit -f .
git submodule update --init

第一个命令完全“取消绑定”所有子模块,第二个命令重新检查它们。
它比其他方法花费更长的时间,但无论您的子模块的状态如何,它都可以工作。

于 2014-12-11T05:11:06.690 回答
256

移动到子模块的目录,然后执行 agit reset --hard将所有修改的文件重置为上次提交的状态。请注意,这将丢弃所有未提交的更改。

于 2012-06-05T23:57:20.520 回答
75

对我来说,拥有

git reset --hard

只需将子模块重置为它签出的状态,而不需要主的 repo 引用的提交/状态。我仍然会像 OP 所说的那样拥有“修改过的内容”。所以,为了让子模块回到正确的提交,我运行:

git submodule update --init

然后当我这样做时git status,它在子模块上是干净的。

于 2013-12-27T02:19:58.717 回答
54

依次执行 4 个步骤:

git submodule foreach git reset --hard HEAD
git submodule update
git submodule foreach "git checkout master; git pull"
git submodule foreach git clean -f
于 2014-05-15T01:56:34.807 回答
35

这对我有用,包括递归进入子模块(也许这就是你的 -f 不起作用的原因,因为你在子模块中更改了一个子模块):

git submodule update -f --recursive
于 2017-07-23T12:06:08.943 回答
19

首先尝试一下,正如其他人所说:

git submodule update --init

如果这不起作用,请切换到子模块目录并使用以下命令查看子模块是否有任何更改:

git status

如果您的子模块有更改,请删除它们。确认运行“git status”时看不到任何更改。

接下来,返回主存储库并再次运行“git submodule update --init”。

于 2019-12-09T19:44:15.953 回答
15

如果要丢弃整个存储库中的所有更改以及子模块,可以使用:

git restore . --recurse-submodules

这将撤消在存储库和子模块中所做的所有更改。

于 2020-05-12T12:08:41.687 回答
10

自 Git 2.14(2017 年第三季度)以来,您不必进入每个子模块来执行git reset(如git submodule foreach git reset --hard

那是因为 git reset 本身现在知道如何递归地进入子模块。

请参阅Stefan Beller ( )的提交35b96d1 ( 2017 年 4 月 21 日)和提交 f2d4899提交 823bab0提交 cd279e2(2017 年 4 月 18 日) 。(由Junio C Hamano 合并 -- --提交 5f074ca中,2017 年 5 月 29 日)stefanbeller
gitster

内置/重置:添加 --recurse-submodules 开关

git-reset是另一个工作树操纵器,应该教它有关子模块的知识。

当用户使用 git-reset 并请求递归到子模块时,这会将子模块重置为超级项目中记录的对象名称,从而分离 HEAD。

警告:两者之间的区别:

  • git reset --hard --recurse-submodule
  • git submodule foreach git reset --hard

是前者还将重置您的主要父回购工作树,因为后者只会重置子模块工作树。
所以谨慎使用。

于 2017-05-29T19:23:52.677 回答
7

对于 git <= 2.13,这两个命令结合起来应该使用递归子模块重置您的 repos:

git submodule foreach --recursive git reset --hard
git submodule update --recursive --init
于 2017-06-21T07:28:24.903 回答
5

很简单:

cd /path/to/submodule/root
git submodule update -f --init  .

大多数答案都建议重置所有子模块,我认为这不是最好的方法,因为它们可能会有合法的变化。

于 2021-04-13T03:57:16.470 回答
3

这适用于我们运行 GIT v1.7.1 的库,其中我们有一个 DEV 包 repo 和 LIVE 包 repo。存储库本身只不过是为项目打包资产的外壳。所有子模块。

LIVE 永远不会有意更新,但是可能会发生缓存文件或事故,从而使存储库变脏。添加到 DEV 的新子模块也必须在 LIVE 中初始化。

DEV 中的包存储库

在这里,我们想要提取我们尚未意识到的所有上游更改,然后我们将更新我们的包存储库。

# Recursively reset to the last HEAD
git submodule foreach --recursive git reset --hard

# Recursively cleanup all files and directories
git submodule foreach --recursive git clean -fd

# Recursively pull the upstream master
git submodule foreach --recursive git pull origin master

# Add / Commit / Push all updates to the package repo
git add .
git commit -m "Updates submodules"
git push   

LIVE 中的包存储库

在这里,我们想要提取提交到 DEV 存储库的更改,而不是未知的上游更改。

# Pull changes
git pull

# Pull status (this is required for the submodule update to work)
git status

# Initialize / Update 
git submodule update --init --recursive
于 2015-08-23T17:48:41.223 回答
3

如果您的子模块发生变化,请使用

git submodule foreach --recursive git reset --hard

如果您的更改是远程子模块更改,则使用

git submodule update --init

如果这些更改已提交,则使用

git reset --hard
git submodule update --init
于 2020-07-08T10:34:55.360 回答
2

我重置所有子模块的方法(分离并保留它们的master分支):

git submodule foreach 'git checkout master && git reset --hard $sha1'
于 2017-08-25T20:57:49.587 回答