Git submodule warning 'multiple configurations found'
Asked Answered
W

2

11

Today I started getting a new warning from git that I haven't seen before regarding my submodules. For example:

warning: <hash_omitted>:.gitmodules, multiple configurations found for 'submodule.foo/bar'. Skipping second one!

A quick search didn't seem to return anything relevant. I see that the warning is generated here, and sounds like it may be related to worktrees?

What exactly does this warning signify, and what is the resolution of it?

Watchdog answered 16/8, 2018 at 18:15 Comment(0)
S
7

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.

Shadbush answered 16/8, 2018 at 20:30 Comment(6)
Excellent explanation, torek. I'm running into this same error as the OP, however my repo's .gitmodules does not have any dupes. Still scratching my head, and will provide an alternate answer if I get past this..Greeley
@Greeley There was a bug in one version of Git (2.17 or 2.19 maybe? I forget) that was kind of similar, where it complained about just about every submodule all the time, which was fixed quite quickly afterward but was annoying. My memory of this one is fuzzy (we ran into it at work and having found that it was just a one-release Git glitch, just updated Git) and I think it had different error messages, but it's worth checking whether it occurs with a newer Git.Shadbush
I am also seeing same message, but without apparent duplicates in .gitmodules . Fit version is git 2.25.1 However, this repo has submodules, that have submodules them selves. (do not ask). Could that message appear if one submodule appears in .gitmodules of master, and as well in .gitmodules of some submodule?Cowen
Same here, I'm seeing the message with Git 2.30.2 and without any duplicates in .gitmodules. @DavorinRuševljan As far as I understand, submodules are identified by path so you cannot have the same submodule appearing at two different paths. If the same remote repository is used in multiple locations as a submodule, I think that shouldn't be a problem.Locoism
@DavorinRuševljan: a submodule-of-submodule shouldn't interfere with the "outer" layer submodules, but the warning could appear for the sub-sub-module if that's where it's hiding.Shadbush
I also had no duplicates in .gitmodules. The "fix" was not to try to rebase, but to simply pull: git pull origin master instead of git pull --rebase origin master.Paniculate
B
1

Edit your .gitmodules, verify that you have 2 submodules with the section [submodule "foo/bar"]. Remove the second one.

Burmaburman answered 16/8, 2018 at 20:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.