Игнорировать новые коммиты для подмодуля git

83

Задний план

Использование Git 1.8.1.1 в Linux. Репозиторий выглядит следующим образом:

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

Проблема

Мастер, с другой стороны, показывает, что для подмодуля книги есть «новые коммиты»:

$ 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 должен полностью игнорировать каталог подмодуля, чтобы мастер тоже был чист:

$ cd /path/to/master/
$ git status
# On branch master
nothing to commit, working directory clean

Неудачная попытка №1 - грязная

В master/.gitmodulesсоответствии с этим ответом внутри файла находится следующее :

[submodule "book"]
        path = book
        url = https://user@bitbucket.org/user/repo.git
        ignore = dirty

Неудачная попытка №2 - без отслеживания

master/.gitmodulesВ соответствии с этим ответом изменено на следующее :

[submodule "book"]
        path = book
        url = https://user@bitbucket.org/user/repo.git
        ignore = untracked

Неудачная попытка №3 - showUntrackedFiles

master/.git/configВ соответствии с этим ответом отредактировано следующее :

[status]
   showUntrackedFiles = no

Неудачная попытка №4 - игнорировать

Добавлен каталог книг в главный файл игнорирования:

$ cd /path/to/master/
$ echo book > .gitignore

Неудачная попытка №5 - клонировать

Добавлен каталог книг в мастер следующим образом:

$ 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 предполагает, что это неправильное использование подмодуля?

Дэйв Джарвис
источник
3
Обычно вы используете подмодули, если хотите связать репозиторий с определенной версией другого репозитория и отслеживать это. Но это не похоже на то, что вам нужно. Вы просто хотите использовать репозиторий внутри другого, не отслеживая его. Тогда не добавляйте его как подмодуль.
Felix Kling
@FelixKling, если вы добавите такие репозитории таким образом и отправите их на GitHub, создаст ли он для них только ссылку без копирования содержимого этих папок?
Роман Беккиев
@Roland: подмодули - это просто файлы со ссылкой на версию другого репозитория. После инициализации в локальной копии репозитория они заменяются фактическим содержимым репозитория.
Феликс Клинг
2
Я думаю, вы ищете "ignore = all"
greuze
1
С Git 2.13 (второй квартал 2017 г.) вы сможете рассмотреть git config submodule.<name>.active false. Смотрите мой ответ ниже
VonC

Ответы:

60

Чтобы включить другой репозиторий, который не нужно отслеживать в его супер-репо, попробуйте следующее:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://user@bitbucket.org/user/repo.git book
$ git add book
$ echo "book" >> .gitignore

Затем совершите.

Как указано в связанной статье о подводных камнях подмодуля git :

... единственная связь между родительским модулем и подмодулем - это записанное значение извлеченного SHA подмодуля, которое хранится в коммитах родительского модуля.

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

Когда вы проверяете другую фиксацию в подмодуле или делаете новую фиксацию в нем, супер-репо увидит, что его извлеченный SHA изменился. Вот когда получишь modified (new commits)линию от git status.

