В чем разница между git pull и git fetch + git rebase?

Другой вопрос говорит, что git pull похож на git fetch + git merge.

Но в чем разница между git pull и git fetch + git rebase?


person michael    schedule 28.07.2010    source источник
comment
кто-то должен очистить ссылку ... и я поражен тем, сколько голосов получил другой вопрос.   -  person xenoterracide    schedule 29.07.2010
comment
@xeno: я думаю, что это просто подсчет того, сколько людей ушло, у меня тоже был этот вопрос   -  person bobobobo    schedule 29.07.2010
comment
Когда-нибудь я найду время, чтобы действительно прочитать документацию git, но до тех пор я добавляю свои голоса к этим типам вопросов.   -  person Eran Medan    schedule 18.09.2012


Ответы (2)


Из вашего вопроса должно быть совершенно очевидно, что вы на самом деле просто спрашиваете о разнице между git merge и git rebase.

Итак, давайте предположим, что вы находитесь в обычном случае - вы проделали некоторую работу в своей основной ветке и извлекаете из источника, который также проделал некоторую работу. После выборки все выглядит так:

- o - o - o - H - A - B - C (master)
               \
                P - Q - R (origin/master)

Если вы объединитесь в этот момент (поведение git pull по умолчанию), предполагая, что конфликтов нет, вы получите следующее:

- o - o - o - H - A - B - C - X (master)
               \             /
                P - Q - R --- (origin/master)

Если, с другой стороны, вы сделали соответствующую перебазировку, вы получите следующее:

- o - o - o - H - P - Q - R - A' - B' - C' (master)
                          |
                          (origin/master)

Содержимое вашего рабочего дерева должно быть одинаковым в обоих случаях; вы только что создали другую историю, которая привела к этому. Перебазирование переписывает вашу историю, делая ее похожей на то, как если бы вы совершили коммит поверх новой основной ветки происхождения (R), а не там, где вы изначально совершили коммит (H). Вы никогда не должны использовать подход перебазирования, если кто-то уже вытащил из вашей главной ветки.

Наконец, обратите внимание, что вы можете настроить git pull для данной ветки на использование перебазирования вместо слияния, установив для параметра конфигурации branch.<name>.rebase значение true. Вы также можете сделать это за один раз, используя git pull --rebase.

