Git diff говорит, что подпроект грязный

227

Я только что запустил git diff и получаю следующий вывод для всех моих примерно 10 подмодулей

diff --git a/.vim/bundle/bufexplorer b/.vim/bundle/bufexplorer
--- a/.vim/bundle/bufexplorer
+++ b/.vim/bundle/bufexplorer
@@ -1 +1 @@
-Subproject commit 8c75e65b647238febd0257658b150f717a136359
+Subproject commit 8c75e65b647238febd0257658b150f717a136359-dirty

Что это значит? Как мне это исправить?

mrwooster
источник

Ответы:

268

Как упомянуто в сообщении Марка Лонгаира в Git Submodules Explained ,

Версии 1.7.0 и более поздних версий git содержат раздражающее изменение поведения подмодуля git.
Подмодули теперь считаются грязными, если у них есть какие-либо измененные или неотслеживаемые файлы , тогда как ранее было бы так, если бы HEAD в подмодуле указывал на неправильный коммит.

Значение знака плюс ( +) в выходных данных подмодуля git изменилось, и когда вы впервые сталкиваетесь с этим, требуется некоторое время, чтобы выяснить, что идет не так, например, просматривая журнал изменений или используя git bisect на git. .git, чтобы найти изменения. Пользователям было бы гораздо приятнее ввести другой символ для «в указанной версии, но грязный».

Вы можете это исправить:

  • либо передайте, либо отмените изменения / изменения в каждом из ваших подмодулей, прежде чем вернуться к родительскому репо (где diff больше не должен сообщать о «грязных» файлах). Чтобы отменить все изменения в вашем подмодуле, просто cdв корневой каталог вашего подмодуля и выполнитеgit checkout .

    dotnetCarpenter комментирует, что вы можете сделать:git submodule foreach --recursive git checkout .

  • или добавить --ignore-submodulesв свой git diff, чтобы временно игнорировать эти "грязные" подмодули.

Новое в Git версии 1.7.2

Как Noam комментирует ниже , этот вопрос упоминает, что начиная с git версии 1.7.2, вы можете игнорировать грязные подмодули с помощью:

git status --ignore-submodules=dirty
VonC
источник
2
Также полезно знать: вы все еще можете git commit -aвыполнить, не беспокоясь о добавлении этих изменений. Хотя они отмечены Mспереди, они не окажутся в вашем коммите.
Гитаарик
1
Мне пришлось зайти в каждый грязный подмодуль и запустить git clean -id.
GDP2
1
@ GDP2, который вы можете надеть в одну строку git submodule foreach --recursive git clean -id(сначала для тестирования в резервном репозитории;))
VonC
1
Случай, в котором я продолжал видеть это необъяснимо, происходило то, что я не отслеживал файлы, которых не было в подмодуле .gitignore. Добавление их туда или в мой глобальный список игнорируемых исправлений.
Бен
21

Также удаление субмодуля, а затем запуск git submodule initи git submodule update, очевидно, сделает свое дело, но не всегда может быть целесообразным или возможным.

user1178907
источник
1
Это сработало для меня, когда я преобразовал некоторые существующие папки в подмодули, а затем перенес их на другой компьютер, на котором все еще были старые папки.
Роджер Липскомб
18

Чтобы игнорировать все неотслеживаемые файлы в любом подмодуле, используйте следующую команду, чтобы игнорировать эти изменения.

git config --global diff.ignoreSubmodules dirty

Это добавит следующую конфигурационную опцию в вашу локальную конфигурацию git:

[diff]
  ignoreSubmodules = dirty

Дополнительную информацию можно найти здесь

Devpool
источник
16

РЕДАКТИРОВАТЬ : Этот ответ (и большинство других) устарели; вместо этого посмотрите ответ Девпула .


Первоначально не было опций конфигурации, чтобы сделать " git diff --ignore-submodules" и " git status --ignore-submodules" глобальным значением по умолчанию (но см. Также Установка флагов git default в командах ). Альтернативный вариант - установить ignoreопцию конфигурации по умолчанию для каждого отдельного подмодуля, который вы хотите игнорировать (для обоих git diffи git status), либо в .git/configфайле (только локальный), либо .gitmodules(будет создан git). Например:

[submodule "foobar"]
    url = git@bitbucket.org:foo/bar.git
    ignore = untracked

ignore = untrackedигнорировать только неотслеживаемые файлы, ignore = dirtyтакже игнорировать измененные файлы и ignore = allигнорировать также фиксации. Очевидно, нет способа подстановить его для всех подмодулей.

Ральф Верстейген
источник
13

Это так, потому что указатель на субмодуль у вас не тот, который на самом деле находится в каталоге субмодуля. Чтобы это исправить, вы должны git submodule updateснова запустить :

Робин Рен
источник
9
git submodule foreach --recursive git checkout .

Это не помогло мне, но дало мне список файлов (в моем случае только один), которые были изменены в подмодуле (без того, чтобы я там что-то делал).

Таким образом, я мог перейти к субмодулю, и состояние git показало, что мой HEAD был отсоединен -> мастер git checkout, статус git, чтобы снова увидеть измененный файл, git checkout> filename <, git pull и все снова в порядке.

Самую малость
источник
9

Я закончил тем, что удалил каталог подмодуля и снова его инициализировал

cd my-submodule
git push
cd ../
rm -rf my-submodule
git submodule init
git submodule update
Szymon Wygnański
источник
4
Я бы лучше понял, что случилось, но это было единственное, что сработало для меня ...
smilebomb
6

Подмодуль может быть помечен как грязный, если настройки файлового режима включены, и вы изменили права доступа к файлам в поддереве подмодуля.

Чтобы отключить файловый режим в подмодуле, вы можете отредактировать /.git/modules/path/to/your/submodule/config и добавить

[core]
  filemode = false

Если вы хотите игнорировать все грязные состояния, вы можете установить ignore = dirtyсвойство в файле /.gitmodules , но я думаю, что лучше отключить только файловый режим.

dryobs
источник
1

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

git submodule update --recursive --remote --init

Источники:

Как мне вернуть мои изменения в подмодуль git?

Простой способ получить последние из всех подмодулей git

Адам Уэстбрук
источник