Хорошо, в git более полезно думать немного по-другому.
Git на самом деле не имеет ветвей. Все, что у него есть, - это много коммитов, и между этими коммитами есть родительские отношения. Коммит также может иметь двух родителей (это происходит при слиянии). Не уверен насчет более чем 2 родителей, не видел этого на практике.
"Ветви" в git на самом деле просто указатели на коммиты. Они похожи на понятные человеку псевдонимы для определенного c идентификатора коммита.
Однако, по соглашению, есть много команд, которые автоматически работают с ними. Например, когда вы фиксируете некоторые изменения в ветке, git создает новый коммит с его родительским установленным в том коммите, на который в данный момент указывает ветка. Затем он обновляет эту ветку, указывая на новый коммит.
Теперь, когда вы клонируете репозиторий, git копирует не только все коммиты, но и все ветви. Но вместо того, чтобы сохранять их имена, он меняет их на remotes/origin/<original name>
. Это опять-таки просто соглашение - эти ветви ни в коем случае не являются особенными, это просто ветви с именем в указанном формате c.
Теперь, когда вы будете sh работать с одним из эти ветви локально, традиция требует, чтобы вы сначала сделали локальную копию ветви: git checkout -b my-first-feature --track remotes/origin/my-first-branch
. Для этого также есть сокращение, которое вы можете найти в документации.
Это создает новую локальную ветвь и указывает на тот же коммит, что и на удаленную ветвь. Кроме того, в новой локальной ветке он отмечает, что «эта локальная ветвь отслеживает эту удаленную ветвь». Это имеет значение, когда вы набираете sh и тянете, мы скоро к этому вернемся Обратите внимание, что это все еще локальная операция. Git не связывался с удаленным репозиторием, чтобы увидеть, куда указывает my-first-branch
. Он просто проверяет локальную ветвь remotes/origin/my-first-branch
.
Теперь у вас есть новая локальная ветвь, с которой вы можете играть, как считаете нужным.
Когда вы выполняете операцию pu sh, git подключается к удаленному репозиторию и пытается заставить удаленный my-first-branch
указывать на тот же коммит, что и ваш локальный my-first-branch
. Для этого он загружает все новые коммиты и пытается обновить указатель удаленной ветви. Если на сервере есть новые коммиты (в my-first-branch
), он откажется. Он обнаруживает это, проверяя, является ли коммит, на который указывает ваш локальный my-first-branch
, потомком коммита, на который указывает удаленный my-first-branch
. Если это не так, вы не можете pu sh. Затем вам нужно выполнить операцию извлечения, которая получит все новые коммиты, обновить локальный remotes/origin/my-first-branch
, чтобы он соответствовал серверу, а затем объединить my-first-commit
с remotes/origin/my-first-commit
. Это создает новый коммит, являющийся потомком удаленного my-first-branch
. Теперь вы можете успешно выполнить pu sh.
Существуют и другие способы игры с коммитами, но понять их все проще, если вы будете думать с точки зрения коммитов, а не ветвей. Ветки просто псевдонимы для удобства. Граф фиксации - вот что важно.