person Cascabel    schedule 28.07.2010
comment
Что произойдет, если вы перебазируете после того, как кто-то уже вытащил из вашей основной ветки? Это сломает репо? - person Didier A.; 22.03.2011
comment
Как узнать, что кто-то вытащил из вашей главной ветки? - person Frank; 07.08.2012
comment
Если вы не знаете наверняка, что кто-то нет, вы должны предположить, что он это сделал. - person Chris Down; 11.02.2013
comment
Я просто подумал, что если вы также не отправляете изменения куда-то, кроме origin/master, я не вижу, чтобы когда-либо сталкивались с проблемой того, что кто-то другой вытащил рассматриваемые изменения, потому что, если вы уже отправили эти изменения в origin/ master, в первую очередь нечего будет перебазировать. Мне кажется, что предупреждение действительно имеет значение только в тех случаях, когда у вас есть что-то более сложное, чем X -> origin/X, но я могу ошибаться. Если кто-то знает сценарий, который я упускаю из виду, поделитесь, пожалуйста. - person neverfox; 26.06.2013
comment
@neverfox Основной сценарий: я нажимаю A на origin/master. Кто-то другой тянет. Я перебазирую, меняю A на A' (или что-то более сложное) и принудительно нажимаю это. Теперь, когда другой человек тянет, он будет пытаться объединить A и A' (или с помощью pull --rebase перебазировать A поверх A'). Оба являются рецептами чего-то по шкале от головной боли до катастрофы, в зависимости от компетентности другого человека. - person Cascabel; 26.06.2013
comment
@neverfox На самом деле, pull --rebase пытается быть умнее, но я не уверен, что это универсально успешно. - person Cascabel; 26.06.2013
comment
Это может показаться придирчивым, но это просто для того, чтобы помочь мне понять: если на вашей диаграмме строки слева направо соответствуют относительному времени, не будет ли конечный результат - o - o - o - o - P - A - Q - B - R - C (т. е. временной порядок коммитов сохраняется)? - person Steve Chambers; 06.11.2013
comment
@SteveChambers Нет, это не результат. Строки просто представляют родословную коммита, т. е. A является родителем B. Нет никакого намека на то, был ли Q или B первым во времени. Все эти операции основаны на графиках коммитов, а не на времени. Rebase просто пересаживает некоторые коммиты, и результат, как я показал, не зависит от временных меток коммитов. - person Cascabel; 06.11.2013
comment
@SteveChambers Перебазирование, о котором идет речь здесь, - это master на origin/master. Git смотрит на master, начинает с коммита C, возвращается к общему предку с origin/master, находит общего родителя A и P, поэтому он знает, что нужно переместить все, начиная с A, поэтому он перемещает A - B - C на origin/master (зафиксировать R) и делает это, заканчивая P - Q - R - A - B - C. - person Cascabel; 06.11.2013
comment
Если вы хотите, чтобы поведение по умолчанию было перебазированием вместо слияния для каждой ветки, которую вы извлекаете, вы можете настроить это глобально, выполнив git config --global branch.autosetuprebase always - person mmjmanders; 16.05.2014
comment
Вам лучше протестировать свою работу, если вы используете Rebase. Если ваши изменения несовместимы с коммитами, сделанными начиная с версии (H), с Rebase никто не узнает, почему вы внесли неработающий код, потому что это будет выглядеть так, как будто вы внесли изменения в последнюю версию (C). Слияние лучше отражает реальность, т.е. фиксирует тот факт, что вы работали над версией (H), а не (C). - person rustyx; 20.07.2014
comment
@didibus: с rypress.com/tutorials/git/centralized-workflows.html: Подумайте, что произошло бы, если бы Мэри перебазировалась после отправки в центральный репозиторий. Она будет переписывать коммиты, которые другие разработчики, возможно, уже включили в свой проект. - person Maria Ines Parnisari; 14.09.2014
comment
есть ли шанс, что код отсутствует или отсутствует файл в git pull? - person urjit on rails; 01.10.2014
comment
Вы никогда не должны использовать подход перебазирования, если кто-то уже вытащил из вашей главной ветки. Я нахожу это предложение очень запутанным, потому что я ожидаю, что master обычно должен быть локальной ветвью, которую никто не должен тянуть? Есть ли какой-нибудь правдоподобный сценарий, когда ветка не находится на удаленном (удаленном / главном) и может быть кем-то вытащена? - person 6bf6411707; 26.01.2019

TLDR:

git pull похоже на бег git fetch, затем git merge
git pull --rebase похоже на git fetch, затем git rebase

В ответ на ваше первое заявление,

git pull похоже на git fetch + git merge.

«В режиме по умолчанию git pull является сокращением для git fetch, за которым следует git merge FETCH_HEAD». Точнее, git pull запускает git fetch с заданными параметрами, а затем вызывает git merge для слияния извлеченных заголовков ветвей с текущей ветвью.

(Ссылка: https://git-scm.com/docs/git-pull)


Для вашего второго утверждения/вопроса:

'Но в чем разница между git pull и git fetch + git rebase'

Опять же, из того же источника:
git pull --rebase

«С --rebase он запускает git rebase вместо git merge».


Теперь, если вы хотите спросить

'разница между merge и rebase'

здесь также есть ответ:
https://git-scm.com/book/en/v2/Git-Branching-Rebasing
(разница между изменением способа записи истории версий)

person gawkface    schedule 12.06.2017
comment
Я хотел бы упомянуть, что git pull --rebase в большинстве случаев похож на git fetch, затем git rebase, но не всегда. В некоторых ситуациях git pull --rebase делает немного больше. См. этот часто упоминаемый пример здесь: gitolite.com/git-pull--rebase - person Daniel K.; 22.07.2019
comment
Большое спасибо за ваш ответ. Теперь я действительно понимаю, как работают команды git fetch + git rebase. Теперь в нашем дереве git больше или меньше конфликтов нет :) - person Travis Le; 07.11.2019
comment
@DanielK, git rebase также выполняет эти дополнительные шаги, так как вскоре после того, как был написан этот пост в блоге. См. обсуждение --fork-point в git help rebase. - person Buster; 15.01.2021