Мы уже рассмотрели git merge, теперь перейдем к pull.
Команда pull забирает изменения из удаленного репозитория и интегрирует их с изменениями в локальном репозитории.
Пример использования
Чтобы забрать изменения из удаленной ветки dev репозитория origin и слить их с изменениями в текущей ветке, где мы находимся, выполним:
git pull origin dev
Это аналогично двум последовательным командам:
git fetch origin git merge origin/dev
Обратите внимание, что перед выполнением команды pull все текущие изменения должны быть закоммичены, так же, как перед выполнением команды merge. Иначе слияние не выполнится.
Параметры по умолчанию
Если попробовать выполнить pull без параметров, находясь в ветке master:
git pull
команда выполнится. Но с какой же веткой происходит в этом случае слияние? По умолчанию это ветка master репозитория origin. (При клонировании удаленного репозитория по умолчанию ему дается имя origin). То есть команда аналогична:
git pull origin master
Как видите, для ветки master заданы параметры по умолчанию. Можно их задать и для других веток. Связывание локальной ветки и удаленной ветки называется отслеживанием ветки.
Настройка отслеживаемой ветки
Давайте сделаем так, чтобы, когда мы находимся в локальной ветке dev, по умолчанию слияние происходило с веткой dev репозитория origin. Перейдем в ветку dev и выполним команду:
git branch -u origin/dev
Эта команда связало локальную ветку dev с удаленной веткой origin/dev.
Теперь когда мы находимся на локальной ветке dev и выполняем pull без параметров, слияние происходит по умолчанию с удаленной веткой dev:
git pull
То есть теперь вышеприведенная команда без параметров будет аналогична команде с параметрами:
git pull origin dev
git pull vs. git fetch
git fetch просто обновляет локальную копию удаленного репозитория. То есть все копии удаленных веток (которые записываются через слеш — например, origin/master) будут содержать самый последний коммит из удаленного репозитория.
Но при этом содержимое локальных веток, в том числе той, на которой вы находитесь, не меняется. В папках остаются те же файлы. Команда fetch безвредна и ее можно делать сколько угодно раз. Иногда даже пишут скрипт, который выполняет git fetch в фоновом режиме.
Команда pull же состоит из fetch и merge. То есть помимо обновления копии удаленного репозитория на вашем компьютере, она еще и реально меняет содержимое папок, с которыми вы работаете. Вливает удаленную ветку в текущую.
git pull —rebase
Рассмотрим команду pull с параметром rebase:
git pull --rebase
На результат слияния параметр —rebase не влияет, единственное, что он делает — меняет вид истории коммитов.
До команды pull
Допустим, мы разветвились с удаленным репозиторием на коммите D:
Наши локальные коммиты с момента разветвления — это нижние E, F, G, а в удаленном репозитории с тех пор появились коммиты A, B, C. Нам надо их накатить сверху на наши коммиты E, F, G, что собственно и делает команда pull.
Обычный pull
Но тут возможны нюансы. По умолчанию делается дополнительный коммит H, который и включает все изменения из удаленной ветки:
pull —rebase
Если же мы выполним:
git pull --rebase
то история локальных коммитов будет выглядеть по другому (при том же результате слияния файлов):
При просмотре истории коммитов мы просто увидим ряд коммитов из основной ветки A, B, C, идущих за нашими локальными E, F, G. Кому-то такой вид выглядит чище, хотя разницы в итоговом содержимом файлов нет.
git pull force
Насильно выполнить git pull нельзя. Она не перезапишет локальные изменения, если есть конфликт. Конфликт все равно придется разрешать.
Если же требуется получить данные из удаленной ветки, перезаписав локальные изменения, то делается это в два этапа. Сначала обновить локальную копию удаленного репозитория:
git fetch --all
Далее, допустим надо перезаписать содержимое текущей ветки данными из ветки master репозитория origin:
git reset --hard origin/master
Если надо перезаписать содержимое текущей ветки данными из другой ветки dev репозитория origin:
git reset --hard origin/dev
Но будьте внимательны с опцией —hard, она действительно затирает коммиты текущей ветки безвозвратно. Если надо их сохранить, то перед выполнением команды создайте новую ветку — в нее все сохранится:
git branch new-branch-to-save-current-commits git fetch --all git reset --hard origin/dev
Что еще интересно: коммиты reset —hard затирает, а если в папке были просто неотслеживаемые файлы, то они не будут затронуты.
Итоги
Команда pull — на любителя, потому что не всем нравится автоматически сливать ветки. Гораздно прозрачнее делать отдельно fetch и merge.