忽略git子模块的新提交


82

背景

在Linux上使用Git 1.8.1.1。存储库如下所示:

master
  book

子模块的创建如下:

$ cd /path/to/master
$ git submodule add https://user@bitbucket.org/user/repo.git book

book子模块是干净的:

$ cd /path/to/master/book/
$ git status
# On branch master
nothing to commit, working directory clean

问题

另一方面,母版显示book子模块有“新提交”:

$ cd /path/to/master/
$ 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:   book (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")

Git应该完全忽略子模块目录,这样母版也是干净的:

$ cd /path/to/master/
$ git status
# On branch master
nothing to commit, working directory clean

尝试失败1-脏

master/.gitmodules根据此答案,文件内包含以下内容:

[submodule "book"]
        path = book
        url = https://user@bitbucket.org/user/repo.git
        ignore = dirty

尝试失败#2-未跟踪

master/.gitmodules根据此答案更改为以下内容:

[submodule "book"]
        path = book
        url = https://user@bitbucket.org/user/repo.git
        ignore = untracked

尝试失败#3-showUntrackedFiles

master/.git/config根据此答案编辑为以下内容:

[status]
   showUntrackedFiles = no

尝试失败4-忽略

将book目录添加到主忽略文件中:

$ cd /path/to/master/
$ echo book > .gitignore

尝试失败#5-克隆

将书目录添加到母版,如下所示:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://user@bitbucket.org/user/repo.git book

book子模块如何位于存储库下自己的存储库目录中,master而git却忽略了该book子模块?也就是说,不应显示以下内容:

#
#       modified:   book (new commits)
#

git status在主存储库中执行时如何隐藏该消息?

一篇关于git子模块陷阱的文章表明这是不合适的子模块用法吗?


3
如果要将存储库链接到另一个存储库的特定版本,并进行跟踪,通常可以使用子模块。但这似乎不是您想要的。您只想在另一个仓库中使用一个仓库,而无需对其进行跟踪。然后不要将其添加为子模块。
Felix Kling 2013年

@FelixKling,如果您以这种方式添加此类存储库并将其推送到GitHub,是否会为其创建仅链接而不复制该文件夹的内容?
Roman Bekkiev

@Roland:子模块只是引用了另一个存储库版本的文件。一旦在存储库的本地副本中对它们进行了初始化,它们就会被存储库的实际内容替换。
菲利克斯·克林

2
我认为您正在寻找“忽略=全部”
greuze 2014年

1
使用Git 2.13(2017年第二季度),您将可以考虑git config submodule.<name>.active false。请在下面
VonC

Answers:


59

要包括另一个不需要在其超级存储库中跟踪的存储库,请尝试以下操作:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://user@bitbucket.org/user/repo.git book
$ git add book
$ echo "book" >> .gitignore

然后提交。

如链接的git子模块陷阱中所述

...父级和子模块之间的唯一链接是子模块的检出SHA的记录值,该值存储在父级的提交中。

这意味着子模块不是通过其检出的分支或标签保存的,而是始终通过特定的提交保存的;提交(SHA)像普通的文本文件一样被保存到超级仓库(包含子模块的仓库)中(当然,它被标记为这种引用)。

当您在子模块中签出其他提交或在其中进行新提交时,超级仓库将看到其签出的SHA已更改。那是当你modified (new commits)git status

要消除这种情况,您可以:

  • git submodule update,这将子模块复位到目前提交保存在超回购(详见git submodule手册页;或
  • git add book && git commit 将新的SHA保存到超级仓库中。

如注释中所述,请考虑放弃book子模块:如果没有必要将其状态作为超级仓库的一部分进行跟踪,则将其克隆到超级仓库中。


3
哇,现在我明白了,为什么超级模块需要知道子模块的版本。当然,这样做是有道理的git add book && git commit。我没有意识到git实际上可以确保两个存储库是同步的。
Sergey Orshanskiy

101

赶紧跑:

$ git submodule update

这会将子模块还原为旧提交(在parent-repo中指定),而不用最新版本的子模块更新parent-repo。


6
不,不是,它不会更改状态。
Ed Bishop

为什么OP会希望book存储库中获取最新信息?在这种情况下,我认为您的答案没有任何意义。
亚历克西斯·威尔克

@AlexisWilke,如果预订界面发生了巨大变化,而OP没有时间在主存储库中进行更改?
Logman

这是我一直在寻找的答案!
LLSv2.0

21

您可以抑制两种更改通知(从git 1.7.2起)。

第一个是未跟踪的内容,发生在您对子模块进行更改但尚未提交这些内容时。父存储库注意到这些,并且git status相应地报告它:

modified: book (untracked content)

您可以使用以下命令抑制这些:

[submodule "book"]
    path = modules/media
    url = https://user@bitbucket.org/user/repo.git
    ignore = dirty

但是,一旦提交了这些更改,父存储库将再次引起注意并相应地报告它们:

modified:   book (new commits)

如果您也想抑制这些变化,则需要忽略所有更改

[submodule "book"]
    path = book
    url = https://user@bitbucket.org/user/repo.git
    ignore = all

想象一下,我已经ignore = all向所有子模块添加了选项。最终,某些模块具有被推送的新提交。如果有人随后克隆了超级仓库,它将处于子模块的旧状态还是签出最新的子模块?
FelikZ 2015年

使用该命令,git clone --recursive git@...您将获得子模块的旧状态。要更新它们,git submodule foreach "git pull"克隆后您将需要类似的东西
greuze 2015年

1
不幸的是,ignore = alloption不会忽略子模块的新提交。我正在运行git版本1.7.1。有什么主意吗?
罗慕路斯

10

Git 2.13(Q2 2017)将添加另一种方式来包含一个不需要其父仓库跟踪的子模块。

在OP的情况下:

git config submodule.<name>.active false

请参阅Brandon Williams()的提交1b614c0提交1f8d711提交bb62e0a提交3e7eaed提交a086f92(2017年3月17日)和提交ee92ab9提交25b31f1提交e7849a9提交6dc9f01提交5c2bd8b(2017年3月16日(由Junio C Hamano合并--commit a93dcb0中,2017年3月30日)mbrandonw
gitster

submodule:解耦URL和子模块兴趣

目前 submodule.<name>.url config选项用于确定给定子模块是否对用户感兴趣。在我们希望在不同的工作树中签出不同的子模块,或者是采用更通用的机制来选择感兴趣的子模块的情况下,这最终变得麻烦。

将来在工作树支持子模块的情况下,将有多个工作树,每个工作树可能只需要检出子模块的一个子集。
在不同的工作树之间,URL(可以在其中获取子模块存储库)的URL不应相同。

用户可以更方便地指定他们感兴趣的子模块组,而不是git submodule init <path>在他们想要在工作树中检出的每个子模块上运行“ ”。

为此,引入了两个配置选项submodule.activesubmodule.<name>.active

  • submodule.active配置包含一个pathspec,用于指定工作树中应该存在哪些子模块。
    • submodule.<name>.active配置是用来表示该特定子模块,应在工作树存在的布尔标志。

重要的是要注意,它的submodule.active功能不同于其他配置选项,因为它采用pathspec。
这使用户可以采用至少两个新的工作流程:

  1. 子模块可以与前导目录进行分组,这样路径规范(例如' lib/')将覆盖所有类似于库的模块,从而使那些对类似于库的模块感兴趣的人submodule.active = lib/只需设置一次即可,“ lib/”中的所有模块都是有趣。
  2. 一旦发明了pathspec-attribute功能,用户就可以使用属性标记子模块以对其进行分组,这样具有属性要求的广泛pathspec(例如“ :(attr:lib)”)就可以用来表示任何具有' lib'属性的模块都很有趣。
    由于.gitattributes文件就像.gitmodules文件一样被超级项目跟踪,因此当子模块在超级项目树中移动时,项目可以调整获取属性的路径.gitattributes,就像它可以调整子模块进入的路径一样.gitmodules

如何<name>在现有项目中找到确切的子模块?
ideaman42

@ ideasman42读取.gitmodules中的配置应该会有所帮助:stackoverflow.com/a/12641787/6309
VonC

嗯,这只是.git/config->[submodule "<name>"]
ideaman42 '17

1
不适合我。这是我的工作:1)用--recursive进行git clone; 2)将git config设置为答案;3)做git checkout,git pull结账最后一个子模块;仍然得到“((新提交)”)。
吴柏权

