Почему я не могу оттолкнуться от мелкого клона?

git clone --depth опция команды говорит

--depth <depth> 
Create a shallow clone with a history truncated to the specified number of revisions. 
A shallow repository has a number of limitations 
(you cannot clone or fetch from it, nor push from nor into it),
 but is adequate if you are only interested in the recent history of a large project with a long history,
 and would want to send in fixes as patches. 

Почему мелкие клоны имеют это ограничение? Почему это рабочий процесс только для исправлений?

Для некоторых рабочих процессов проекта мне нужно передать только последний коммит из одной ветви в кодировщик, а затем дать им возможность push их (перемотка вперед) разработки на главный сервер. Это частично для обеспечения безопасности, защиты IP и размера репо, а также для уменьшения путаницы, которую большой репо может принести наивному кодеру. Есть ли рабочий процесс git, который позволяет это?


Обновление: на основании ответа Карла Билефельда git checkout --orphan должен быть правильный ответ. Но все еще нужно "клонировать" эту ветвь в одиночку новому пользователю и уметь эффективно ее продвигать.

Страница руководства гласит:

git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>] --orphan

Создать новую сиротскую ветвь с именем <new_branch>начал с <start_point> и переключиться на это. Первый коммит, сделанный в этой новой ветке, не будет иметь родителей, и он станет корнем новой истории, полностью отсоединенной от всех других ветвей и коммитов.

Индекс и рабочее дерево настраиваются так, как если бы вы ранее выполняли git checkout <start_point>, Это позволяет вам начать новую историю, которая записывает набор путей, похожих на <start_point> легко бегать git commit -a сделать корневой коммит.

Это может быть полезно, когда вы хотите опубликовать дерево из коммита без раскрытия его полной истории. Возможно, вы захотите сделать это, чтобы опубликовать ветвь проекта с открытым исходным кодом, чье текущее дерево является "чистым", но чья полная история содержит проприетарные или иным образом обремененные биты кода.

Если вы хотите запустить отключенную историю, которая записывает набор путей, который полностью отличается от одного из <start_point>, затем вы должны очистить индекс и рабочее дерево сразу после создания сиротской ветви, выполнив git rm -rf . с верхнего уровня рабочего дерева. После этого вы будете готовы подготовить новые файлы, заново заполнить рабочее дерево, скопировав их из другого места, распакуя архив и т. Д.

Ссылка VonC на комментарии Junio ​​интересна. Я думаю, что руководство должно обеспечить руководство в этом случае и позволить правильную команду [например, clone <branch> --options], чтобы извлечь только соответствующую часть репо. Очевидно, вероятность push успех увеличивается благодаря наличию нескольких связанных коммитов и SHA1 в нижней части истории, которые блокируют сопоставление репо.


Обновление Git 1.9.0: заметки о выпуске 14 февраля '14.

"Извлечение из мелко клонированного репозитория раньше было запрещено, главным образом потому, что соответствующие пути кода не подвергались тщательной проверке, и мы не беспокоились о поддержке такого использования. Этот выпуск пытается разрешить передачу объекта из мелко клонированного репозитория более контролируемым образом. (то есть получатель становится мелким хранилищем с усеченной историей)."

Это хорошая новость для мелких клонеров. Далее - узкие клоны возможно.

2 ответа

Как говорит Джунио С. Хамано (главный сопровождающий Git):

Разве правило не более или менее похоже на:

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

Обновление 2014: см. " Является ли git clone --depth 1 (неглубокий клон) более полезным, чем кажется?": Это ограничение будет снято с Git 1.9!

Обновление 2015: с Git 2.5+ вы даже сможете получить один коммит. См. " Извлечение определенного коммита из удаленного репозитория git".


Оригинальный ответ (август 2011 г.):

На самом деле, если подумать, это намного сильнее, чем "не может вычислить общее".

История может выглядеть так:

          R---R---R
         /
  --R---R---X---X---S---S---S

где S коммиты у вас есть в вашем мелком хранилище, и R это коммиты, которые существуют в репозитории, который получает ваш толчок.
Поскольку ваша история мелкая, ни одно хранилище не имеетX"это коммиты, которые должны существовать для того, чтобы история хранилища получателей была полной; получатель не мелкий для начала, и мы не хотим делать его мелким.

