如何将更改恢复到git子模块?


268

我有一个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 

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


如果git reset --hard不起作用,请首先尝试使用指定远程分支git reset --hard origin/<branch_name>
杰里·K

Answers:


208

移至子模块的目录,然后执行a git reset --hard将所有修改的文件重置为它们的最后提交状态。请注意,这将丢弃所有未提交的更改。


6
git子模块更新(即使没有--init)对我也有效,可以在我没有实际更改任何内容时放弃子模块“更改”。如果转到子模块目录,并且git status显示为空,请尝试此操作,而不要重设。
折衷的DNA

16
git submodule update --init为我工作;没有--init它根本不起作用。
Per Lundberg

高超!!我在导入我的仓库中对子模块进行了更改。然后,它又恢复了原来的样子。
Noitidart '16

2
reset --hard不适用于我,由于局部更改,我的子模块仍然无法取消初始化。
malhal's

33
git submodule update -f --init对于我来说,除了@markshiz 。
otiai10

279

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

git submodule foreach git reset --hard

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

git submodule foreach --recursive git reset --hard


7
与尝试将cd插入每个子模块目录相比,这对自动化来说要好得多。
特拉维斯·卡斯蒂略

4
请注意,您可能还想git submodule foreach --recursive git clean -x -f -d
yoyo

1
在我的机器上(使用Git 2.22.0的Windows)在使用--recursive标志时第二个git命令周围需要单引号,否则它将不起作用:git submodule foreach --recursive'git clean -x -f -d'
aatwo

196

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

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

第一个命令完全“解除绑定”所有子模块,然后第二个命令重新签出它们。
它比其他方法花费的时间更长,但是无论子模块的状态如何,它都可以工作。


1
遗憾的是,这在我的情况下不起作用(在git子模块中修改了本地文件),“ update --init”命令error: Your local changes to the following files would be overwritten by checkout
冒出

要更新特定的部分组件做:$ git的子模块DEINIT -f - <submodule_path>然后$ git的子模块更新--init - <submodule_path>
Priyank

我尝试了上面的所有方法,直到获得了这一方法。对我来说,这是唯一一个得到了我的混帐看“清洁”(不*,我PS1git status -uno无法解释)。
Guy Rapaport

60

对我来说,有

git reset --hard

只需将子模块重置为已签出的状态,而不是主模块回购引用的提交/状态所必需的。我仍然会有OP所说的“已修改的内容”。因此,为了使子模块返回正确的提交,我运行:

git submodule update --init

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


遗憾的submodule update --init是,无论如何我似乎都没有恢复本地修改:|
rogerdpack

48

依次执行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

2
唯一对我也有帮助的人。
Victor Sergienko 2014年

问题,如果子模块是新的,则该目录中没有.git文件,对吗?git命令会冒泡到父仓库吗?
圣地亚哥亚利桑那州

1
@jiahut即使这样做,当从父级执行“ git status”时,子模块旁边仍然有“(新提交”)?
David Doria

1
@DavidDoria 对我来说git submodule update是固定的(new commits)
ubershmekel


11

就像其他人所说的,先尝试一下:

git submodule update --init

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

git status

如果您的子模块有更改,请摆脱它们。验证运行“ git status”时看不到任何更改。

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


9

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

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

请参阅Stefan Beller()的commit 35b96d1(2017年4月21日)和commit f2d4899commit 823bab0commit cd279e2(2017年4月18日(通过合并JUNIOÇ滨野- -提交5f074ca,2017年5月29日)stefanbeller
gitster

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

git-reset 是另一个工作树操纵器,应该对子模块进行讲授。

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

警告:之间的区别:

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

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


7

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

git submodule foreach --recursive git reset --hard
git submodule update --recursive --init

3

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

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

2

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

git restore . --recurse-submodules

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


0

我重置所有子模块的方式(无需分离并保留其“ master”分支):

git子模块foreach'git checkout master && git reset --hard $ sha1'

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.