Всякий раз, когда вы видите:
modified: some-name (modified content)
в git status
выводе, это означает, что ваш Git-репозиторий считает, что каталог с именем some-name
является частью некоторого другого Git репозиторий.(Обратите внимание, что здесь имя подкаталога / папки, some-name
в этом примере, не заканчивается косой чертой.)
Один из способов, который я считаю полезным подумать об этой проблемеэто притворяться, что задействовано несколько Git (потому что они есть): один - ваш Git, работающий в вашем хранилище, а другой в этом случае - Git папки или подкаталога, работающий во втором хранилище Git.,И это - или, по крайней мере, был - второй репозиторий Git, в какой-то момент.
Это повторяется: этот подкаталог / папка действительно был каким-то другимGit репозиторий раньше.Это может или не может все еще быть вторым хранилищем.Более того, ваш собственный Git-репозиторий каким-то образом уже записал присутствие другого Git. Если бы ваш Git-репозиторий не записал это, вы бы увидели:
Untracked files:
(use "git add <file>..." to include in what will be committed)
subgit/
Вместо этого,тем не менее, вы видите:
Changes not staged for commit:
...
modified: subgit (modified content)
Итак, тот факт, что ваш вывод Git репозитория git status
говорит о modified content
или untracked content
означает ваш репозиторий вполне уверен , что этот подкаталог является некоторым другим хранилищем.Ваш репозиторий сообщает об относительном состоянии другого репозитория.
Вы можете получить другую подсказку по этому поводу, если используете git status -uall
или git status --untracked-files=all
(это означает то же самое, -u
- это сокращение от --untracked-files=
): если ваш Git не считает, что подкаталог содержит другое хранилище Git, он заглянет внутрь подкаталога и сообщит вам о каждом файле в каталоге.Если ваш Git убежден, что подкаталог является собственным Git-репозиторием, он не будет заглядывать в него и сообщать о каждом файле, но ваш Git также не скажет «измененный контент» или ««неотслеживаемый контент» вот так.
Что с этим делать, зависит от того, что вы хотите, чтобы произошло в конце
Во-первых, нам нужно поговорить о подмодулях.
Подмодули
Git имеет концепцию под названием submodules .Некоторые люди называют их sob-modules , потому что они заставляют программистов плакать.Essentially Подмодуль по существу означает: Я говорю моему Git записывать информацию о другом хранилище Git.
Теперь подумайте о том, как вы клонируете хранилище Git.Это с одной простой командой: git clone <em>url name</em>
, или, может быть, даже просто git clone <em>url</em>
с результирующим клоном, идущим в имя каталога / папки на основе URL.(При указании аргумента name
выбирается имя каталога / папки вместо того, чтобы указывать URL-адрес.)
Итак, если ваш репозиторий - который мы назовем суперпроектом , поскольку он контролирует некоторые суб-Gits - будет ссылаться на какой-то другой репозиторий, то, что нужно вашему Git:
- URL, который он должен клонировать
- имя каталога / папки, которое следует использовать при клонировании
Эти два фрагмента информации в собственном подмодуле хранятся в файле с именем .gitmodules
в верхнем уровне суперпроекта.
Этот .gitmodules
файл необходим для создания нового клона суперпроекта.Это нужно только в новом клоне!Если у вас уже есть клон, который работает и управляет своими вложенными репозиториями, содержимое .gitmodules
файла больше не имеет значения.
С .gitmodules
или без негоВаш Git также записывает больше о подмодуле
Каждый репозиторий Git состоит из трех частей:
- Git хранит сам репозиторий
.git
.Он содержит несколько баз данных, которые вам не нужно искать в себе. - Git also хранит то, что называется, по-разному, index , staging area или cache .То, как он называется, зависит от того, кто или какая часть Git выполняет вызов, но все три являются именами для одной и той же вещи.
- Git предоставляет вам рабочее дерево .Файлы внутри вашего Git-репозитория хранятся в специальном, замороженном, сжатом формате Git-only.Они не могут быть изменены .Они могут быть добавлены к , как при добавлении большего количества версий файлов, но все они являются просто историческими записями.Поэтому вам нужно место, где вы можете получить в этих файлах, в обычном не-Git формате, и работать с ними и вместе с ними.Это ваше рабочее дерево .
Рабочее дерево часто является частью Git, с которой вы работаете больше всего - ну, естественно, оно прямо в названии, не так ли?не так ли?И все же Git на самом деле не использует рабочее дерево, в некотором смысле.Он помещает в него файлы, которые вы можете использовать;и когда вы запускаете git add
, ваш Git копирует файлы из рабочего дерева в эту вещь в # 2 выше: они входят в index .
Когда Git делает новый коммит, Git использует файлы, которые есть в index .Именно наличие файла в индексе делает файл отслеживаемым в первую очередь.Когда Git заполнит ваше рабочее дерево, используя git checkout
для извлечения коммита, Git сначала заполняет ваш index .В этом индексе происходит все реальное действие Git: в него включаются существующие коммиты, и из него создаются новые коммиты.Так что на самом деле важен индекс, а не рабочее дерево, по крайней мере, насколько новые коммиты идут.Независимо от того, что вы делаете в рабочем дереве, Git действительно обращает внимание только на индекс. Вот почему вы должны постоянно использовать git add
: это копия каждого файла в индекса, который имеет значение для Git.
Короче говоря,ваш индекс содержит то, что войдет в следующий коммит, который вы сделаете .Внутри него есть копия всех ваших файлов в формате «pre-Git-ified», готовом к заморозке навсегда.Вот что делает ваш индекс таким важным.Если вы изменяете файл рабочего дерева, вы должны использовать git add
, чтобы скопировать (и Git-ify) файл, чтобы быть готовым к следующему коммиту.
Итак, для Git важны коммиты, идентифицируемый по их большим уродливым хеш-идентификаторам, которые уникальны: никогда не бывает двух разных коммитов с одинаковым хеш-идентификатором, и индекс , который используется для создания новых коммитов.Вы используете рабочее дерево для выполнения своей работы, но затем вы обновляете индекс вашего Git и заставляете свой Git делать новый коммит из него.
Здесь также снова появляются субмодули.Если ваш Git действует как суперпроект, например, наблюдая за каким-то вложенным Git в некоторой папке с именем subgit/
, тогда ваш Git запишет их идентификатор хита коммитов Git в вашем индексе!
Подумайте об этом немного.Ваш Git не сохраняет файлы своего Git.Ваш Git знает, что если его Git - Git в вашей папке subgit/
- сохранил некоторые файлы в коммите, то идентификатор хэша коммита хорош forever .Этот простой хэш-идентификатор, каким бы большим и уродливым он ни был, уникальным образом идентифицирует всех этих файлов в их сохраненном навсегда виде .Так что вашему Git не нужно для сохранения файлов.Все, что нужно сделать, это сохранить хеш-код их коммита.
это именно то, что делает ваш суперпроект Git.Вместо сохранения файлов - их файлов - ваш Git просто сохранил свой хэш-идентификатор commit в своем индексе.И затем, поскольку он находится в вашем индексе, он также входит в ваши коммиты. С этого момента каждый новый коммит содержит свой хэш-идентификатор. Если вы хотите записать другой хеш-идентификатор, вы говорите им - другой Git, тот, кто контролируетпапка subgit/
- для переключения на другой хэш-идентификатор коммита или для создания нового коммита;и тогда у вас есть ваша запись Git с хеш-идентификатором в вашем индексе, так что ваш следующий коммит имеет правильный хеш-код подпроекта.
Обратите внимание, что всеэто работает даже без файла .gitmodules
. Но если у вас нет файла .gitmodules
, этот суперпроект, который контролирует некоторые другие репозитории Git, работает здесь, но вы не сможете легко его клонировать позже.
Теперь вы должны решить: вам нужен субмодуль или нет?
Если вы хотите субмодулей, ну, вы уже там - или хотя бы на полпутитам.Если у вас есть файл .gitmodules
, в котором содержится хранилище подпроектов, ваш суперпроект уже записывает правильный URL-адрес и имя для будущих клонов.Если нет, то вам, вероятно, следует создать файл .gitmodules
, используя git submodule add
.См. Также Как `git submodule add` Существующий подпозиторий? (Это ответ на вопрос о том, как исправить подпроектный репозиторий, который изначально не был правильно добавлен, но вы делаете хотите использовать в качестве правильного подмодуля.)
Итак, вам нужен подмодуль, и он уже есть в .gitmodules
Учитывая, что вы решили, что do хотитечтобы использовать подмодуль и чтобы все было правильно записано, вам нужно сделать , а не git add subgit
.Как вы уже видели, это ничего не делает!
Вместо этого вам нужно начать новый сеанс, введя cd
в подмодуль, или открыть новое окно, в котором выначать работать в субмодуле, или как угодно.Теперь вы в новом и другом хранилище!Но, о-о, вы, вероятно, находитесь в режиме detached HEAD .
Все нормально: вы можете выбрать работу в этом режиме.Или вы можете запустить git checkout <em>somebranch</em>
, чтобы войти в какую-то ветку, или git checkout -b <em>newbranch</em>
, чтобы создать новую ветку при текущем коммите.Вы должны делать все, что имеет смысл для этого Git-репозитория.
Теперь, когда вы находитесь в этом новом и другом репозитории, вы можете работать как обычно с вашим рабочим деревом.Как только все файлы будут расположены так, как вы хотите, в ветке, которую вы хотите, вы git add
изменили файлы и / или git add
не отслеживали файлы, чтобы скопировать их в индекс.Вы тогда git commit
результат.И теперь у вас есть новый коммит, и вы можете git push
это или что-то еще, что вы делаете с этими коммитами в этом хранилище.
Теперь, когда вы закончили делать новыйкоммит, который содержит обновленные и / или новые файлы в подпроекте, теперь вы можете вернуться к суперпроекту.Вы cd
возвращаетесь к суперобъекту, или закрываете это окно, или что-то еще, и возобновляете работу в суперпроекте.
Теперь все, что вам нужно сделать в суперпроекте, - запустить git add <em>subproject</em>
.Если подпроект называется 1267, просто 1268.Это копирует идентификатор хеша под-репозитория в ваш индекс , так что теперь он готов к фиксации.Добавьте все, что вам нравится, и запустите git commit
, чтобы создать новый коммит, который навсегда заморозит все содержимое вашего индекса.Это сохранит ваши файлы и хеш-идентификатор коммита вашего подпроекта , все из которых были готовы войти в ваш индекс.
Так что вам не нужен субмодуль илиСубгит вообще
Это оЭто немного сложнее, особенно в очень старых версиях Git.Современный Git делает это намного проще.Итак, здесь я собираюсь передать весь ответ на Как мне удалить подмодуль? Обратите внимание, что большинство ответов, включая этот короткий для современного Git , имеют идею, чтовы также собираетесь удалить все рабочее дерево из под-репозитория.Если вы хотите сохранить рабочее дерево, самый простой способ - просто переместить или скопировать его в другое место. Обязательно сохраните файлы, которые были изменены и / или не отслежены , поскольку они, вероятно, не в не фиксируют в под-хранилище!