Почему по умолчанию git pull выполняет слияние вместо ребазирования?


71

Рассмотрим следующую ситуацию:

  • У вас есть клон Git-репозитория
  • У вас есть локальные коммиты (коммиты, которые еще нигде не были переданы)
  • Удаленный репозиторий имеет новые коммиты, которые вы еще не согласовали

Так что-то вроде этого:

Нефиксированные коммиты

Если вы выполните git pullс настройками по умолчанию, вы получите что-то вроде этого:

объединить коммит

Это потому что git выполнил слияние.

Хотя есть альтернатива. Вместо этого вы можете сказать pull, чтобы сделать ребаз:

git pull --rebase

и вы получите это:

перебазировать

На мой взгляд, перебазированная версия имеет множество преимуществ, которые в основном сосредоточены на поддержании чистоты вашего кода и истории, поэтому я немного удивлен тем фактом, что git выполняет слияние по умолчанию. Да, хеши ваших локальных коммитов будут изменены, но это похоже на небольшую цену за более простую историю, которую вы получаете взамен.

Я ни в коем случае не предполагаю, что это как-то плохо или неправильно по умолчанию. У меня просто возникают проблемы с размышлениями о причинах, по которым слияние может быть предпочтительным по умолчанию. Есть ли у нас понимание того, почему он был выбран? Есть ли преимущества, которые делают его более подходящим по умолчанию?

Основная мотивация для этого вопроса заключается в том, что моя компания пытается установить некоторые базовые стандарты (надеюсь, больше похожие на руководящие принципы) для того, как мы организуем и управляем нашими репозиториями, чтобы облегчить разработчикам доступ к репозиторию, с которым они ранее не работали. Я заинтересован в том, чтобы сделать так, чтобы мы обычно делали перебаз в такой ситуации (и, вероятно, рекомендовали разработчикам по умолчанию переустанавливать свои глобальные конфигурации), но если бы я был против, я, конечно, спросил бы, почему rebase не ' по умолчанию, если это так здорово. Поэтому мне интересно, есть ли что-то, что я пропускаю.

Было высказано предположение, что этот вопрос является дубликатом Почему многие веб-сайты предпочитают «git rebase», а не «git merge»? ; однако этот вопрос несколько противоположен этому. В нем рассматриваются преимущества перебазирования перед слиянием, а в этом вопросе говорится о преимуществах слияния перед перебазированием. Ответы там отражают это, сосредотачиваясь на проблемах слияния и преимуществах rebase.



Другая проблема заключается в том, что если вы случайно фиксируете мастер, а затем выполняете объединение, два мастера могут быть не синхронизированы, даже если объединение выглядит нормально. Вот почему мой псевдоним включает --ff-only.
Иксрек

если sourcetree когда-либо изменит свой график, чтобы он отображал перебазирование / слияние по-другому, вы перейдете на слияние?
Эван

1
@Ewan SourceTree не должен менять свое графическое представление об этом. Это точно представляет график.
jpmc26

4
Для избирателей-дураков, обратите внимание, что содержание в ответе, который я принял, совершенно точно не присутствует в вопросе, который вы утверждаете, является дубликатом.
jpmc26

Ответы:


56

Трудно понять наверняка, почему слияние является значением по умолчанию, не услышав от человека, который принял это решение.

Вот теория ...

Git не может предположить, что это нормально - перебазировать каждое нажатие. Послушай, как это звучит. «Перебазируйте каждое притяжение». просто звучит неправильно, если вы используете запросы на удаление или подобное. Вы бы перебазировали по запросу?

В команде, которая не просто использует Git для централизованного контроля версий ...

  • Вы можете тянуть вверх и вниз по течению. Некоторые люди много тянут из нижестоящих, от участников и т. Д.

  • Вы можете работать над функциями в тесном сотрудничестве с другими разработчиками, извлекая у них информацию или из общей ветки тем, и все же время от времени обновляйтесь из основной ветки разработки. Если вы всегда делаете ребазинг, то в итоге вы меняете общую историю, не говоря уже о забавных конфликтных циклах.

Git был разработан для большой высокораспределенной команды, где каждый не тянет и не тянет к одному центральному репо. Так что по умолчанию имеет смысл.

  • Разработчики, которые не знают, когда можно выполнить ребазинг, будут объединяться по умолчанию.
  • Разработчики могут сделать ребаз, когда захотят.
  • Коммиттеры, которые делают много натяжений и имеют много притяжений, получают значение по умолчанию, которое подходит им лучше всего.

