Изменить: есть очень специфическая (и, возможно, специфичная для CentOS) проблема с отдельными каталогами Git и рабочего дерева в очень старой версии Git 1.7.1, используемой здесь, так что для этого конкретного случая --work-tree=/home/marweldc/app
приводит к тому, что Git не может путешествовать туда и обратно между каталогом Git и рабочим деревом. (Другие пути рабочего дерева не вызывают проблемы.)
Git не замечает, что ему не удалось вернуться к пустому репозиторию, а затем он не может ничего сделать с именами веток (поскольку он не может вернуться к репозиторию, он, скорее всего, потерпит неудачу все в эта точка).
Более современный Git, вероятно, вообще не имеет ошибки или заметит невозможность переключения между рабочим деревом и голым репозиторием.
Между тем, указание --git-dir=<path>
, кажется, решает проблему.
Оригинальный (общий) ответ ниже.
Этот:
fatal: You are on a branch yet to be born
означает только то, что он говорит, хотя то, что он говорит, может сбивать с толку. :-) Вы действительно находитесь "на" какой-то еще не существующей ветке.
(Неясно, в какой ветке вы находитесь — у вас может быть «отключенный HEAD», как его называет Git, — но похоже, что у вас больше нет ветки master
, если вы когда-либо были .)
Укороченная версия
Используйте git branch
, чтобы увидеть, в какой ветке вы сейчас находитесь, и какие ветки у вас есть. Используйте git symbolic-ref HEAD refs/heads/master
, чтобы принудительно установить HEAD
голого репозитория обратно в ветку master
. Для другой ветки с именем B используйте refs/heads/B
.
Подробный ответ, то есть, что происходит, следует.
Независимо от того, пустой репозиторий или нет, в нем все равно есть текущая ветвь
В любом обычном не голом репозитории можно посмотреть на какой ветке вы находитесь, запустив git status
. Но git status
просматривает рабочее дерево, поэтому в голом репозитории git status
отказывается запускаться: рабочего дерева нет.
Еще один способ узнать, на какой ветке вы находитесь, — запустить git branch
:
$ git branch
diff-merge-base
* master
stash-exp
Это работает как в голых, так и в не голых репозиториях. *
идет по имени текущей ветки.
Как в обычном репозитории изменить ветку, в которой вы находитесь?
Ответ1: git checkout
. Например, git checkout master
ставит вас (или меня) на master
, а git checkout stash-exp
ставит вас (или меня) на stash-exp
.
1Есть еще один способ — использование команды подключения, но обычно вы не хотите использовать ее, так как это может испортить разницу между текущей фиксацией, индексом и работа-дерево. Но так как голый репозиторий не имеет рабочего дерева, это становится... ну, "безопасный" - это слишком сильно, но можно сказать "гораздо менее опасный".
Как в голом репозитории изменить ветку, в которой вы находитесь?
Ответ по-прежнему git checkout
.
Когда вы извлекаете ветку из пустого репозитория, она использует и изменяет вашу текущую ветку точно так же, как и при извлечении ветки из обычного репозитория.
Конечно, вы не можете git checkout
создать ветку в пустом репозитории, потому что это обновляет рабочее дерево. За исключением того, что вы можете использовать git --work-tree=... checkout ...
. Вы указываете имя ветки для извлечения, и это записывает имя новой ветки в HEAD
, как обычно. Если вы извлекаете фиксацию по хэш-идентификатору, это отсоединяет HEAD
, как обычно.< /эм>
Нерожденные (сиротские) ветки
Но есть еще один особый случай: если вы установите HEAD
на имя ветки, которая еще не существует (как вы сделали бы, например, с git checkout --orphan
), это помещает имя в HEAD
без создания ветки. Это достаточно нормально в обычном (не голом) репозитории, за исключением того, что вы видите это только в двух случаях:
Когда вы впервые создаете новый пустой репозиторий. Вы находитесь на master
, но master
еще не существует. Вы разрешаете эту ситуацию, помещая коммит в репозиторий, который переходит в master
, что создает master
. (Новый коммит является корневым коммитом, т. е. не имеет родительского коммита.)
Когда вы используете git checkout --orphan
: это настраивает вас так же, как когда вы находитесь в новом, пустом репозитории, записывая имя ветки в HEAD
как обычно, но без создания ветки. Вы разрешаете эту ситуацию, записывая новый коммит, который переходит в нерожденную ветку, которая создает ветку, которая сейчас родилась (существует, указывая на новый корневой коммит, который вы только что сделали).
Делать то же самое в голом репозитории
Очевидно, вы не можете сделать это обычным способом в голом репозитории, потому что обычный способ — работать с рабочим деревом, git add
вещей в индекс и git commit
. Голый репозиторий не имеет рабочего дерева. (У него все еще есть индекс, и git checkout
, что вы можете сделать, когда вы задаете рабочее дерево с --work-tree
, по-прежнему записывает сквозь индекс. Это довольно сложно и путается с ловушками развертывания после получения многих людей, поскольку они не понимают индекс.)
То, что вы можете и делаете постоянно, в чистом репозитории — это получение git push
es. Когда вы получаете push, вы принимаете запросы (или команды) от другого Git в форме:
- Пожалуйста, установите вашу ветку
master
для фиксации 1234567
- Удалить ветку
testing
(Вы сами решаете, следует ли и как проверять эти запросы в хуке pre-receive
или update
. Если вы не делаете ничего особенного, вы получаете встроенные проверки Git по умолчанию, которые позволяют любому создавать или удалять любую ветку или тег, но разрешить ускоренную перемотку вперед только для ветвей.)
Предположим, например, что в вашем голом репозитории есть ветка master
, а ветка master
еще не существует. Затем кто-то из Interwebs подключается к вашему серверу и говорит: «Эй, ты, голый репозиторий Git, здесь есть несколько коммитов, а теперь создай ветку master
, указывающую на коммит 1234567
!» В этом случае, предполагая, что вы принимаете этот запрос/команду, как только ваш Git закончит их обслуживание, у вас действительно теперь есть master
. Это приведет вас к:
fatal: You are on a branch yet to be born
to:
On branch master
потому что ваша текущая ветвь master
, которой раньше не было, теперь существует.
Использование сантехнических команд
команды подключения git update-ref
и git symbolic-ref
предназначены для использования в скриптах. Они предполагают, что вы точно знаете, что делаете. (Если вы используете их, не зная, что делаете, вы можете создать беспорядок: у них нет встроенных проверок безопасности.) Второй из них, в частности, заключается в том, как Git внутренне устанавливает HEAD
, чтобы выбрать, на какой ветке вы находитесь. .
Если вы запустите:
git symbolic-ref HEAD refs/heads/branch
это записывает ref: refs/heads/branch
в HEAD
, и теперь вы On branch branch
. Он не обновляет индекс и не обновляет рабочее дерево, но в голом репозитории нет рабочего дерева, и получение push-уведомления не обновляет index, так что это очень похоже на то, что происходит, когда вы получаете push.
Таким образом, это достаточно безопасное занятие. Это позволяет вам изменить ветку, в которой вы находитесь, без использования git checkout
. Это нормальный и правильный, хотя и неудобный — убедитесь, что вы правильно пишете имя ветки и включаете префикс refs/heads/
— способ установить HEAD
в голом репозитории.
person
torek
schedule
24.04.2017
git worktree --list
? - person Mark Adelsberger   schedule 24.04.2017git worktree --list
дает мнеgit: 'worktree' is not a git command. See 'git --help'.
Видимо у меня устаревший гит? - person ralbatross   schedule 24.04.2017git log
в удаленном репо, не означает, что он не пуст? - person ralbatross   schedule 24.04.2017