Git stores per-submodule configuration data in files named .gitmodules
. This file has the same layout as .git/config
, but unlike .git/config
, is actually committed. The warning is telling you that the data in that .gitmodules
file is suspect (see below for details).
Each commit stores a snapshot of every file, so every commit that has a submodule, has (as part of that commit) a .gitmodules
file.1 Checking out that particular commit results in checking out that .gitmodules
file in your work-tree, so that you can examine it and modify it if necessary. Note that once the commit is made, its snapshot of .gitmodules
is permanent and read-only, so you cannot fix the error in the existing commit(s) that have a bad version of this file, but the error is just a warning. You can (and generally should) fix it in any new commits you make, by fixing the .gitmodules
file and using git add .gitmodules
.
1Technically this is only true for a properly-formed commit, as a commit could store a tree that has a gitlink entry, yet lack the .gitmodules
file. That would be a different error, though.
What goes in a configuration file
Git's configuration file format borrows heavily from INI files. Here's a sample .git/config
:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git://git.kernel.org/pub/scm/git/git.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
Each setting names a variable contained within a section, described in square brackets. If the section is just one part like [core]
, the variables are core.filemode
and so on. If the section has a second part like [remote "origin"]
, the variables are remote.origin.url
and remote.origin.fetch
.
Running git config --local --list
turns the above configuration into a list of variables and their values:
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=git://git.kernel.org/pub/scm/git/git.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
Using git config
, you can manipulate the variables programmatically. But note that it's possible, at least by file-format, to have a section repeat:
$ cat foo.conf
[core]
foo = bar
[dave]
hal = ibm
[core]
podbaydoors = closed
$ git config -f foo.conf -l
core.foo=bar
dave.hal=ibm
core.podbaydoors=closed
Much of Git reads these configuration files in a very linear fashion, starting with the system-wide one (/etc/git/config
or some other system-specific location), then your per-user one ($HOME/.gitconfig
or similar), then the local repository's configuration (.git/config
). If you set the same variable more than once, perhaps by repeating a section in several configuration files, typically the last setting is the one that gets used:
[user]
name = A
name = B
email = [email protected]
email = [email protected]
Your user name and email address here will be B <[email protected]>
as the later setting overrides the earlier one.
Some variables, however, accumulate. The fetch
setting for each remote works this way, for instance. If you put:
[remote "origin"]
fetch = +refs/notes/*:refs/notes/*
in your $HOME/.gitconfig
, and your per-repository .git/config
has remote.origin.fetch
set to the usual +refs/heads/*:refs/remotes/origin/*
, your git fetch
will force-update all your own notes references and your usual remote-tracking references. (Doing this is generally inadvisable, by the way—this could clobber your notes, if you are using them. It's just an example of the kind of thing you can do. If you are going to do this, use a special remote name!)
The warning, and how to fix it
When the submodule code is at work, however, it looks for the first:
[submodule "path"]
section and reads those variables. If there is a second:
[submodule "path"]
section, it ignores those settings.2 Make sure that the second one is not being used for anything; if not, remove it. If some of its settings should apply, move them into the first section.
(The hash ID comes out because git config
can be told to read .gitmodules
directly from a commit or tree, and the submodule code does this as the module settings are needed before the checkout finishes.)
2This is a slight overstatement, but the fix is still the same thing.