Быстрейший способ потерять двадцать минут — набрать git pull в папке над вашим репозиторием. Git отвечает fatal: not a git repository (or any of the parent directories): .git, и большинство ответов в сети советует git init — что неверно для трёх из четырёх реальных причин.
Триаж за 60 секунд:
git rev-parse --show-toplevel || ls -a Если репозиторий существует выше, --show-toplevel печатает его корень — не та папка, дело закрыто, cd туда. Если падает и он, та же команда покажет содержимое папки: нет .git в списке — репозитория здесь никогда и не было. Одна команда отделяет две причины, за которыми большинство случаев. Остальная часть поста — про более редкие.
Почему Git пишет «fatal: not a git repository»?
Git находит репозиторий, поднимаясь от текущего каталога в поисках записи .git, и останавливается на первой. Этот подъём ломается ровно четырьмя способами: вы снаружи дерева, каталога .git больше нет, переменная окружения увела поиск в сторону, либо .git есть, но указывает в никуда. По опросу Stack Overflow 2022 года Git стоит примерно на 94% машин разработчиков — ошибка эта общий обряд посвящения. Выучите четыре случая один раз, и перестанут тратиться время и нервы.
(Если с репозиторием всё в порядке и вы пришли отменить коммит, страница Undo Anything in Git собирает все способы починки с этого сайта в одном месте.)
Случай 1: вы не в том каталоге
Самый частый. Две формы:
- Вы сделали
cdв подкаталог —docs/,src/api/— а привычка с другого проекта подсказывает, что корень здесь. Git поднимается, не находит ничего, сдаётся. - Вы склонировали репозиторий и ждали файлы здесь, но
git cloneвсегда создаёт подкаталог с именем репозитория. Checkout лежит уровнем ниже.
git rev-parse --show-toplevel # печатает корень, когда он есть
cd "$(git rev-parse --show-toplevel)" # прыжок туда одной командой Вторая команда навсегда лечит проблему мышечной памяти: работает с любой глубины внутри репозитория.
Случай 2: нет .git — папка никогда не была репозиторием
ls -a не показывает .git. Обычно это:
- ZIP с GitHub. Code → Download ZIP отдаёт только файлы: без
.git, без истории, без remote. Документация GitHub это подтверждает: ZIP-архив содержит лишь снимок кода. - Файлы, скопированные с другой машины или из другого проекта, без скрытого каталога.
- Чистильщик удалил
.gitкак «бесполезную скрытую папку».
Починка: клонировать заново, история вернётся.
cd ..
git clone https://github.com/<user>/<repo>.git git init здесь начинает совершенно новый репозиторий; ничего не возвращается. А куча скопированных файлов обычно тянет за собой неотслеживаемые; git remove untracked files прикроет уборку, когда клон встанет на место.
git initне чинит репозиторий — он создаёт пустой там, где вы стоите.
Случай 3: GIT_DIR экспортирован и ломает все репозитории
Примета: ошибка следует за вами в каталоги, где час назад всё работало. Экспортированный GIT_DIR велит Git смотреть на один фиксированный путь вместо поиска репозитория, и каждый «обычный» каталог становится «not a repository».
env | grep GIT_DIR # GIT_DIR=/какой-то/старый/путь
unset GIT_DIR Если возвращается каждое утро — строка в ~/.bashrc, ~/.zshrc или CI-обёртке его экспортирует. Системы CI ставят GIT_DIR намеренно: внутри пайплайна это правильно, в интерактивном shell — мина.
Случай 4: submodule не инициализирован
Вы заходите в vendor/libfoo/, и Git говорит, что каталог не репозиторий. Он прав: до инициализации каталог submodule — пустая папка со строкой в .gitmodules и без единого checkout.
cat .gitmodules # перечисляет пути submodule
git submodule update --init --recursive Запускайте из корня репозитория, не изнутри submodule — правило подъёма действует и тут, а пустому submodule некуда подниматься.
Случай 5: .git — файл, и его цель исчезла
Worktree и submodule делают .git однострочным файлом: gitdir: /путь/к/настоящему/gitdir. Когда настоящий gitdir удалён (чистка .git/modules, переезд диска), указатель висит, и подъём находит .git, который не отвечает:
$ ls -la .git
-rw-r--r-- 1 you you 35 Sep 28 10:12 .git # файл, а не каталог
$ cat .git
gitdir: ../.git/modules/libfoo git worktree repair # перевязывает worktree со сменившимися путями Если worktree repair не находит цель — gitdir потерян. История submodule живёт в .git/modules/<имя> родительского репозитория; проверьте, что она там, прежде чем хоронить всё.
Симптом → причина → починка
| Симптом | Вероятная причина | Починка |
|---|---|---|
Ошибка в одном проекте, ls -a без .git | ZIP / скопированные файлы | заново git clone |
| Ошибка из подкаталога, корень работает | Вы снаружи дерева | cd "$(git rev-parse --show-toplevel)" |
| Ошибка везде, даже там, где работало | Экспортирован GIT_DIR | unset GIT_DIR, вычистить из профиля shell |
| Ошибка внутри каталога submodule | submodule не инициализирован | git submodule update --init --recursive |
.git — файл, ошибка остаётся | Висячий указатель worktree/submodule | git worktree repair, иначе заново клонировать |
Так когда git init всё-таки верное решение?
Один раз: когда ls -a не показывает .git, а вы и собирались начать здесь новый репозиторий. Запускайте — и следующая команда git add, а не git log.
Во всех остальных случаях это ловушка с подписью. git init на каталог глубже строит вложенный репозиторий без коммитов — и следующий git log ответит fatal: your current branch 'main' does not have any commits yet. Эта ошибка значит: вы только что создали репозиторий там, где стояли, а настоящий — уровнем выше. Уборка хирургическая:
cd вложенный-каталог
rm -rf .git # удаляет только случайный репозиторий, файлы целы Проверьте строку приглашения перед этим rm: он должен выполняться внутри вложенного каталога, никогда — в корне проекта. Затем cd в настоящий корень и подтвердите через git rev-parse --show-toplevel, что Git находит то, что должен был найти с самого начала.
FAQ
Почему git status пишет fatal: not a git repository?
Git ищет каталог .git в текущей папке и во всех родительских. Нет .git нигде вверх по дереву — нет репозитория: обычно вы не в той папке, либо проект приехал без своей истории.
Чинит ли git init ошибку fatal: not a git repository?
Только там, где репозитория никогда не было. init создаёт новый пустой репозиторий и не может вернуть историю откуда-то ещё. Запустите его на каталог глубже — получите вложенный репозиторий без единого коммита.
Как исправить ошибку внутри submodule?
Из корня репозитория: git submodule update --init --recursive. До этого каталог submodule пуст, и Git называет его not a repository.
Почему ошибка появляется в каждом репозитории на машине?
Экспортированная переменная GIT_DIR подменяет поиск репозитория везде. Выполните env | grep GIT_DIR, затем unset GIT_DIR — и уберите её из профиля shell, если она возвращается.
— mrsaynothing
$ Поделиться
$ Следующий гайд — на почту
Одно письмо на пост. Починил — пошёл дальше.
что это?