Это совершенно нормально.
Когда вы впервые клонируете какой-нибудь репозиторий, вы даете указание вашему Git вызвать другой Git по некоторому URL:
git clone <url>
Ваш Git начинается с созданияновый пустой репозиторий - в нем нет коммитов и веток.Затем он устанавливает remote - обычно имя origin
, которое записывает URL-адрес, который вы дали - и запускает git fetch
.Эта операция извлечения переносит все их коммиты, которых у вас нет, что, конечно, является просто «всеми коммитами», поскольку у вас их еще нет.
В конце процесса извлечения, ваш Git устанавливает все ваши имена для удаленного слежения , 1 origin/*
.Вы получаете одно такое имя для каждого имени ветки в другом Git.Обратите внимание, что на данный момент у вас все еще нет собственных имен веток!
Мы можем нарисовать имена коммитов и удаленного отслеживания обычным способом:
...--o--o--o <-- origin/master
\
o--o <-- origin/develop
и так далее.Каждое отдельное имя указывает на один конкретный коммит, наконечник ветви.
Что нужно сделать, чтобы добавить свои коммиты к одному из нихэто создать ваше собственное имя ветки, указывая на один из этих коммитов.На самом деле, вы должны сделать это, чтобы иметь возможность git checkout <em>somebranch</em>
.Итак, последнее, что git clone
делает, это запускается:
git checkout master
(или, может быть, какое-то другое имя, в зависимости от того, что вы скажете ему проверить в конце).Это вызывает немного магии.
Git просматривает все ваши собственные имена ветвей, которых нет.Не находит master
.Вместо того, чтобы жаловаться на и ничего не делать, ваш Git продолжает просматривать все ваши имена для удаленного слежения .Он ищет тот, который похож на master
, и находит точно один: origin/master
.Таким образом, ваш Git на данный момент создает имя master
и устанавливает его так, чтобы он указывал на тот же коммит как origin/master
:
...--o--o--o <-- master (HEAD), origin/master
\
o--o <-- origin/develop
Теперь, когда имя master
существует, git checkout
может проверить его, и теперь вы находитесь на ветке master
.
Ни одно из других origin/*
имен не использовалось ... еще .Но если вы сейчас выполните:
git checkout develop
, ваш Git проходит тот же процесс: develop
не существует, поэтому он просматривает все ваши имена для удаленного отслеживания и находит origin/develop
.Затем он говорит себе: Ага, вы должны захотеть, чтобы я создал develop
, указывающий на тот же коммит, что и origin/develop
, а затем переключиться на develop
! Итак, он делает это:
...--o--o--o <-- master, origin/master
\
o--o <-- develop (HEAD), origin/develop
На этих рисунках я прикрепляю слово HEAD
к текущей проверенной ветви.Git делает то же самое внутри: вот как Git знает, в какой ветке вы находитесь, и какое имя ветви нужно изменить при добавлении новых коммитов.
Обратите внимание, что нет необходимости создавать новыйимя ветки, пока вы не захотите добавить коммиты к нему .Вы можете проверить конкретную фиксацию по ее хэш-идентификатору или использовать git checkout origin/develop
вместо git checkout develop
.Это дает вам то, что Git называет detached HEAD:
...--o--o--o <-- master, origin/master
\
o--o <-- HEAD, origin/develop
Теперь HEAD
указывает непосредственно на коммит, вместо того, чтобы отмечать имя ветви и позволять имени ветви указывать накоммит.Это нормально, пока вы не сделаете new commits;то вы, вероятно, хотите, чтобы иметь имя ветви, чтобы вспомнить последний такие совершить
1 Это спорно, является ли это также считаются «имена филиалов.».Это, безусловно, имена , и они определяют кончики структурных ветвей в графе коммитов.Но двухсловная фраза удаленные ветви , которую некоторые люди используют для обозначения этих слов, вводит в заблуждение.Это имена в вашем хранилище Git!Git называет их названиями веток удаленного отслеживания , которые используют объединенную строку слов remote + tracking + ветка таким образом, что отличается от других способов, которыми Git использует каждое отдельное слово.Неудивительно, что люди находят Гита сводящим с ума.