Создайте новый git-репозиторий внутри подпапки с помощью git init и игнорируйте в основном git-репо - PullRequest
0 голосов
/ 15 декабря 2018

Я попытался понять подмодуль git.Это кажется сложным (у меня нет опыта работы с субмодулем).Возможно, стоит потратить некоторое время.Но сейчас у меня есть несколько вопросов, связанных с подмодулем git.

На самом деле я пытаюсь:

  • с основным репозиторием, внутри основного репозитория, который я хотел бы создатьновый (под) репозиторий.Итак, что я сделал:
    - сначала) создаю папку (ABC).
    - Второй) в главном хранилище игнорировать папку (ABC).
    - в-третьих) в папке de (ABC), git init (для создания нового хранилища)

Это правильный способ создания вложенного хранилища (или, возможно, в правильном направлении)?

Является ли подмодуль git таким же, как я делал выше?

Заранее спасибо.

1 Ответ

0 голосов
/ 16 декабря 2018

Git не определяет «под-репозиторий», поэтому вы можете определить его так, как вам нравится.

Git действительно определяет, что означает перечисление каталога в .gitignore,и этот конкретный шаблон работает отлично.То, что вы сделали, это установили два репозитория, которые вообще не связаны друг с другом.

В типичной установке эти два репозитория будут жить бок о бок:

$HOME/
      [various dot files, personal files, etc]
      src/
          project-A/
                    .git/
                         [all of Git's files]
                    .gitignore
                    README.md
                    [various files]
          project-B/
                    .git/
                         [all of Git's files]
                    .gitignore
                    README.md
                    [various files]

Все, что вы сделали, это переместились project-B внутрь project-A рабочего дерева .Помните, что любой стандартный репозиторий состоит из трех частей:

  • Сам репозиторий .git, полный файлов, которые Git использует для собственных целей Git.Он содержит основные базы данных Git-репозитория, одна из которых содержит все коммиты и другие объекты Git.В нем есть все файлы, которые нужны Git для выполнения собственных задач Git.(Вы можете посмотреть на эти файлы в любое время, но в целом вам не следует редактировать их напрямую, если вы не знаете, что делаете. Но некоторые из них предназначены для очевидного, в этом случае прямого редактированиякак правило, тоже работает нормально. Возможно, вы захотите просмотреть файл .git/config, например - он имеет довольно простой формат, напоминающий файлы INI Windows. Просмотр файла .git/HEAD также поучителен.)

  • Рабочее дерево , в котором вы выполняете свою реальную работу.Это обычное дерево каталогов, содержащее обычные файлы.Git заполнит его файлами, извлеченными из коммита, чтобы вы могли работать с этими файлами.Здесь вы также можете хранить файлы, о которых Git ничего не знает: эти файлы называются неотслеживаемыми файлами .Git будет жаловаться на них, если вы не перечислите их - или их шаблоны имен - в файле .gitignore, основная функция которого состоит в том, чтобы Git прекратил жаловаться на них (и убедитесь, что вы случайно не поместили их в индекс, длячто, см. следующий пункт).

  • Индекс , где Git сохраняет следующий коммит, который вы собираетесь сделать .В индексе есть копия каждого файла, не замороженного из текущего коммита, готового перейти в следующий коммит.Но эти копии находятся в специальном формате Git-only, как файлы внутри коммитов.Это не обычные файлы, подобные файлам в вашем рабочем дереве.

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

Наличиефайл в индексе - это то, что делает файл отслеживаемым , поэтому файл, который находится в рабочем дереве, но не в индексе, является неотслеживаемым файлом ,Git будет жаловаться на это, как мы только что сказали, если вы не скажете Git не жаловаться на этот файл через запись .gitignore.

Вы можете запустить git add с опцией(например, -a) или аргумент (например, .), который говорит добавить все или добавить много файлов .В этом случае git add проверяет любой неотслеживаемый в настоящее время файл - любой файл, который не в индексе прямо сейчас - по настройкам .gitignore, а не будет добавлятьфайл, так что он останется без отслеживания.

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

Индекс сам по себе является файлом, а иногда и более чем одним файлом, внутри .git, но его стоит перечислить отдельно по двум причинам.Во-первых, это так важно и так в вашем лице, даже если вы не можете увидеть это.Во-вторых, Git теперь поддерживает git worktree add для создания дополнительных рабочих деревьев.Каждое добавляемое вами рабочее дерево имеет свой собственный индекс .То есть индекс и рабочее дерево сопряжены: есть только один репозиторий , и с этим одним репозиторием вы получаете одно дерево индекса и работы бесплатно.Затем вы можете git worktree add второе дерево индекса и работы, затем третье дерево индекса и работы и так далее.Очевидно, что индекс, по крайней мере, логически отличается от самого хранилища, тогда: он связывается с рабочим деревом, а не с хранилищем.

В любом случае, результат вышеупомянутого состоит в том, чтопоместив project-B внутрь project-A, все, что вы сделали, - это проект А, у которого есть тонн игнорируемых файлов:

$HOME/
      [various dot files, personal files, etc]
      src/
          project-A/
                    .git/
                         [all of Git's files]
                    .gitignore                           <-- lists `/project-B/`
                    project-B/
                              .git/
                                   [all of Git's files]  <-- these files are untracked in A
                              .gitignore                 <-- and this is untracked in A
                              README.md                  <-- and so is this
                              [various files]            <-- and all of these
                    README.md
                    [various files]

Это gitсубмодуль вроде того же, что я делал выше?

Не совсем, нет.Это существенно сложнее.Однако создает аналогичную структуру рабочего дерева .

При использовании подмодулей вы фактически связываете в двух репозиториях.Однако эта связь, по сути, односторонняя.

Обычно вы сначала создаете два отдельных, полностью независимых хранилища и заполняете их различными коммитами.Это похоже на параллельную настройку, описанную выше, когда проекты A и B располагаются рядом друг с другом, а не как вложенные, один внутри другого.На самом деле, очень часто вы вообще не создаете проект B: кто-то еще уже уже создал проект B, как, например, необычная библиотека, которую вы хотели бы использовать дляпроделать некоторую работу в вашем новом проекте A. Давайте рассмотрим это в качестве примера, поскольку он не только более распространен, но и того, как его ожидает использовать git submodule - и если вы делаетеСам проект B, вы можете просто начать свой первый удар в проекте B, настроить его на GitHub или где бы вы ни собирались сохранить его для общей доступности, и получить все это, прежде чем приступить к созданию проекта A.

Итак, на данный момент у вас есть проект B, который - давайте предположим - имеет свой главный, общедоступный репозиторий открытого доступа, хранящийся в GitHub по URL git://github.com/someuser/B / ssh://git@github.com/someuser/B / https://github.com/someuser/B.

Теперь вы собираетесь создать проект A. Вы можете использовать GitHub «создать репозиторий», нажимая кнопки, чтобы сначала создать его там, а затем клонировать на свой ноутбук или где бы вы ни работали:

<click some buttons in browser>

git clone <url> A      # so now you have A/README.md and A/.git and so on
cd A

Или вы можете создать егокак пустой на GitHub или даже не создавать его на всех на GitHub, если вам нравится:

mkdir A
cd A
git init

В любом случае, вы сейчас находитесь в каталоге A/, который имеет.git/ подкаталог, содержащий базы данных репозитория, индекс и рабочее дерево.Внутри этого рабочего дерева вы можете создавать и редактировать различные файлы, использовать git add, чтобы скопировать их в индекс, чтобы они переходили к следующему коммиту, а затем запустить git commit, чтобы сделать новые коммиты, которые замораживают содержимое индекса вновый снимок.

Теперь вы готовы ссылка хранилище B, которое все еще является независимым Git-хранилищем, само по себе в хранилище A.при этом вы выбираете один из URL-адресов, по которым находится основная версия репозитория B.Ваш Git запустит git clone, чтобы поместить новый клон хранилища B в ваше рабочее дерево, поэтому вы также должны выбрать путь для проекта B - каталог, в который он войдет, в вашем текущем рабочем дереве.Давайте рассмотрим ssh://github.com/someuser/B здесь как URL и project-B как каталог:

git submodule add ssh://github.com/someuser/B project-B

Your Git теперь запускает git clone, чтобы создать project-B как клон ssh://github.com/someuser/B.Этот клон является обычным клоном практически во всех отношениях.Например, у него есть .git. 1 Мы просто называем его "подмодулем", потому что он используется другим хранилищем Git.Это не должно знать или заботиться об этом - что касается клона B, то это просто обычный клон.

Между тем, тот факт, что A теперь использует клон B, превращает A в то, что Git называет суперпроект .В вашем рабочем дереве A команда git submodule add создаст файл с именем .gitmodules, поместив URL-адрес и путь для подмодуля B в этот файл.Он git add отправит этот файл в индекс А, готовый к следующему коммиту.И, наконец, он git add будет индексировать A специальную запись типа gitlink , используя git add project-B, который является путем для подмодуля B.

Итак, теперь index в A содержит две совершенно новые записи: одну для .gitmodules, которая - если вы посмотрите на копию файла рабочего дерева - теперь перечисляет подмодуль, а одна - для «файла» -действительно, gitlink - с именем project-B.Если вы сейчас запустите git commit в рабочем дереве для проекта A, вы получите новый коммит в базе данных репозитория.В этом новом коммите есть все файлы, которые уже были в индексе (например, README.md и т. Д.), Плюс этот новый файл .gitmodules, плюс эта новая вещь gitlink.


1 В более старых версиях Git этот .git в клоне подмодулей проекта B представляет собой обычный каталог, содержащий базу данных репозитория для этого клона, как и любое обычное рабочее дерево Git-репозитория с базой данных внутри его .git,В современном Git это файл, который сообщает Git, где найти базу данных репозитория .git для клона подмодуля проекта B, которую Git секретирует в каталоге .git для проекта A (то есть в A/.git).Такое скрытие хранилища submodule-B позволяет добавлять рабочие ветви для A к share хранилищу submodule-B, а не просто дублировать его.


Операция подмодуля

Помните, опять же, подмодуль не должен знать, что это подмодуль: это просто обычный, обычный репозиторий Git.Если вы сейчас cd project-B зайдете в рабочее дерево для клона проекта B и запустите git log и git status и различные другие команды Git, все они работают, и они все расскажут вам, что происходит в этом клоне проекта B.

Вы можете работать здесь, если хотите!Тем не менее, есть загвоздка.Суперпроект Git, управляющий рабочим деревом для проекта A, к этому моменту дал команду подмодулю 1232 * Git, находящемуся здесь в рабочем дереве каталога project-B,перейдите в режим detached HEAD .Если вы не знакомы с режимом отключенного HEAD, вам нужно узнать об этом.Если вы знакомы с ним - или после того, как вы ушли и узнали об этом и вернулись сюда - один один конкретный коммит , в котором ваше рабочее дерево подмодуля project-B имеетHEAD отключен - это хэш-идентификатор, который записывается в gitlink в суперпроекте.

Другими словами, когда вы работаете в проекте A и говорите ему иди манипулируйте другим репозиторием Git в проекте.-B каталог , способ, которым проект A Git знает , который обязуется использовать , это искать в gitlink , хранящемся в индексе для проекта A. Скажем, для иллюстрации,что это 0123456....

Если вы делаете перейдете в каталог project-B, вы находитесь в клоне B, и вы можете git checkout любой другой коммит иличетная git checkout a ветвь в B. Это изменяет отсоединенный HEAD или даже присоединяет его к ветке, так что теперь в хранилище B есть другой извлеченный коммит.Допустим, вы делаете это:

cd project-B
git checkout develop
... do some work ...
git add ... some files ...
git commit -m 'do work on B to make it more useful for A'

Вы можете git push новый фиксируется обратно в GitHub, поскольку проект B в конце концов является обычным старым хранилищем.Но теперь коммит HEAD в project-B (каталог рабочего дерева) больше не 0123456..., теперь, скажем, 8088dad....Если вы вернетесь обратно к рабочему дереву проекта A и запустите git submodule status, вы увидите, что управляющий Git A говорит: эй, субмодуль удалился из отсоединенного HEAD, который я хотел, он не включен 0123456... больше!

Это правда, но если это то, что вы хотите , теперь пришло время использовать git add до обновить запись gitlink вИндекс для проекта A:

git add project-B

, например.Теперь index , связанный с рабочим деревом проекта A, вызывает коммит 8088dad... в подмодуле, и если вы запускаете git commit в рабочем дереве проекта A, вы получаете новый коммит для проекта A, которыйговорит следующее:

git commit -m 'update submodule B to 8088dad...'

(Это на самом деле не лучшее сообщение о коммите - лучше сказать, какие функции подмодуля B вы используете сейчас, а не просто «Я переключился на коммит»8088dad "- но это пример, и я даже не знаю , какие функции вы используете.)

Существуют и другие способы танца обновления субмодуля, а затем записив новом коммите в суперпроекте, что суперпроект Git должен дать команду подмодулю Git проверить этот конкретный коммит.Команда git submodule выражает многие из них.Но дело в том, что в репозитории superproject есть коммиты - многие со временем, каждый из которых говорит:

  • Я использую подмодуль из url ...
  • хранится по пути path ...
  • , и когда я его использую, я запускаю субмодуль Git для проверки коммита hash-ID.

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

Summary

Цель git submodule - дать вам возможность указать в вашем суперпроекте Git, что вы зависите от какого-то другого Git-репозитория.Вы записываете URL этого репозитория, который вы хотите, чтобы новые клоны использовали для git clone субмодуля.Вы записываете путь , который вы хотите, чтобы ваш суперпроект Git использовал для сохранения клона.И с каждым коммитом в суперпроекте вы записываете конкретную фиксацию подмодуля для этого субмодуля, чтобы клонировать суперпроект, а затем проверить некоторую конкретную историческую фиксацию в этом клоне, также клонирует субмодуль и проверяет правильную историческую фиксацию в субмодуле-клоне.

Это означает, что суперпроект Git теперь зависит от подмодуля: хотя клон субмодуля:управляется с помощью команд Git суперпроекта (что делает подмодуль своего рода подчиненным), сам суперпроект больше не является независимым.Нужна помощь этого подмодуля Git, чтобы суперпроект чувствовал себя целым.И поскольку подчиненный подмодуль является клоном , это не мешает любому, кто управляет оригинальной версией подмодуля, делать все, что он хочет с этим хранилищем.Это даже включает в себя копирование коммитов из источника клона подмодуля, и если исходные коммиты источника удалили , хэш-идентификаторы, сохраненные в коммитах суперпроекта, теперь бесполезны.

Thэто не значит не делать этого , это просто означает знать, в какие зависимости вы попадаете, когда делаете это. Если вы хотите, чтобы ваш проект А был такимнезависимо от существования проекта B и точных хеш-идентификаторов коммитов, не используйте субмодуль.Если вы согласны с тем, что ваш проект A зависит от проекта B, и вы хотите, чтобы было удобно использовать новые функции из project-B по мере их появления, git submodule хорошо подходит.

...