Чтобы устранить это, вы можете:

  • git submodule update, который сбросит подмодуль до фиксации, сохраненной в настоящее время в супер-репо (подробности см. на git submoduleстранице руководства ; или
  • git add book && git commit чтобы сохранить новый SHA в супер-репо.

Как упоминалось в комментариях, рассмотрите возможность отказа от bookподмодуля: клонируйте его внутри супер-репо, если отслеживание его состояния как части супер-репо не требуется.

Невик Ренель
источник
3
Ух ты, теперь я понимаю, почему супермодуль должен знать версию подмодуля. Конечно, есть смысл делать git add book && git commit. Я не понимал, что git действительно может гарантировать синхронизацию двух репозиториев.
Сергей Оршанский
103

Просто беги:

$ git submodule update

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

Шив Кумар
источник
6
Нет, это не изменит статус.
Эд Бишоп,
Почему именно бы О.П. хочет не иметь последнюю из bookхранилища? Я не думаю, что ваш ответ имеет смысл в этом контексте.
Alexis Wilke
@AlexisWilke, а если интерфейс книги кардинально изменится и OP не успеет внести изменения в главное репо?
Logman
Это тот ответ, который я искал!
LLSv2.0 03
21

Есть два типа уведомлений об изменениях, которые вы можете подавить (начиная с 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опцию для всех подмодулей. В конце концов, в некоторых модулях были добавлены новые коммиты. Если кто-то затем клонирует супер-репо, будет ли он в старом состоянии подмодулей или он будет проверять самые последние?
FelikZ 04
С помощью команды git clone --recursive git@...вы получите старое состояние подмодулей. Чтобы обновить их, вам понадобится что-то вроде git submodule foreach "git pull"после клонирования
greuze
1
К сожалению, ignore = allопция не игнорирует новые коммиты подмодуля. Я использую git версии 1.7.1. Любая идея?
Ромул
10

Git 2.13 (второй квартал 2017 г.) добавит еще один способ включения подмодуля, который не должен отслеживаться его родительским репо.

В случае OP:

git config submodule.<name>.active false

См. Фиксацию 1b614c0 , фиксацию 1f8d711 , фиксацию bb62e0a , фиксацию 3e7eaed , фиксацию a086f92 (17 марта 2017 г.) и фиксацию ee92ab9 , фиксацию 25b31f1 , фиксацию e7849a9 , фиксацию 6dc9f01 , фиксацию 5c2bd8b (16 марта 2017 г.) Брэндона Уильямса ( mbrandonw) .
(Объединено Junio ​​C Hamano - gitster- в фиксации a93dcb0 , 30 марта 2017 г.)

submodule: разделить интерес URL и подмодуля

В настоящее время submodule.<name>.urlпараметр конфигурации используется, чтобы определить, представляет ли данный подмодуль интерес для пользователя. Это становится громоздким в мире, где мы хотим иметь разные подмодули, проверенные в разных рабочих деревьях, или более обобщенный механизм для выбора, какие подмодули представляют интерес.

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

Пользователям также может быть удобно указать группы подмодулей, которые им интересны, вместо того, чтобы запускать " git submodule init <path>" для каждого подмодуля, который они хотят получить в своем рабочем дереве.

Для этого вводятся две опции конфигурации: submodule.activeи submodule.<name>.active.

  • submodule.activeКонфигурации имеют pathspec , что определяет , какой должен существовать подмодуль в рабочем дереве.
    • submodule.<name>.activeКонфигурации является булевой флаг , используемый для указания, что конкретный подмодуль должен существовать в рабочем дереве.

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

  1. Подмодули могут быть сгруппированы с ведущим каталогом, так что путь, например, ' lib/' будет охватывать все модули, похожие на библиотеки, чтобы позволить тем, кто интересуется модулями библиотечного типа, установить " submodule.active = lib/" только один раз, чтобы указать, что все модули в ' lib/' являются интересно.
  2. Как только функция pathspec-attribute будет изобретена, пользователи могут пометить подмодули атрибутами, чтобы сгруппировать их, так что широкая pathspec с требованиями к атрибутам, например ' :(attr:lib)', может использоваться, чтобы сказать, что любые и все модули с libатрибутом ' ' представляют интерес.
    Поскольку .gitattributesфайл, как и .gitmodulesфайл, отслеживается суперпроектом, когда подмодуль перемещается в дереве суперпроекта, проект может регулировать, в какой путь получает атрибут .gitattributes, точно так же, как он может регулировать путь, в котором находится подмодуль .gitmodules.
VonC
источник
Как найти точный <name>вариант для подмодуля в существующем проекте?
ideasman42 03
@ ideasman42 Должно помочь чтение конфигурации в .gitmodules: stackoverflow.com/a/12641787/6309
VonC
Ах, это просто ценность от .git/config->[submodule "<name>"]
ideasman42
1
Не работает для меня. Вот что я делаю: 1) git clone с --recursive; 2) установите git config в качестве ответа; 3) выполните git checkout, git pull для проверки последнего подмодуля; По-прежнему получаю "(новые коммиты)".
У Байцюань
2
@VonC Перед тем, как отправить вам сообщение, я попробовал оба (с существующим репо, а также с новым инициализированным репо), в обоих случаях это не сработало.
Porcupine
3

Ответ Невика Ренеля, безусловно, правильный для того, о чем вы спрашиваете: я не хотел иметь подмодуль, как, черт возьми, мне выйти из этой ситуации ?! .

Только, если вашему masterпроекту требуется bookподмодуль, это хороший жест, чтобы сохранить его как таковой, потому что тогда другие пользователи, которые проверяют ваш проект, могут наслаждаться отсутствием какой-либо специальной gitкоманды для запуска (ну ... есть некоторые специальные команды для использования субмодулей, но в целом, я думаю, управлять им все же проще.)

В вашем случае вы вносите изменения в bookрепозиторий и в какой-то момент фиксируете эти изменения. Это означает, что у вас есть новые коммиты в этом подмодуле, у которых есть новая ссылка на SHA1.

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

cd /path/to/master
git commit . -m "Update 'book' in master"

Это обновит ссылку на SHA1 masterдо последней версии, доступной в bookрепозитории. В результате этот коммит позволяет другим проверять все репозитории master& bookв подсказке.

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

Алексис Вилке
источник
-5

Бежать

git submodule update 

на корневом уровне.

думаю2010
источник
Просто кому интересно. В моем случае (и OP?) Это не меняет того, что git statusговорится. Он по-прежнему считает, что изменения произошли.
squarism
Максим