2
@VonC在向您发送消息之前,我尝试了两种方法(使用现有存储库以及新的初始化存储库),但在两种情况下均无法正常工作。
豪猪

3

Nevik Rehnel的答案肯定是您所问的正确答案:我不想拥有一个子模块,如何摆脱这种局面?

仅当您的master项目需要book子模块时,这是一个很好的选择,因为这样,其他签出您的项目的用户便可以不必git运行任何特殊命令(嗯...有一些特殊命令可以使用)子模块,但总的来说,它仍然更易于管理。)

在您的情况下,您在book存储库中进行更改,并在某些时候提交这些更改。这意味着您有新的提交在该子模块中,这些具有新的SHA1引用。

您需要在master目录中执行的操作是将这些更改提交到master存储库中。

cd /path/to/master
git commit . -m "Update 'book' in master"

这会将SHA1引用更新masterbook存储库中可用的最新版本。结果,此提交使其他人可以检出提示中的所有masterbook存储库。

因此,实际上,每当您对子模块进行更改时,您都会再次提交一次。如果您同时更改master存储库中的某些文件,则这是半透明的,因为您要同时提交这两个文件。


-5

git submodule update 

从根本上讲。


只为任何想知道的人。就我而言(和OP?),这并没有改变git status说什么。它仍然认为发生了变化。
squarism

克隆别人的答案是非常不好的做法
Maxim
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.