Для доказательства намерений, вот ссылка на хорошо известное письмо от Линуса Торвальдса с его мнением о том, когда им не следует перебазировать. Dri-devel git pull email

Если вы проследите весь поток, вы увидите, что один разработчик вытягивает из другого разработчика, а Линус вытягивает из обоих. Он ясно высказывает свое мнение. Поскольку он, вероятно, решил, что Git по умолчанию, это может объяснить почему.

Многие люди сейчас используют Git централизованно, где все в небольшой команде тянут только из центрального репо по восходящему потоку и выталкивают на тот же самый пульт. Этот сценарий позволяет избежать некоторых ситуаций, когда перебазирование не является хорошим, но обычно не устраняет их.

Предложение: не делайте политику изменения по умолчанию. Каждый раз, когда вы собираете Git вместе с большой группой разработчиков, некоторые разработчики не будут понимать Git все это глубоко (включая меня). Они пойдут в Google, ТАК, получат рекомендации по кулинарной книге, а затем зададутся вопросом, почему некоторые вещи не работают, например, почему git checkout --ours <path>получается неправильная версия файла? Вы всегда можете пересмотреть свою местную среду, создать псевдонимы и т. Д. По своему вкусу.


5
+1 за то, что вы не изменили значение по умолчанию - вместо того, чтобы переходить на собственный рабочий процесс git, вероятно, лучше взять тот, который существует (например, любой, документированный Atlassian atlassian.com/git/tutorials/comparing-workflows/… )
Роб Черч

1
Спасибо за ответ. Информация о том, как тянуть вниз по течению, была тем, чего мне не хватало Также, что довольно интересно, ссылка, которую вы дали, вдохновляет именно то, чего я хотел бы достичь: «Люди могут (и, вероятно, должны) перебазировать свои частные деревья (свою собственную работу)».
jpmc26

2
@jpmc Отлично. На самом деле. Перебазирование частных деревьев может отвлечь много внимания от общей истории. Я делаю это. Важно понимать, когда этого не делать.
Joshp

«Некоторые разработчики не будут понимать все это Git». Rebase НЕ является супер-необычной («глубокой» и т. Д.) Функцией Git. Вы действительно считаете эту вещь трудной для понимания? Я думаю, что это должно быть триггером, чтобы назвать dev некомпетентным.
Виктор Ярема

15

Если вы прочитали man-страницу git для rebase, она говорит :

Перебазирование (или любая другая форма переписывания) ветки, на которой работают другие, является плохой идеей: любой нижестоящий пользователь вынужден вручную исправлять свою историю. В этом разделе объясняется, как это исправить с точки зрения нижестоящего. Однако реальное исправление заключается в том, чтобы в первую очередь избежать перебазирования вверх по течению.

Я думаю, это говорит о том, что это достаточно хорошо для того, чтобы вообще не использовать rebase, не говоря уже о том, чтобы автоматически делать это при каждом нажатии. Некоторые люди считают, что rebase вреден . Возможно, его вообще никогда не следовало вводить в git, поскольку все, что он, похоже, делает, это претворяет в жизнь историю, то, что не должно быть необходимо в любом SCM, единственной важной задачей которого является сохранение истории.

Когда вы говорите «держать историю в чистоте», думайте, что вы ошибаетесь Это может выглядеть лучше, но для инструмента, предназначенного для хранения истории изменений, гораздо чище сохранять каждый коммит, чтобы вы могли видеть, что произошло. Дезинфекция истории впоследствии похожа на полировку патины, делая богатый антиквариат похожим на блестящую репродукцию :-)


3
@ Иван ИМХО "не работает, но выглядит красиво" - это то, что должно быть зарезервировано исключительно для индустрии моды, а не для ИТ. ИМХО, мерзавец должен убрать его, так как он явно побуждает слишком многих людей думать, что стиль важнее, чем сущность.
gbjbaanb

12
Я бы оспорил ваше предположение, что держать историю в чистоте бесполезно. Это не. История хранилище предназначено для потребления человеком, и как таковой, есть много ценного, чтобы сделать его читаемым. В моем конкретном случае использования мы даже предполагаем, что руководители проектов , не являющиеся разработчиками, должны иметь возможность читать историю. Чистая история может только помочь с этим, и это может помочь новому разработчику, который никогда не видел основы кода и должен погрузиться и исправить ошибку, понять, что случилось в определенной области кода.
jpmc26

