Ошибка 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 дней гарантии