TL;DR резюме
В целом нас интересуют две или три вещи:
- Что произойдет, если вы запустите
git fetch
без дополнительных аргументов?
- Что произойдет, если вы запустите
git merge
или git rebase
без дополнительных аргументов?
- Что произойдет, если вы запустите
git pull
без дополнительных аргументов?
Краткий ответ на вопрос № 1: Git выбирает один из ваших пультов для загрузки, а затем извлекает данные с этого пульта. Удаленный выбор Git происходит из настройки remote = name
в разделе [branch]
. Если такой настройки нет, Git использует origin
.
Ответ на вопрос № 2: Git выбирает какое-то имя для использования, как если бы вы запустили git merge name
или git rebase name
. name
основан на настройке merge = ref
в разделе [branch]
, но принцип его работы несколько неясен: если в этом же разделе, например, указаны remote = origin
и branch = refs/heads/master
, имя, которое Git выбирает для использования, не master
, а скорее origin/master
. Если он говорит remote = origin
и branch = develop
, Git выбирает имя origin/develop
и так далее.
(Хотя это выглядит очень просто, фактическое сопоставление внутри Git довольно сложно: если в разделе указано remote = .
и branch = master
, имя будет, например, master
, а не ./master
. Если вы настроите необычные спецификации выборки, может произойти еще больше странностей. ответ вообще не распространяется на этот последний случай.)
Ответ на вопрос № 3 в каком-то смысле самый простой: git pull
просто запускает сначала git fetch
, а затем — при условии, что это удается — одну из двух других команд, git merge
или git rebase
, так что вам действительно нужно взглянуть только на вопросы 1 и 2.
Длинный
Запись merge
под каждым разделом branch
, я думаю, наименее очевидна. Документация Git немного неясна. Давайте сначала покроем остальные.
Настройки в разделе [remote "..."]
Есть много возможных настроек. Как правило, вам не нужно устанавливать какие-либо из них с помощью git config
напрямую — почти все они имеют команды-оболочки, чтобы установить их более удобным для пользователя способом. Это включает в себя обе настройки, которые вы видите здесь. Их также редко хочется менять.
Раздел remote
для каждого именованного удаленного устройства, такого как origin
, содержит URL-адрес для git fetch
(и, при необходимости, отдельный URL-адрес для отправки для git push
и другие элементы конфигурации remote.*
в виде описано в git config
документации). Он также имеет одну или несколько строк fetch
, которые предоставляют аргументы refspec по умолчанию для git fetch
с этого удаленного устройства.
То есть, если вы запустите:
git fetch origin
Git будет искать remote.origin.url
, чтобы увидеть, куда подключиться, затем подключиться туда, а затем получить ссылки на основе всех записей remote.origin.fetch
. Значение по умолчанию, которое вы видите здесь:
+refs/heads/*:refs/remotes/origin/*
указывает Git скопировать все ветки1 из удаленного хранилища, переименовав их в ветку удаленного отслеживания с префиксом origin/
2 в вашем собственном репозитории, поэтому :
git fetch origin
в принципе все достается. (В начале +
говорится, что Git должен делать это независимо от того, является ли обновление ветки удаленного отслеживания операцией быстрой перемотки вперед. То есть это похоже на использование --force
, но без указания --force
.)
С другой стороны, если вы запустите:
git fetch origin a:b c:d
Git полностью проигнорирует все строки fetch =
, извлекая только ссылки a
и c
с удаленного сервера и записывая их в ссылки b
и d
в вашем репозитории. (И поскольку здесь нет ни +
, ни --force
, ни один из них не будет принудительно обновлен, хотя в большинстве случаев это все равно не имеет значения.)
1, 2 ссылка – это общий термин, охватывающий теги обеих ветвей и (и многое другое). Имена ветвей, такие как master
, являются просто сокращением для ссылок, начинающихся с refs/heads/
. Имена ветвей удаленного отслеживания, такие как origin/master
, являются просто сокращением для ссылок, начинающихся с refs/remotes/
. Обратите внимание, что часть origin/
происходит от строки fetch =
, но для того, чтобы все это работало должным образом, эта строка должна совпадать с именем пульта в квадратных скобках.
Настройки в разделе [branch "..."]
Есть много возможных настроек. В общем, вам не нужно устанавливать какой-либо из них с помощью git config
напрямую — почти все они имеют команды-оболочки, чтобы установить их более удобным для пользователя способом. Это включает в себя обе настройки, которые вы видите здесь. Не так уж редко хочется изменить один или оба из них, используя команду, которую мы вскоре увидим.
Тем не менее, часть remote
сама по себе довольно ясна: это означает, что если вы находитесь в ветке master
и запускаете git fetch
вообще без указания удаленного имени, Git должен получать данные с удаленного сервера с именем origin
.
Часть merge
сложная. В нем указано имя ветки, которое видно на удаленном компьютере. Обратите внимание, что когда мы запускаем git fetch origin
, мы говорим нашему Git вызвать другой Git, найти другой Git master
и скопировать его в наш репозиторий, но назвать его origin/master
. И еще... в этой строке merge
написано merge = refs/heads/master
. Разве не должно быть написано: merge = refs/remotes/origin/master
?
Вероятно, так и должно быть, но эта настройка предшествует самому изобретению пультов. Так что это не так; вместо этого в нем указано полное имя ссылки, как оно отображается на удаленном компьютере.
Этот параметр используется, если вы запускаете git merge
или git rebase
без указания имени ветки для слияния или перебазирования. Git пропускает имя через сопоставления, предоставленные строкой fetch =
для удаленного сервера, чтобы выяснить, например, что оно должно объединяться с origin/master
.
Этот параметр также используется вспомогательной командой git pull
, которая фактически3 аналогична запуску git fetch
с последующим запуском git merge
.
Возможно, вы захотите изменить одно или оба из них. Например, если вы создаете новый локальный филиал feature/tall
, он может вообще не иметь никаких настроек branch.feature/tall.remote
и branch.feature/tall.merge
.
Поскольку вы только что создали эту ветку, в ней нет origin/feature/tall
. Git по адресу origin
еще не имеет feature/tall
, поэтому у вас нет его копии.
Затем вы git push origin feature/tall:feature/tall
хотите, чтобы ваш Git вызывал Git origin
и чтобы их Git создавал эту ветку, так что теперь у вас делает origin/feature/tall
. Возможно, вы захотите, чтобы ваш Git запомнил это.
Вы могли запустить две команды git config
, но вместо этого вы можете запустить одну команду оболочки более высокого уровня:
git branch --set-upstream-to=origin/feature/tall feature/tall
Это говорит вашему Git установить branch.feature/tall.remote
на origin
, а branch.feature/tall.merge
на refs/heads/feature/tall
(это имя на origin
).
Вы можете комбинировать шаги git push
и git branch --set-upstream-to
, используя git push -u
, что даже лучше, но суть здесь остается: вы используете оболочку, чтобы получить оба значения одновременно, поскольку установка только одного значения не так уж и важна. полезно.4
Специальное удаленное имя .
означает этот репозиторий (в отличие от какого-либо удаленного репозитория). Если в разделе [branch "xyzzy"]
указаны remote = .
и branch = refs/heads/whatever
, то ветвь xyzzy
имеет локальную ветвь whatever
в качестве восходящей, а не, например, origin/whatever
в качестве восходящей.
3Это намеренно замалчивает множество мелких деталей.
4Установка только части remote
действительно влияет на будущее git push
, но git merge
и git rebase
не смогут выполнять сопоставление ветвей удаленного отслеживания без обеих записей.
person
torek
schedule
10.04.2017