3
Код существует в первую очередь для выполнения машиной (возможно, после компиляции). Применяя вашу философию выше, мы пришли бы к выводу, что читаемость кода не имеет значения, потому что никакая читабельность не решит трудности понимания кода. Я никогда не предлагал что-то раздавить. Я просто говорю, что сложный график, который расходится по множеству пересекающихся путей, трудно проследить, поэтому стоит немного инвестировать в поддержание вашей истории достаточно чистой. Также обратите внимание, что линейная история более благоприятна для использования инструментов git, таких как «винить» и «делить».
jpmc26

6
Документы не говорят "не перебазировать". Он говорит: «Не переоценивайте изменения, которые находятся выше по потоку от других людей ». Существует огромная разница между этими двумя. Сам Линус советует немного перебазировать для организации истории, как видно из ссылки в принятом ответе. И как любой инструмент узнает, какие коммиты не имеют значения (особенно если инструментам трудно анализировать нелинейную историю!), И как вы узнаете, с каким коммитом вы хотите работать (особенно без возможности копаться в истории!)? Вы предостерегаете конкретную ситуацию от догматической крайности.
jpmc26

4
Вы определенно не хотите «хранить историю изменений», если это включает в себя каждый коммит, который когда-либо делал разработчик. Следуя этой логике, мы должны также записывать исходную версию кода каждый раз, когда нажимается клавиша возврата. Каждый коммит должен быть минимальным и полным изменением, которое по-прежнему поддерживает весь проект в стабильном состоянии. Если позже будет обнаружено, что ваш исходный коммит содержит ошибки, гораздо лучше перебазировать / отредактировать / изменить коммит, чем создавать другой. Тем не менее, см. Также mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
Микко Ранталайнен

12

Вы правы, если у вас есть только один локальный / измененный репозиторий. Однако рассмотрим, например, второй локальный ПК.

Как только ваша локальная / измененная копия будет перенесена куда-то еще, ребазинг испортит эти копии. Конечно, вы можете заставить толкаться, но это быстро становится сложным. Что произойдет, если один или несколько из них будут иметь совершенно новый коммит?

Как вы можете видеть, это очень ситуативно, но базовая стратегия кажется (на мой взгляд) гораздо более практичной в нестандартных случаях / случаях сотрудничества.


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


1
«После перебазирования очень вероятно, что более старые коммиты могут следовать за более новыми изменениями» - это также происходит со слияниями, поэтому вам (возможно) нужен симпатичный граф, чтобы понять это. Время, когда был сделан коммит, может быть задолго до слияния, которое привело его в эту ветку.
Стив Джессоп

6

Основная причина, вероятно, заключается в том, что поведение по умолчанию должно «просто работать» в публичных репозиториях. Опровержение истории, которую уже слили другие люди, вызовет у них проблемы. Я знаю, что вы говорите о своем частном репо, но в целом git не знает и не заботится о том, что является частным или публичным, поэтому выбранный по умолчанию будет по умолчанию для обоих.

Я git pull --rebaseчасто использую в своем личном репо, но даже там у него есть потенциальный недостаток, который заключается в том, что история моего HEADбольше не отражает дерево, поскольку я фактически работал над ним.

В качестве большого примера, предположим, что я всегда запускаю тесты и проверяю, что они проходят, прежде чем делать коммит. Это имеет меньшее значение после того, как я это сделаю git pull --rebase, потому что больше не правда, что дерево в каждом из моих коммитов прошло тесты. Пока изменения не вмешиваться каким - либо образом, а код я тяну был проверен, то предположительно он будет проходить испытания, но мы не знаем , потому что я никогда не пробовал. Если непрерывная интеграция является важной частью вашего рабочего процесса, то любая перебазировка в репо с CIed вызывает беспокойство.

Я не против этого, но это беспокоит некоторых людей: они предпочли бы, чтобы их история в git отражала код, над которым они фактически работали (или, возможно, к тому моменту, когда они его продвигают, упрощенную версию правды после некоторого использования "исправление").

Я не знаю, является ли именно эта проблема причиной, по которой Линус решил объединить, а не перебазировать по умолчанию. Могут быть и другие недостатки, с которыми я не сталкивался. Но так как он не стесняется выражать свое мнение в коде, я уверен, что все сводится к тому, что он считает подходящим рабочим процессом для людей, которые не хотят слишком много думать об этом (и особенно для тех, кто работает в общественных чем частное репо). Избегание параллельных линий на симпатичном графике в пользу чистой прямой линии, которая не представляет параллельное развитие в том виде, в котором оно произошло, вероятно, не является его главным приоритетом, даже если оно ваше :-)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.