Для git submodule status
:
$ git submodule status
hash-1 path-1 (describe-output-1)
hash-2 path-2 (describe-output-2)
:
hash-n path-n (describe-output-n)
Это говорит вам, для каждого пути субмодуля, идентификатор ha sh фиксации, который был извлечен в пределах этого пути субмодуля, и результат выполнения git describe
внутри этого подмодуля. Например, если вы увидели
51ebf55b9309824346a6589c9f3b130c6f371b8f foo (v2.25.0-462-g51ebf55b93)
в качестве вывода, но затем сделали git checkout v2.15.0
в каталоге foo
:
(cd foo; git checkout v2.15.0)
и запустили его снова, вы бы см .:
+cb5918aa0d50f50e83787f65c2ddc3dcb10159fe foo (v2.15.0)
вместо. (Знак +
указывает, что он не синхронизирован; см. Ниже.)
Идентификатор ha sh является просто результатом выполнения git rev-parse HEAD
в каждом подмодуле. Выходные данные описания - это просто результат запуска git describe
в каждом подмодуле. Путь в середине - это аргумент, который вам нужно указать для команды cd
(change-directory), чтобы переключиться с суперпроекта на данный подмодуль.
Для git submodule summary
подробности немного сложнее. Это, в основном, запускает git log
в каждом подмодуле.
Основы подмодулей
Помните, что подмодуль - это не что иное, как другой Git репозиторий - тот, который Git вызывает подмодуль - плюс немного клея в этом Git хранилище, которое Git вызывает суперпроект . «Клей» в суперпроекте состоит из очень небольшого числа элементов:
Информация, необходимая для git clone
подмодуля, хранящаяся в файле с именем .gitmodules
. Это используется, только когда вы сначала указываете суперпроекту Git сделать этот клон, например, через git submodule update --init
.
имя пути подмодуля, как это появляется в суперпроекте. Суперпроект Git создаст пустой каталог / папку (какой бы термин вы ни выбрали) для хранения рабочего дерева для этого подмодуля. 1
A совершить га sh ID . Суперпроект Git примет этот коммит с идентификатором ha sh и, по сути, запустит (cd <em>path</em>; git checkout <em>hash</em>)
, чтобы перевести подмодуль Git в режим detached HEAD , с этой конкретной фиксацией.
Эти два последних элемента хранятся в каждом новом коммите, который вы делаете в суперпроекте (и уже сохранены в существующих коммитах). 2 Для get сохранено, имя пути и фиксация ha sh ID должны храниться в Git в index , потому что Git делает все новые коммиты из индекса.
( Если вам неясно различие между Git index и вашим рабочим деревом , см. В чем разница между HEAD, рабочим деревом и индексом, в Git? и Что означает git -rm под рабочим деревом и индексом? .)
1 В современном Git, .git
для подмодуля, который появится в этом пути, является обычным файлом, содержимое которого будет путем, по которому подмодуль Git можно найти хранилище. Суперпроект Git выведет базу данных хранилища из подмодуля. Git называет это поглощением подмодулем. В более старых версиях Git подмодуль будет иметь собственную директорию .git
/ папку, содержащую базу данных репозитория подмодуля Git.
2 Фактически, первый элемент - файл .gitmodules
- также должен присутствовать во всех этих коммитах, но, поскольку это обычный файл, в этом нет ничего особенного: вы просто работаете с ним, как с любым обычным файлом. Поскольку суперпроекту действительно требуется , он только один раз, при клонировании подмодуля, если вы случайно или намеренно пропустите его из новых коммитов, вы не заметите, пока кто-то другой не попытается использовать этот коммит в качестве отправной точки для клона super sh суперпроекта.
Так как изменить a .gitmodules
файл довольно редко, и он переносит коммиты иначе, как и любой другой файл, это редко проблема. Это в основном проблема, только если вы создаете субмодуль, используя в первую очередь что-то отличное от * 1102. *
Чтение gitlinks, а не связывание непосредственно с субмодулем
Сверхпроектный объект, который записывает и путь, и идентификатор sh, готовый к go в вашем следующем коммите, называется gitlink . Он существует только в индексе Git, поэтому его очень трудно увидеть. (Вы можете вывести содержимое индекса, используя git ls-files --stage
, но обычно это слишком многословно.) Но оно всегда есть: здесь говорится , чтобы использовать этот коммит, извлечение, как отдельный HEAD , this ha sh ID в this подмодуле .
Предположим, что есть подмодуль по пути sub
(в индексе, как :sub
или :0:sub
- номер здесь - промежуточный слот). Когда вы делаете коммиты в суперпроекте, эта ссылка превращается в коммиты. Вы можете прочитать его из индекса:
git rev-parse :sub
или прочитать из текущего коммита:
git rev-parse HEAD:sub
или прочитать из любого коммита:
git rev-parse <hash>:sub
чтобы получить сохраненный gitlink ha sh ID для sub
из данного коммита ha sh -ID.
Если вы запустите git submodule update
в своем суперпроекте, то Git сделает соответствующий (cd sub; git checkout <hash>)
в зависимости от того, какой идентификатор ha sh находится в индексе прямо сейчас. Это git checkout
, если репозиторий подмодулей «чистый», чисто проверит этот конкретный коммит.
Но каждый подмодуль является репозиторием a Git - рабочим деревом, индекс и базовая база данных хранилища. Вы можете cd sub
и git checkout
, что хотите, или испачкали его индекс (sub
) и / или его рабочее дерево. И этот подмодуль может иметь свои собственные имена веток - это репозиторий Git, и каждый репозиторий Git имеет имена веток, верно? Предположим, вы cd sub; git checkout master
, например. Теперь этот подмодуль в ветви , а не в режиме detached HEAD . Вы можете делать новые коммиты, запускать git merge
и / или выполнять все виды других команд. Вы можете получить новые коммиты из некоторого верхнего хранилища. Вы можете делать все, что захотите: это Git репозиторий со всеми доступными Git командами.
Предположим, что вы что-то сделали - не имеет значения, что - для некоторых Git хранилище, которое действует как подмодуль для какого-то суперпроекта. Теперь вы возвращаетесь к суперпроекту (cd ..
) и в суперпроекте, вы спрашиваете его: какой коммит вы порекомендовали проверить? То есть вы читаете gitlink запись в суперпроекте, из индекса суперпроекта или из коммита.
У вас есть два идентификатора ha sh. Они могут быть одинаковыми! Может быть, master
в подмодуле - это идентификатор ha sh, хранящийся в gitlink суперпроекта. Или, может быть, они разные. Если вы только что сделали новый коммит в подмодуле, он определенно отличается, потому что каждый новый коммит ha sh ID является уникальным.
Если они разные, git submodule status
выведет +<hash>
; ha sh, который он печатает, - это тот, который фактически проверен в sub
. Если они совпадают, он печатает (одиночный) идентификатор ha sh без +
.
Между тем, если вы запустите git submodule summary
, ваш суперпроект Git:
- захватывает рекомендуется га sh ID
- захватывает фактически проверено га sh ID
- использует
git log
в подмодуле, чтобы найти, какие коммиты находятся «между» этими двумя идентификаторами ha sh.
В частности, он использует git log --oneline --left-right <hash1>...<hash2>
(обратите внимание на --oneline
и три точки здесь; он также вызывает еще несколько вариантов, но они являются ключевыми). Значение hash1
- это рекомендуемое га sh, а значение hash2
- , фактически проверенное га sh. Результатом этого списка является отображение коммитов, которые доступны с hash1
, но не hash2
(с префиксом <
) и коммитов, которые доступны с hash2
, но не hash1
(с префиксом >
).
(Подробнее о достижимости см. Think Like ( а) Git.)
git submodule summary
: --files
против --cached
Я также не могу понять значение --files
опция
Параметр --files
используется по умолчанию. Опция --cached
изменяется, когда git submodule summary
получает два идентификатора ha sh. Вместо получения первого га sh из индекса (:sub
), а затем перехода в подмодуль и считывания значения HEAD
для второго он считывает первый идентификатор из текущего коммита (HEAD:sub
) и получает секунду из индекса (:sub
). Остальная часть его работы такая же: введите подмодуль и запустите git log
с соответствующими параметрами.