Если вы клонировали некоторое время назад, работали без связи с другой стороной, в то время как другая сторона развивалась, И если бы прогресс другой стороны включал перемотку и перестройку истории, вы бы увидели похожую топологию.
Самый левыйS"на изображении выше, возможно, был верхушкой ветви, когда вы мелко клонировали с глубиной 1, и с тех пор удаленный конец, возможно, отбросил три верхних коммита и восстановил свою историю, которая ведет к самой правой"R".
В таком случае подталкивание к пульту HEAD не удастся.


Так что это может работать в некоторых случаях, но это не поддерживается:

Если я должен что-то сказать по этому поводу...

  • Я думаю, что "не поддерживается" - это краткий способ дать достаточно хорошую информацию, но он будет работать только для умных людей.

  • Не все умны; некоторые сами пробуют это, видят, что операция, кажется, работает для их ограниченного числа испытаний, и решили, что она будет работать большую часть времени.
    И они поздравляют свой собственный интеллект с тем, что он говорит "большую часть времени", а не "всегда".
    И они расстраиваются, когда видят, что это не работает, даже если их предупреждают.


Для получения дополнительной информации о процессе обновления мелкого клона см. " Как обновить мерзкий клон git?".

Есть ли рабочий процесс git, который позволяет это?

Да, это отправить исправления в виде исправлений. git format-patch специально разработан, чтобы включить это. Это называется рабочий процесс "привратник", если вы хотите, чтобы Google для более подробной информации. Трудно поверить в то, что организация обеспокоена "безопасностью и защитой ИС", поскольку ваша организация еще не использует нечто подобное, когда один человек или небольшая группа отвечают за проверку "ненадежных" изменений, прежде чем они внесут их в реальную сборку.


Исходя из вашего комментария, теперь у меня есть лучшее представление о ваших требованиях. Я бы порекомендовал создать сиротскую ветку (см. Git checkout --orphan), с какой бы точки вы ни хотели, чтобы ваши разработчики запускались. Клонируйте только эту ветвь в другое хранилище, доступное для этих разработчиков, и пусть они обычно клонируют, толкают и извлекают из этого репо.

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

Это немного сложнее, чем обычно, но это цена, заплаченная за дополнительную изоляцию.

Я нашел обходной путь с помощью пакетов git.

Это решение будет реплицировать те же самые коммиты в другой репозиторий, как "git push", и не потребует перебазирования или приведет к изменению идентификатора фиксации.

К сожалению, для этого требуется shell-доступ (например, ssh) к целевому хосту.

Покажу решение на примере.

Сначала нам нужно получить неглубокий клон в демонстрационных целях.

Давайте загрузим выпуск v0.5.0.0 с одной фиксацией из https://github.com/skarnet/s6-rc в новый репозиторий в качестве мелкого клона.

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

Поэтому не стесняйтесь заменять следующие сопоставления переменных, используя другой URL-адрес и другой выпуск.

В нашем примере неглубокий клон можно создать с помощью:

$ url=https://github.com/skarnet/s6-rc
$ rel=v0.5.0.0
$ git init ${url##*/} && cd ${url##*/}
$ git pull --depth=1 "$url" $rel:master

Это создаст подкаталог "s6-src" (при использовании вышеуказанных значений переменных), содержащий новый клон.

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

$ b=$rel.gbnd
$ git bundle create $b HEAD

Это создаст файл v0.5.0.0.gbnd с использованием ранее установленных переменных оболочки.

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

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

$ url=https://github.com/skarnet/s6-rc
$ rel=v0.5.0.0
$ git init ${url##*/} && cd ${url##*/}
$ c=`git bundle unbundle $b | cut -d " " -f 1`; echo "$c"
$ git tag $rel $c # optional: create a tag for the imported commit.
$ git reset --hard $c
$ git fetch --depth=1 .

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

Также обратите внимание, что вы можете опустить "git init", если репозиторий уже существует.

Это оно!

Однако последние инструкции применимы только для обычных расчетов.

Возможно, вы захотите импортировать неглубокий комплект клонов в "чистый" репозиторий.

В этом случае вместо этого сделайте следующее:

$ url=https://github.com/skarnet/s6-rc
$ rel=v0.5.0.0
$ cd ${url##*/}.git
$ c=`git bundle unbundle $b | cut -d " " -f 1`; echo "$c"
$ git tag $rel $c
$ git fetch --depth=1 . $rel
Другие вопросы по тегам