Почему «git status» показывает, что я нахожусь в основной ветке, а «git branch» нет во вновь созданном репозитории?

83

Я пытаюсь автоматизировать процесс и выдаю git branchкоманду, чтобы узнать, в какой я ветке. Все работает нормально, за исключением недавно инициализированного репо, которое git branchничего не возвращает. Учитывая, что я ничего не сделал с репо, даже начальную фиксацию, я могу принять ответ. Однако, если я запускаю, git statusон сообщает мне, что я нахожусь в masterветке, как показано здесь:

$ mkdir todelete
$ cd todelete
$ git init
Initialized empty Git repository in /u/u70021a/todelete/.git
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)
$ git branch
$

Я делаю что-то неправильно? Есть ли какие-то настройки, которые я неправильно установил?

У меня также есть несколько новых людей в Git, и я не могу объяснить им, почему команда, показывающая, в какой ветке они находятся, ничего не показывает, а команда status показывает.

GOVarney
источник

Ответы:

94

Я поддержал два других ответа, но думаю, что это просто: вы можете быть в ветке, которой не существует. Это нормально и для нового пустого репозитория, потому что для существования имени ветки это имя ветки должно идентифицировать хэш-идентификатор существующей действительной фиксации. В новом пустом репозитории нет коммитов, поэтому имена веток еще не могут существовать.

Тем не менее, вы изначально находитесь в какой-то ветке. Вы находитесь в той ветке, имя которой хранится в специальном имени HEAD. В новом пустом репозитории Git хранит имя master(точнее, refs/heads/masterполное имя ветки) в HEAD, так что вы в нем master, пока masterне существует.

Вы можете изменить используемую несуществующую ветку git checkout -b:

$ git init
Initialized empty Git repository in [path]
$ git checkout -b asdf
Switched to a new branch 'asdf'
$ git checkout -b hello
Switched to a new branch 'hello'

Когда вы находитесь в несуществующей ветке, следующая сделанная вами фиксация создает ветку. Так же и git checkout --orphanработает.

торек
источник
6
Благодарю. Хотя я не согласен с тем, что отображает git. По крайней мере, я понимаю почему. Ваш пример оформления заказа интересен. Согласно документации для "git checkout" -b означает: создать новую ветку с именем <new_branch>, что не совсем верно. В вашем примере на самом деле не создается ни ветка asdf, ни hello. Но они будут, если выполнить коммит. Лично я считаю, что сообщение «На главном узле ветки» следует изменить на «Следующая фиксация на мастере ветки», потому что до тех пор, пока не будет выполнена фиксация, основная ветка не существует.
GOVarney
2
Я не уверен, имеет ли это отношение к вашему случаю или нет, но я хочу указать, что для Git можно вообще не находиться ни в какой ветке.
sklott
Git внутренне использует, cat .git/HEADчтобы узнать, в какой ветке он находится, выяснение того, что ветка существует, потребует больше времени на ЦП и диск, так что, вероятно, поэтому они этого не сделали
Феррибиг
Следует отметить, что вы вообще не должны использовать git branchавтоматизированный процесс, потому что он не предназначен для этого варианта использования. Было бы интересно посмотреть, что показывают здесь не-фарфоровые команды, имеет git symbolic-ref --short HEADли такое же поведение?
Voo
@Voo: git symbolic-refпоказывает имя, содержащееся в HEAD(отсюда ссылка на сиротскую / нерожденную ветку), при условии, что HEADоно не отсоединено. В новом пустом репозитории HEAD его нельзя отсоединить, поскольку отсоединенный HEAD должен содержать хэш-ID существующей действительной фиксации. (В непустом хранилище, с отдельными ГОЛОВАМИ, git symbolic-refвыдает ошибку.)
Торек
23

git branchничего не показывает, потому что ветки нет. Но, как вы можете прочитать man git init:

Эта команда создает пустой репозиторий Git - в основном каталог .git с подкаталогами для объектов, ссылок / заголовков, ссылок / тегов и файлов шаблонов. Также создается начальный файл HEAD, который ссылается на HEAD главной ветви.

Я выделил жирным шрифтом ту часть, которую считаю актуальной - похоже, хотя основной ветки еще нет, ссылка на нее уже существует, и поэтому она показана в git status. При фиксации будет создана соответствующая ветка.

Stanowczo
источник
3
Таким образом, похоже, что «git status» просто отображает «имя ветки», как показано в .git / HEAD (ref: refs / heads / master), но не проверяет согласованность, просматривая .git / refs / Heads, чтобы узнать, не действительно существует.
GOVarney
Я не могу сказать наверняка, так как я не проверял код git, но то, что вы написали, имеет для меня смысл. Но все же я предпочитаю ответ Торека моему :).
Stanowczo
17

Существующие ответы обращаются к буквальному вопросу о том, почему результат такой, какой он есть, но я думаю, что они как бы замалчивают реальную проблему ...

Вы сказали , что вы что - то автоматизировать, поэтому я предположил бы , что ни git statusни git branchявляется лучшим инструментом в контексте сценариев.

Некоторые альтернативы можно найти в этом обсуждении: Как программно определить текущую извлеченную ветку Git

Не зная ваших потребностей (или того, как вы хотите, чтобы будущая ветка вела себя), я не могу дать рекомендации, но я понимаю, что некоторые команды предназначены для взаимодействия с человеком (фарфор), а другие - для сценариев ( сантехника)

Марк Адельсбергер
источник
15

Ветка еще не родилась. Поэтому git branchне показывает его ( git symbolic-ref HEADуказывает, что ваша HEAD указывает на ведущую ветвь по умолчанию и что она еще git branchне родилась, поскольку не показывает ее, т.е. вы можете находиться в ветке, которая еще не существует). Однако фиксация чего-либо создаст ветку.

Это также верно, если вы проверяете orphanветку.

Я предполагаю, что git statusпоказывает имя ветки, поскольку это ветка, которая будет создана.

Для создания сценариев см. Как программно определить текущую извлеченную ветку Git.

MrTux
источник
2

В git ветка по умолчанию master. Когда вы делаете коммит, git будет "использовать" текущую ветку, в которой вы сейчас находитесь. Поскольку вы инициализировали новый репозиторий, вы находитесь в ветке «по умолчанию», и поэтому вы не видите его в списке веток, он появится, как только вы зафиксируете свои изменения.

введите описание изображения здесь

введите описание изображения здесь

CodeWizard
источник
2
Я понимаю ветвление, я не понимаю, почему "git status" говорит, что я нахожусь в несуществующей ветке.
GOVarney