Частичный клон с Git и Mercurial

Можно ли клонировать только одну ветку (или из данного коммита) в Git и Mercurial? Я имею в виду, я хочу клонировать центральное репо, но так как он огромен, я бы хотел получить только часть его и при этом иметь возможность внести свой вклад в мои изменения. Является ли это возможным? Мол, я хочу только с Тэга 130 или что-то подобное?

Если так, то как?

7 ответов

Решение

В Git Land вы говорите о трех различных типах частичных клонов:

  • мелкие клоны: я хочу историю с момента пересмотра X и далее.

    использование git clone --depth <n> <url> для этого, но, пожалуйста, помните, что мелкие клоны несколько ограничены во взаимодействии с другими хранилищами. Вы сможете создавать патчи и отправлять их по электронной почте.

  • частичное клонирование по пути к файлу: я хочу всю историю изменений в некотором каталоге /path,

    Не возможно в Git. С современным Git вы можете иметь редкие проверки, то есть у вас есть целая история, но вы извлекаете (располагаете в рабочей области) только подмножество всех файлов.

  • клонирование только выбранной ветви: я хочу клонировать только одну ветку (или выбранное подмножество ветвей).

    Возможно и

    до git 1.7.10 не все просто: вам нужно будет делать то, что делает клон вручную, т.е. git init [<directory>], затем git remote add origin <url>, редактировать .git/config замена * в remote.origin.fetch по запрашиваемой ветке (вероятно, 'master'), затем git fetch,

    от git 1.7.10 git clone предлагает --single-branch Опция, которая, кажется, была добавлена ​​только для этой цели, и кажется довольно простой.

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

Вы также можете сделать мелкий клон только из выбранного набора ветвей.

Если вы знаете, как люди захотят разбить вещи по пути к файлу (несколько проектов в одном репозитории), вы можете использовать субмодули (вроде svn:externals), чтобы предварительно разбить репо на отдельные клонируемые части.

На ртутной земле вы говорите о трех различных типах частичных клонов:

  • мелкие клоны: я хочу, чтобы история с точки ревизии X и далее использовала расширение remotefilelog
  • частичные клоны по пути к файлу: я хочу, чтобы вся история изменений в каталоге / пути с экспериментальным расширением smallhg, или я хочу, чтобы только файлы в каталоге / пути были в моем рабочем каталоге с экспериментальным редким расширением (поставляется с версии 4.3, см. hg help sparse).
  • частичные клоны по ветке: я хочу всю историю ревизий на ветке Y: используйте clone -r

Если вы знаете, как люди захотят разбить вещи по пути к файлу (несколько проектов в одном репо (позор вам)), вы можете использовать суб-репозитории (вроде svn externals), чтобы предварительно разбить репо на отдельно клонируемые части

Кроме того, что касается "такого огромного, что я хотел бы получить только часть этого": вам действительно нужно сделать это только один раз. Просто клонируйте это, пока вы обедаете, и тогда у вас есть это навсегда. Впоследствии вы можете pull и получить дельты эффективно идти вперед. И если вам нужен еще один клон, просто клонируйте свой первый клон. Где вы получили клон, не имеет значения (а локальные клоны не занимают дополнительного дискового пространства, поскольку они являются жесткими ссылками под крышками).

Выбранный ответ дает хороший обзор, но не хватает полного примера.

Сведите к минимуму объем загрузки и проверки (а), (б):

git clone --no-checkout --depth 1 --single-branch --branch (name) (repo) (folder)
cd (folder)
git config core.sparseCheckout true
echo "target/path/1" >>.git/info/sparse-checkout
echo "target/path/2" >>.git/info/sparse-checkout
git checkout

Периодически оптимизируйте местное хранилище (c)(необязательно, используйте с осторожностью):

git clean --dry-run # consider and tweak results then switch to --force
git gc
git repack -Ad
git prune

Смотрите также: Как работать с большими репозиториями с помощью git.

Этот метод создает неверсионный архив без вложенных репозиториев:

hg clone -U ssh://machine//directory/path/to/repo/project projecttemp

cd projecttemp

hg archive -r tip ../project-no-subrepos

Неверсионный исходный код без вложенных репозиториев находится в каталоге project-no-subrepos.

Что касается Git, то может иметь историческое значение то, что Линус Торвальдс ответил на этот вопрос с концептуальной точки зрения еще в 2007 году в докладе, который был записан и доступен в Интернете.

Вопрос в том, можно ли извлечь из репозитория Git только некоторые файлы.

Tech Talk: Линус Торвальдс на git t=43:10

