Как эффективно использовать git fetch из мелкого клона

Мы используем git для распространения операционной системы и поддержания ее в актуальном состоянии. Мы не можем распространять полный репозиторий, так как он слишком велик (> 2 ГБ), поэтому мы использовали мелкие клоны (~ 300 МБ). Однако недавно при выборке из неглубокого клона теперь неэффективно извлекается весь репозиторий размером> 2 ГБ. Это непосильная трата полосы пропускания для развертываний.

В документации git говорится, что вы не можете получать данные из неглубокого репозитория, хотя это строго неверно. Существуют ли какие-либо обходные пути, позволяющие git clone --depth 1 получать только то, что из него изменилось? Или какая-то другая стратегия, чтобы сохранить размер распределения как можно меньше, имея при этом все биты, необходимые git для обновления?

Я безуспешно пытался клонировать из --depth 20, чтобы увидеть, будет ли он обновляться более эффективно, но это не сработало. Я также изучал http://git-scm.com/docs/git-bundle, но это кажется создавать огромные связки.


person hendry    schedule 14.10.2013    source источник
comment
но это, кажется, создает огромные связки: только для первого. После этого вы можете создавать инкрементные пакеты.   -  person VonC    schedule 14.10.2013
comment
Мое начальное распределение не может быть огромным ...   -  person hendry    schedule 14.10.2013
comment
Вам придется снова попытаться выполнить выборку для вашего мелкого клона с помощью Git 1.9 / 2.0 (первый квартал 2014 г.): эти операции теперь намного эффективнее. См. мой ответ ниже   -  person VonC    schedule 19.01.2014
comment
Git 2.5 (второй квартал 2015 г.) поддерживает фиксацию одной выборки! Я отредактировал свой ответ ниже, теперь ссылаясь на Извлечь конкретную фиксацию из удаленного репозитория git.   -  person VonC    schedule 08.06.2015


Ответы (5)


--depth - это вариант git fetch. Я вижу, что документ на самом деле не подчеркивает, что git clone выполняет выборку.

Когда вы выполняете выборку, два репозитория обмениваются информацией о том, у кого что есть, начиная с голов удаленного и выполняя поиск в обратном направлении последнего общего коммита в истории извлеченных ссылок, а затем заполняя все недостающие объекты, чтобы завершить только новые коммиты между самые последние общие коммиты и недавно полученные.

--depth=1 выборка просто получает подсказки веток, а не предыдущую историю. Дальнейшие выборки этих историй будут извлекать все новое с помощью вышеупомянутой процедуры, но если ранее извлеченные коммиты не вошли в недавно извлеченную историю, выборка извлечет все это - если вы не ограничите выборку с помощью --depth.

Ваш клиент выполнил выборку глубины = 1 из одного репо и переключил URL-адреса на другое репо. По крайней мере, один длинный путь предков в ссылках этого нового репо, по-видимому, не имеет никаких коммитов ни с чем, что в настоящее время находится в вашем репо. Возможно, это стоит изучить, но в любом случае, если нет какой-либо особой причины, ваши клиенты могут просто выполнять каждое извлечение --depth=1.

