忽略 git 子模块的新提交
Posted
技术标签:
【中文标题】忽略 git 子模块的新提交【英文标题】:Ignore new commits for git submodule 【发布时间】:2013-01-03 07:26:43 【问题描述】:背景
在 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
问题
另一方面,master 显示 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 应该完全忽略子模块目录,这样 master 也是干净的:
$ cd /path/to/master/
$ git status
# On branch master
nothing to commit, working directory clean
失败的尝试 #1 - 脏
在文件master/.gitmodules
内如下,根据这个answer:
[submodule "book"]
path = book
url = https://user@bitbucket.org/user/repo.git
ignore = dirty
失败的尝试 #2 - 未跟踪
将master/.gitmodules
更改为以下,根据此answer:
[submodule "book"]
path = book
url = https://user@bitbucket.org/user/repo.git
ignore = untracked
尝试失败 #3 - showUntrackedFiles
将master/.git/config
编辑为以下内容,根据此answer:
[status]
showUntrackedFiles = no
尝试失败 #4 - 忽略
将书籍目录添加到主忽略文件中:
$ cd /path/to/master/
$ echo book > .gitignore
失败的尝试 #5 - 克隆
在master中添加book目录如下:
$ 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 submodule pitfalls 的文章表明这是不恰当的子模块用法?
【问题讨论】:
如果要将存储库链接到另一个存储库的某个版本并跟踪它,通常会使用子模块。但这似乎不是你想要的。您只想在另一个存储库中使用存储库,而不对其进行跟踪。然后不要将其添加为子模块。 @FelixKling,如果您以这种方式添加此类存储库并将其推送到 GitHub,它会为其创建链接而不复制该文件夹的内容吗? @Roland:子模块只是引用其他存储库版本的文件。一旦它们在存储库的本地副本中初始化,它们就会被存储库的实际内容替换。 我认为您正在寻找“ignore = all” 使用 Git 2.13(2017 年第二季度),您将可以考虑git config submodule.<name>.active false
。见my answer below
【参考方案1】:
只要运行:
$ git submodule update
这会将子模块恢复为旧提交(在 parent-repo 中指定),而不会使用最新版本的子模块更新 parent-repo。
【讨论】:
不,不是,它不会改变状态。 为什么 OP 希望不拥有来自book
存储库的最新信息?在这种情况下,我认为您的回答没有任何意义。
@AlexisWilke 如果书籍界面发生巨大变化并且 OP 没有时间在主仓库中进行更改?【参考方案2】:
要包含另一个不需要在其超级存储库中跟踪的存储库,请尝试以下操作:
$ cd /path/to/master/
$ rm -rf book
$ git clone https://user@bitbucket.org/user/repo.git book
$ git add book
$ echo "book" >> .gitignore
然后提交。
如链接git submodule pitfalls article中所述:
... 父模块和子模块之间的唯一联系是存储在父模块提交中的子模块签出 SHA 的记录值。
这意味着子模块不是由其签出的分支或标签保存的,而是始终由特定的提交保存的;该提交 (SHA) 像普通文本文件一样保存到超级存储库(包含子模块的存储库)中(当然,它被标记为此类引用)。
当您在子模块中签出不同的提交 或在其中进行新提交时,超级存储库将看到其签出的 SHA 已更改。这就是您从git status
获得modified (new commits)
行的时候。
要消除这种情况,您可以:
git submodule update
,这会将子模块重置为当前保存在超级仓库中的提交(详见the git submodule
manpage;或
git add book && git commit
将新的 SHA 保存到超级存储库中。
如 cmets 中所述,考虑放弃 book
子模块:将其克隆到超级存储库中,如果不需要将其状态作为超级存储库的一部分进行跟踪。
【讨论】:
哇,现在我明白了,为什么超级模块需要知道子模块的版本。当然,git add book && git commit
是有意义的。我没有意识到git实际上可以确保两个repos是同步的。【参考方案3】:
有两种可以隐藏的更改通知(从 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
选项。最终,一些模块有新的提交被推送。如果有人克隆超级仓库,它会处于子模块的旧状态还是会检查最新的?
使用命令git clone --recursive git@...
您将获得子模块的旧状态。要更新它们,克隆后您需要git submodule foreach "git pull"
之类的东西
不幸的是,ignore = all
选项不会忽略子模块的新提交。我正在运行 git 版本 1.7.1。有什么想法吗?【参考方案4】:
Git 2.13(2017 年第二季度)将添加另一种方式来包含不需要由其父 repo 跟踪的子模块。
在 OP 的情况下:
git config submodule.<name>.active false
请参阅commit 1b614c0、commit 1f8d711、commit bb62e0a、commit 3e7eaed、commit a086f92(2017 年 3 月 17 日)和commit ee92ab9、commit 25b31f1、commit e7849a9、commit 6dc9f01、@987 2017 年 3 月 16 日)Brandon Williams (mbrandonw
)。(由 Junio C Hamano -- gitster
-- 合并,commit a93dcb0,2017 年 3 月 30 日)
submodule
: 解耦 url 和子模块的兴趣目前
submodule.<name>.url
配置选项用于确定是否 给定的子模块是用户感兴趣的。这最终成为 在我们想要检查不同子模块的世界中很麻烦 在不同的工作树或更通用的机制中进行选择 感兴趣的子模块。在工作树支持子模块的未来,将会有多个 工作树,每个可能只需要子模块的一个子集 已签出。 URL(这是可以获取子模块存储库的位置)在不同的工作树之间不应有所不同。
用户也可以更方便地指定组 他们感兴趣的子模块,而不是在他们想要在工作中签出的每个子模块上运行“
git submodule init <path>
” 树。为此引入了两个配置选项,
submodule.active
和submodule.<name>.active
。submodule.active
配置包含一个路径规范,用于指定工作树中应存在哪些子模块。submodule.<name>.active
配置是一个布尔标志,用于指示是否 该特定子模块应存在于工作树中。请务必注意,
submodule.active
的功能不同于 其他配置选项,因为它需要一个路径规范。 这允许用户采用至少两个新的工作流程:子模块可以与前导目录分组,例如路径规范'
lib/
' 将涵盖所有类库模块,让对类库模块感兴趣的人只需设置一次“submodule.active = lib/
”,即可说出“lib/
”中的所有模块都很有趣。 一旦发明了 pathspec-attribute 特性,用户就可以用属性标记子模块来对它们进行分组,从而形成具有属性要求的广泛路径规范,例如':(attr:lib)
',可用于表示任何和所有具有'lib
' 属性的模块都很有趣。 由于.gitattributes
文件,就像.gitmodules
文件一样,被超级项目跟踪,当一个子模块在超级项目树中移动时,项目可以调整哪个路径获取.gitattributes
中的属性,就像它可以调整哪个路径一样path 在.gitmodules
中有子模块。
【讨论】:
如何为现有项目中的子模块找到准确的<name>
?
@ideasman42 阅读 .gitmodules 中的配置应该会有所帮助:***.com/a/12641787/6309
啊,这只是来自.git/config
的值--> [submodule "<name>"]
不适合我。这是我所做的: 1) 使用 --recursive 进行 git clone; 2)将 git config 设置为答案; 3)做git checkout,git pull到checkout最后一个子模块;仍然得到“(新提交)”。
@VonC 在给你发消息之前,我尝试了两种方法(使用现有的 repo 以及新的初始化 repo),对于这两种情况它都不起作用。【参考方案5】:
Nevik Rehnel 的回答对于您所问的问题肯定是正确的:我不想拥有一个子模块,我到底要如何摆脱这种情况?!。
仅当您的master
项目需要book
子模块时,保留它是一个很好的姿态,因为这样其他签出您的项目的用户就可以享受没有任何特殊的git
命令来运行(嗯...有一些特殊的命令可以使用子模块,但总的来说,我认为它仍然更易于管理。)
在您的情况下,您在 book
存储库中进行了更改,并在某个时候提交了这些更改。这意味着您在该子模块中有新提交,它们有一个新的 SHA1 引用。
您需要在主目录中做的是在主存储库中提交这些更改。
cd /path/to/master
git commit . -m "Update 'book' in master"
这会将master
中的SHA1 引用更新为book
存储库中可用的最新版本。因此,此提交允许其他人在提示处签出所有 master
和 book
存储库。
因此,实际上,每当您对子模块进行更改时,您都会再次提交一次。如果您还对 master
存储库中的某些文件进行了更改,则它是半透明的,因为您会同时提交这两个文件。
【讨论】:
【参考方案6】:运行
git submodule update
在根级别。
【讨论】:
仅供任何想知道的人使用。就我而言(和 OP?),这不会改变git status
所说的内容。它仍然认为发生了变化。
克隆别人的答案是非常糟糕的做法以上是关于忽略 git 子模块的新提交的主要内容,如果未能解决你的问题,请参考以下文章
您是不是忽略 .gitignore 中的 git 子模块或将其提交到您的仓库?
git 子模块更新 --init --force --remote