Подмодуль Git с предупреждением "найдено несколько конфигураций"

Сегодня я начал получать новое предупреждение от git, которое раньше не видел в отношении своих подмодулей. Например:

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

Быстрый поиск, похоже, ничего не дал. Я вижу, что предупреждение генерируется здесь, и звучит так, как будто оно может быть связано с рабочими деревьями?

Что именно означает это предупреждение, и каково его разрешение?

2 ответа

Git хранит данные конфигурации для каждого подмодуля в файлах с именем .gitmodules, Этот файл имеет тот же макет, что и .git/config, но в отличие от .git/config, на самом деле совершено. Предупреждение говорит вам, что данные в этом .gitmodules файл подозрительный (подробности см. ниже).

Каждый коммит хранит снимок каждого файла, поэтому каждый коммит, который имеет подмодуль, имеет (как часть этого коммита) .gitmodules файл.1 Проверка этой конкретной фиксации приводит к проверке того, что .gitmodules файл в вашем рабочем дереве, так что вы можете проверить его и при необходимости изменить. Обратите внимание, что после того, как коммит сделан, его снимок .gitmodules является постоянным и доступным только для чтения, поэтому вы не можете исправить ошибку в существующих коммитах, у которых есть неверная версия этого файла, но ошибка является просто предупреждением. Вы можете (и, как правило, должны) исправить это в любых новых коммитах, сделанных вами .gitmodules файл и использование git add .gitmodules,


1 Технически это верно только для правильно сформированного коммита, поскольку коммит может хранить дерево с записью gitlink, но без .gitmodules файл. Это было бы другой ошибкой, хотя.


Что идет в файле конфигурации

Формат файла конфигурации Git в значительной степени заимствует из файлов INI. Вот образец .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

Каждый параметр именует переменную, содержащуюся в разделе, описанном в квадратных скобках. Если раздел только одна часть, как [core]переменные core.filemode и так далее. Если в разделе есть вторая часть, как [remote "origin"]переменные remote.origin.url а также remote.origin.fetch,

Бег git config --local --list превращает вышеуказанную конфигурацию в список переменных и их значений:

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

С помощью git configВы можете манипулировать переменными программно. Но обратите внимание, что возможно, по крайней мере, по формату файла, повторить раздел:

$ 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

Большая часть Git читает эти файлы конфигурации очень линейно, начиная с общесистемного (/etc/git/config или какое-либо другое системное местоположение), затем ваше (для каждого пользователя) ($HOME/.gitconfig или аналогичный), то конфигурация локального репозитория (.git/config). Если вы устанавливаете одну и ту же переменную более одного раза, возможно, повторяя раздел в нескольких файлах конфигурации, обычно последний параметр - это тот, который используется:

[user]
     name = A
     name = B
     email = wrong@example.com
     email = wright@example.com

Ваше имя пользователя и адрес электронной почты здесь будут B <wright@example.com> поскольку более поздняя настройка переопределяет предыдущую.

Однако некоторые переменные накапливаются. fetch настройка для каждого пульта работает, например, так. Если вы положите:

[remote "origin"]
    fetch = +refs/notes/*:refs/notes/*

в вашем $HOME/.gitconfigи ваш репозиторий .git/config имеет remote.origin.fetch установить на обычный +refs/heads/*:refs/remotes/origin/*, ваш git fetch принудительно обновит все ваши собственные ссылки на заметки и ваши обычные ссылки для удаленного отслеживания. (Между прочим, делать это, как правило, нецелесообразно - это может загромождать ваши заметки, если вы их используете. Это всего лишь пример того, что вы можете сделать. Если вы собираетесь это сделать, используйте специальное удаленное имя!)

Предупреждение и как это исправить

Когда код подмодуля работает, он ищет первый:

[submodule "path"]

раздел и читает эти переменные. Если есть второй:

[submodule "path"]

раздел, он игнорирует эти настройки.2 Убедитесь, что второй не используется ни для чего; если нет, удалите его. Если некоторые из его настроек должны применяться, переместите их в первый раздел.

(Идентификатор хеша выходит, потому что git config можно сказать читать .gitmodules непосредственно из коммита или дерева, и код подмодуля делает это, так как настройки модуля необходимы до окончания оформления.)


2 Это небольшое завышение, но исправление - это то же самое.

Отредактируйте свой .gitmodules, убедитесь, что у вас есть 2 субмодуля с разделом [submodule "foo/bar"], Удалить второй.

Другие вопросы по тегам