person jthill    schedule 16.10.2013
comment
Как вы можете видеть в моем тесте, я жестко сбросил настройки до a26424, который находится в удаленном github.com/Webconverger/webc/commit/master. Поэтому я не понимаю, почему он просто не загружает все новое. Как я могу сравнить удаленные ссылки? git ls-remote показывает только теги / ветки ... - person hendry; 16.10.2013
comment
Вы поменяли репо. У вас есть десять веток и семнадцать тегов в этом новом репо, и по крайней мере один из них ссылается на давнюю родословную, не имеющую общих коммитов с какой-либо историей в вашем репо. - person jthill; 16.10.2013
comment
Итак ... IIUC, я должен удалить ветки / теги на github.com/webconverger/webc ( новое репо), чтобы убедиться, что все общее с, скажем, a26424? - person hendry; 16.10.2013
comment
Или загрузите только те ссылки, которые вы хотите (чтобы установить значения по умолчанию, см. ['Remote. ‹Name› .fetch](https://www.kernel.org/pub/software/scm/git/docs/git-fetch.html#_named_remote_in_configuration_file) entry in fetch` обсуждение того, как настроить пульты дистанционного управления). - person jthill; 16.10.2013
comment
IIUC --depth 1 - это правильный путь, хотя мы не реализовали его, так как мой коллега обнаружил ошибку, которая теперь исправлена ​​в github.com/git/git/commit/ Итак, мы ждем от github, будет ли он развернут, и тогда мы будем его использовать. - person hendry; 17.10.2013
comment
Это может быть проще всего. С неограниченным refspec вы все равно получите 27 коммитов в первый раз. Вы проверили, что общего в старых и новых репозиториях, а что нет? - person jthill; 17.10.2013
comment
На самом деле я не понял, как легко проверять общие или исключенные ссылки. Какие-нибудь советы? - person hendry; 21.10.2013
comment
git ls-remote сообщит вам все ссылки пульта дистанционного управления, git branch -a и git tag сообщат вам все те, которые у вас есть. - person jthill; 21.10.2013
comment
git fetch -v -v -v Я нашел, кстати, очень полезным - person hendry; 23.10.2013

Только что сделал g clone github.com:torvalds/linux, и это заняло так много времени, что я просто пропустил CTRL+C.

Потом сделал g clone github.com:torvalds/linux --depth 1, и он клонировал довольно быстро. И у меня есть только одна фиксация в git log.

Так что clone --depth 1 должно работать. Если вам нужно обновить существующий репозиторий, вы должны использовать git fetch origin remoteBranch:localBranch --depth 1. Он тоже работает, он получает только одну фиксацию.

Подводя итоги:

Исходный клон:

git clone git_url --depth 1

Обновление кода

git fetch origin remoteBranch:localBranch --depth 1
person Waterlink    schedule 22.10.2013
comment
Я хотел бы добавить глубину в конфигурацию, чтобы я мог использовать git fetch origin без необходимости запоминать фильтр глубины. Это возможно? - person artfulrobot; 21.02.2015
comment
Да, вы можете создать псевдоним. Вот руководство по псевдониму в git: git-scm.com / book / en / v2 / Git-Basics-Git-Aliases - person Waterlink; 21.02.2015
comment
У меня сработало только это решение (--unshallow не работает). Ключ был branch:branch - person FractalSpace; 17.02.2017

Обратите внимание, что Git 1.9 / 2.0 (первый квартал 2014 г.) может быть более эффективным при извлечении неглубокого клона.
См. совершить 82fba2b, от Нгуен Тай Нгук Дуй (pclouds):

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

Все подробности приведены в shallow.c: 8 шагов для выбора новых коммитов для .git/shallow.

Вы можете увидеть последствия в таких коммитах, как 0d7d285, f2c681c, и c29a7b8, которые поддерживают клонирование, send-pack / receive-pack с / из мелких клонов.
https://github.com/git/git/commit/16094885ca94f72abc28a915f9aa4021e203a16d.
Вы можете даже клонировать из неглубокого репо.

Обновление 2015 г .: git 2.5+ (второй квартал 2015 г.) позволит даже выборку за одну фиксацию! См. Извлечение определенной фиксации из удаленного репозитория git.

Обновление 2016 (октябрь): git 2.11+ (4 квартал 2016 г.) позволяет получать:

person VonC    schedule 19.01.2014

Если вы можете выбрать конкретную ветку, это может быть еще быстрее. Вот пример использования основной ветки Spark и последнего тега:

Первоначальный клон

git clone [email protected]:apache/spark.git --branch master --single-branch --depth 1

Обновление до определенного тега

git fetch --depth 1 origin tags/v1.6.0

Таким образом становится очень быстро переключать теги / ветвь.

person Martin Tapp    schedule 07.01.2016

Я не знаю, подходит ли это вашей настройке, но я использую полное клонирование репо в отдельном каталоге. Затем делаю неглубокий клон из удаленного репозитория со ссылкой на локальный.

git clone --depth 1 --reference /path/to/local/clone [email protected]/group/repo.git 

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

Также я обнаружил, что в некоторых случаях, когда пульт сильно изменился, клон начинает получать слишком много данных. Тогда хорошо его сломать и обновить эталонное репо (которое, как ни странно, занимает гораздо меньше полосы пропускания, чем вначале), а затем снова запустить клон.

person Rajish    schedule 22.10.2013
comment
Я пробовал вашу команду с несколькими параметрами и без них, и получаю что-то вродеfatal: reference repository '[email protected]/group/repo.git' is shallow. - person user2284570; 03.04.2015
comment
Вы не можете использовать неглубокий репозиторий / клон в качестве ссылки. Это должен быть клон полной глубины. - person Rajish; 05.04.2015
comment
Вы имеете в виду, что я не могу использовать--depth 1? - person user2284570; 05.04.2015
comment
Не для справочного репозитория. - person Rajish; 07.04.2015