фатальный: не git-репозиторий: '.' - PullRequest
0 голосов
/ 22 марта 2019

У меня есть действительное хранилище git с именем /tmp/A.Когда я cd на /tmp/A и запускаю любую команду git из bash, она работает хорошо, но когда я запускаю git команды из callCommand, вызываю в программе на haskell, я получаю ошибку:

fatal: Not a git repository: '.'

Если я введу callCommand pwd и ls -la перед командой git, например:

callCommand $ "pwd; ls -la; git status"

Это показывает, что оно находится на правильном пути /tmp/A, а ls показывает, чтохранилище существует и имеет каталог .git, но git возвращает ошибку.

Что я делаю не так?

Upd.

ls вывод

drwxrwxr-x 11 xxx xxx 4096 Mar 22 11:44 .
drwxrwxr-x  3 xxx xxx 4096 Mar 22 11:44 ..
drwxrwxr-x  8 xxx xxx 4096 Mar 22 11:44 .git
-rw-rw-r--  1 xxx xxx  270 Mar 22 11:44 .gitignore
drwxrwxr-x  7 xxx xxx 4096 Mar 22 11:44 dir2
drwxrwxr-x  8 xxx xxx 4096 Mar 22 11:44 dir1
drwxrwxr-x  9 xxx xxx 4096 Mar 22 11:44 test

Upd.Upd.

Неудачная программа вызывается из ловушки post-receive клонированного репозитория git.Когда запустить ту же программу не из ловушки этого хранилища, он работает нормально.Почему само клонирование репозитория из хука не работает?

1 Ответ

1 голос
/ 22 марта 2019

TL; DR: вы, вероятно, хотите, чтобы unset GIT_DIR был в начале вашего сценария (хорошо, однако Haskell выполняет эту операцию).


Проблема здесь в том, что, хотя /tmp/A является разумным Git-репозиторием, сам фактический репозиторий находится в подкаталоге .git. Таким образом, /tmp/A/ - это рабочее дерево , а /tmp/A/.git - это собственное хранилище .

При нормальной работе мы запускаем git <em>subcommand arguments ...</em>, например, git status или git commit -m <em>message</em> из наших рабочих деревьев . Рабочее дерево содержит каталог .git или, в некоторых случаях, файл 1 a .git. Команда верхнего уровня git проверяет наличие .git, находит его и сообщает ага, хранилище равно ./.git. Или он не находит .git, поэтому он смотрит на один уровень вверх, например, с /tmp/A он поднялся бы на один уровень до /tmp сам и проверил там .git. Это повторяется до некоторой точки остановки. 2

Во всех случаях этот процесс поиска должен либо успешно завершиться - путем нахождения собственного хранилища, либо git <em>subcommand</em> умрет с сообщением fatal: Not a git repository .... Теперь приходит критический и скрытый на виду, секретный: На этом этапе команда верхнего уровня git устанавливает переменную среды с именем GIT_DIR для хранения пути к действительному хранилищу. It затем запускает подкоманду, которая использует $GIT_DIR для поиска хранилища. В нашем обычном сценарии использования, где мы находимся в /tmp/A, а /tmp/A содержит каталог .git, это устанавливает $GIT_DIR в /tmp/A/.git, и все подкоманды работают.

Но в вашем случае $GIT_DIR уже установлен. В частности, он установлен на .. Так что теперь команда git верхнего уровня прекращает поиск . Он только проверяет, что $GIT_DIR является действительным, и называет репозиторий Git, либо умирает с сообщением об ошибке fatal. Так как /tmp/A не является хранилищем - это действительно /tmp/A/.git - это вызывает проблему.

Сброс переменной среды снова включает поиск, устраняя проблему. Вы также можете использовать --git-dir в качестве аргумента или установить правильное значение в $GIT_DIR. Обратите внимание, что те же правила применяются с $GIT_WORK_TREE: аргумент --work-tree устанавливает $GIT_WORK_TREE, и если вы не используете его, а $GIT_WORK_TREE не установлен , то интерфейс * 1082 Команда * использует свой , взбирающийся по дереву файловой системы в каталог .git или код файла , чтобы найти корень вашего рабочего дерева. Поэтому, если $GIT_DIR или $GIT_WORK_TREE установлены при запуске git <em>subcommand</em>, Git подчиняется им, если вы не переопределите их с помощью --git-dir и / или --work-tree.

Крючки всегда имеют $GIT_DIR набор. Также они могут иметь или не иметь $GIT_WORK_TREE. Большинство из них работают на верхнем уровне рабочего дерева, но, как и документация githooks заметки, pre-receive, update, post-receive, post-update и push-to-checkout все работают в $GIT_DIR.


1 Уловка .git -as-a-file используется и подмодулями, и добавленными рабочими деревьями в современном Git. Git 1.7 и более ранние 1.8 оставили подмодули со встроенными каталогами .git и не поддерживают добавленные рабочие деревья.

2 Очевидная остановка - достижение /, когда некуда подняться. Однако Git по умолчанию осторожен, по крайней мере, в Unix и Unix-подобных системах, чтобы избежать лазания по точке монтирования . Точки монтирования позволяют вам объединять различные слои файловой системы и / или пулы хранения в единую древовидную иерархию. Обычно /tmp сама по себе может быть файловой системой памяти, например, и большие системы могут изолировать «системное хранилище» (/ и т.п.) от «пользовательского хранилища» (/home). Docker использует точки монтирования для реструктуризации файловых систем в образе Docker и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...