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

我有一个git子模块(RestKit),我已经添加到我的repo。

我不小心更改了里面的一些文件,我想回到原始版本。为了做到这一点,我试着逃跑

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

不恢复本地修改的文件 如何重置该子模块的内容?< / p >

276600 次浏览

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

如果您希望为所有子模块执行此操作,而不必更改目录,则可以执行

git submodule foreach git reset --hard

你也可以使用递归标志应用到所有子模块:

git submodule foreach --recursive git reset --hard

对我来说,有

git reset --hard

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

git submodule update --init

然后当我执行git status时,它在子模块上是干净的。

按顺序执行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

一个比之前所有答案都更安全的方法:

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

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

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

LIVE从不被故意更新,但是缓存文件或意外可能发生,使repo变得脏。添加到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

自Git 2.14 (Q3 2017)以来,你不必进入每个子模块来执行git reset(就像在git submodule foreach git reset --hard中一样)

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

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

内置/重置:添加——递归子模块开关

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

当用户使用git-reset和请求递归到子模块时, 方法中记录的对象名称将重置子模块 superproject,分离head .

警告:两者的区别:

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

是前者也会重置你的主父回购工作树,因为后者只会重置子模块的工作树

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

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

这对我来说是有效的,包括递归到子模块中(也许这就是为什么你的-f不起作用,因为你在子模块中改变了一个子模块):

git submodule update -f --recursive

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

git submodule foreach 'git checkout master && git reset --hard $sha1'

首先试试这个,就像其他人说的那样:

git submodule update --init

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

git status

如果子模块有更改,请删除它们。验证当你运行“git status”时,你不会看到任何变化。

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

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

git restore . --recurse-submodules

请注意,它只撤销所有本地更改(在存储库中,在所有子模块中)。

但是git reset ...接受target-commit-id作为输入,并且可以将HEAD移动到任何提交。

如果子模块中有更改,则使用

git submodule foreach --recursive git reset --hard

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

git submodule update --init

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

git reset --hard
git submodule update --init

很简单:

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

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