Подводя итог, он сказал, что одно из проектных решений Git, которое отличает его от других систем управления исходным кодом (он цитирует BitKeeper и SVN), заключается в том, что Git управляет контентом, а не файлами. Следствием этого является то, что, например, diff из подмножества файлов в двух ревизиях вычисляется, сначала беря весь diff, а затем сокращая его только до тех файлов, которые были запрошены. Другое дело, что вы должны проверить всю историю; все или ничего. По этой причине он предлагает разделить слабо связанные компоненты между несколькими репозиториями и упоминает о продолжающихся усилиях по реализации пользовательского интерфейса для управления репозиторием, который структурирован как суперпроект, содержащий небольшие репозитории.

Насколько я знаю, это фундаментальное дизайнерское решение до сих пор яблок сегодня. Супер-проект, вероятно, стал тем, чем сейчас являются субмодули.

Если, как в nobar' ответа , вы репак в частичном клоне Git, убедитесь , что:

      git clone --filter=blob:none --no-checkout https://github.com/me/myRepo
cd myRepo
git sparse-checkout init
# Add the expected pattern, to include just a subfolder without top files:
git sparse-checkout set /mySubFolder/

# populate working-tree with only the right files:
git read-tree -mu HEAD

Что касается локальной оптимизации в частичном клоне, например:

      git clean --dry-run # consider and tweak results then switch to --force
git gc
git repack -Ad
git prune

используйте Git 2.32 (2 квартал 2021 г.), где " " ( ) в частичном клоне излишне ослабленные объекты в пакете promisor до 2.32: исправлено.

См. (21 апреля 2021 г.) Рафаэля Сильвы ( raffs).
(Слияние Junio ​​C Hamano - gitster- в коммите a0f521b, 10 мая 2021 г.)

Фиксацию a643157: избегать ослабления промисорных объектов в частичных клонах

Автор отчета: СЕДЕР Габор.
Помощник: Джефф Кинг.
Помощник: Джонатан Тан.
Подпись: Рафаэль Сильва.

Когда git repack -A -d( manman ) запускается в частичном клоне, вызывается дважды: один раз для переупаковки всех объектов promisor и один раз для переупаковки всех объектов non-promisor.
Последний вызов с --exclude-promisor-objects а также --unpack-unreachable, который освобождает все объекты, неиспользуемые во время этого вызова.
К сожалению, сюда входят объекты-обещания.

Поскольку -d аргумент git repack( man) впоследствии удаляет все незакрепленные объекты также в пакетах, эти только что ослабленные объекты промисора будут немедленно удалены.
Однако в этом дополнительном оттоке диска вообще нет необходимости.
Например, в недавно клонированном частичном репо, которое фильтрует все объекты blob (например, --filter=blob:none), repackзаканчивается распаковкой всех деревьев и фиксацией в файловой системе, потому что каждый объект в данном конкретном случае является промисорным объектом.
В зависимости от размера репо это значительно увеличивает использование диска: в моей копии linux.git каталог объектов увеличил использование диска на 26 ГБ.

Чтобы избежать этого лишнего оттока диска, передайте имена файлов пакетов промисоров как --keep-packаргументы для второго вызова.
Это информирует о том, что объекты promisor уже находятся в безопасном пак-файле и, следовательно, их не нужно освобождать.

Для тестирования нам нужно проверить, был ли ослаблен какой-либо объект.
Однако «свидетельство» (ослабленные объекты) удаляется во время процесса, что не позволяет нам проверить каталог объектов.
Вместо этого давайте научим pack-objectsдля подсчета ослабленных объектов и передачи через trace2, что позволяет проверять события отладки после завершения процесса.
Это новое событие используется в добавленном регрессионном тесте.

Наконец, добавьте новый тест производительности, чтобы оценить влияние этих изменений на производительность (проверено на git.git):

       Test          HEAD^                 HEAD
----------------------------------------------------------
5600.3: gc    134.38(41.93+90.95)   7.80(6.72+1.35) -94.2%

Для более крупного репозитория, такого как linux.git, улучшение еще больше:

       Test          HEAD^                     HEAD
-------------------------------------------------------------------
5600.3: gc    6833.00(918.07+3162.74)   268.79(227.02+39.18) -96.1%

Эти улучшения особенно важны, потому что каждый объект в недавно клонированном частичном репозитории является промисорным объектом.

В Mercurial вы должны быть в состоянии сделать это, используя:

hg convert --banchmap FILE SOURCEDEST REVMAP

Вы также можете захотеть:

--config convert.hg.startrev=REV

Источником может быть git, mercurial или множество других систем.

Я не пробовал, но новообращенный довольно богат.

Другие вопросы по тегам