Yandex Metrika
sanches.free 1 просмотр

Ошибка shallow update not allowed в Git: неглубокий клон и push в новый remote

Что происходит

Сообщение shallow update not allowed обычно появляется при попытке отправить в другой удалённый репозиторий ветку, полученную из неполной истории. У принимающей стороны нет гарантий, что цепочка коммитов согласована с полным деревом; сервер не обязан сливать «обрезанную» историю с нуля в новый bare-репозиторий.

Типичная цепочка действий: в каталоге с уже существующим деревом выполняют git remote add для нового URL и затем git push — и получают отказ, если локальная копия была неглубокой.

Откуда берётся shallow

Клон с ограничением глубины задаётся флагом --depth N: скачиваются только последние N коммитов от указанной ветки. Для быстрой выборки на CI или короткого ознакомления с проектом это нормально, но такая копия не претендует на полноту истории.

Пример (имя удалённого и URL замените на свои): git clone https://example.com/org/repo.git --depth 15. Пушить изменения обратно безопасно в тот же самый remote, с которого клонировали и где лежит полная история; проблемы начинаются при переносе в другой хост без предварительной «распаковки» истории.

Как проверить, shallow ли текущий репозиторий

В логе в режиме от старых коммитов к новым (git log --reverse или с пагером) у «искусственного» корня может появляться пометка grafted — признак того, что родители за пределами скачанной глубины недоступны.

В Git 2.15 и новее достаточно одной команды; для старых версий смотрите наличие файла shallow внутри каталога .git (путь можно получить через git rev-parse --git-dir).

git rev-parse --is-shallow-repository
test -f "$(git rev-parse --git-dir)/shallow" && echo "shallow file present" || echo "no shallow marker file"

Если есть доступ к исходному remote с полной историей

Добавьте или оставьте remote на тот сервер, где история полная, и выполните распаковку:

git fetch --unshallow имя_remote

После успешного fetch репозиторий перестаёт быть shallow; дальше можно снова настраивать push в новый удалённый URL. Подставьте имя того remote, откуда тянете полную историю (часто origin или отдельный алиас для старого сервера).

Если старого сервера уже нет

Самый прямой путь — новый репозиторий без старой истории

Если полную историю взять неоткуда и важна только текущая рабочая копия, можно удалить метаданные Git и инициализировать репозиторий заново: история коммитов пропадёт, зато не останется ограничения shallow. Перед rm -rf .git убедитесь, что несохранённых правок нет и что вы осознанно жертвуете историей.

Оставить только доступные коммиты, но убрать признак shallow

Иногда помогает переписать первый доступный коммит так, чтобы он стал корнем без «прививки» к недоступным родителям: интерактивный rebase от корня, у первого коммита действие edit, затем пустое исправление и продолжение. Это тонкая операция; делайте на копии и осознавайте, что полную прошлую историю вы всё равно не восстановите.

git rebase -i --root
git commit --amend --no-edit
git rebase --continue

На шаге rebase в списке для самого нижнего коммита замените pick на edit, сохраните файл и следуйте подсказкам Git во всплывающем редакторе. После успешного завершения проверьте снова git rev-parse --is-shallow-repository и при необходимости лог на отсутствие grafted у «нового» корня.

На что смотреть в продакшене

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

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии