忽略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.active和 submodule.<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引用更新master为book存储库中可用的最新版本。结果,此提交使其他人可以检出提示中的所有master&book存储库。

因此,实际上,每当您对子模块进行更改时,您都会再次提交一次。如果您同时更改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.