Какая разница между 'git merge' и 'git rebase'?

Какая разница между git merge и git rebase?

Ответ 1

Предположим, что первоначально было 3 фиксации, A, B, C:

A-B-C

Затем разработчик Дэн создал commit D, а разработчик Ed создал commit E:

A-B-C-D-E

Очевидно, что этот конфликт должен быть каким-то образом разрешен. Для этого существует 2 способа:

Объединить

A-B-C-D-E-M

Оба коммиты D и E все еще здесь, но мы создаем транзакцию слиянием M, которая наследует изменения от D и E. Однако это создает форму бриллианта, которую многие считают очень запутанной.

Rebase

A-B-C-D-E-R

Мы создаем commit R, фактическое содержимое которого идентично содержимому слияния M выше. Но мы избавляемся от commit E, как никогда не существовало (обозначается точками - исчезающей линией). Из-за этой облитерации E должен быть локальным для разработчика Ed и никогда не должен был быть перенесен в какой-либо другой репозиторий. Преимущество rebase в том, что алмазную форму избегают, а история остается хорошей прямой - большинство разработчиков любят это!

Ответ 2

Мне очень нравится этот отрывок из 10 вещей, которые я ненавижу о git (он дает краткое объяснение для rebase во втором примере):

3. Документация crappy

Страницы руководства - одно всемогущее "f *** you" 1. Они описывают команды с точки зрения компьютерного ученого, а не пользователя. Пример:

git-push – Update remote refs along with associated objects

Вот описание для людей:

git-push – Upload changes from your local repository into a remote repository

Обновить, еще один пример: (thanks cgd)

git-rebase – Forward-port local commits to the updated upstream head

Перевод:

git-rebase – Sequentially regenerate a series of commits so they can be 
             applied directly to the head node

И тогда мы имеем

git-merge - Join two or more development histories together

что является хорошим описанием.


1. без цензуры в оригинале

Ответ 3

Лично я не считаю, что стандартная техника диаграмм очень полезна - стрелки всегда кажутся неправильными для меня. (Они обычно указывают на "родителя" каждого коммита, который заканчивается во времени назад, что странно).

Объяснить это словами:

  • Когда вы переформатируете свою ветку на свою ветку, вы сообщите Git, чтобы она выглядела так, как если бы вы проверили свою ветку чисто, а затем выполнили всю свою работу, начиная с нее. Это делает чистый, концептуально простой пакет изменений, которые кто-то может просмотреть. Вы можете повторить этот процесс снова, когда на их ветке появятся новые изменения, и вы всегда получите чистый набор изменений "на кончике" своей ветки.
  • Когда вы объединяете свою ветку в свою ветку, вы связываете две ветки истории вместе в этой точке. Если вы снова это сделаете позже с большим количеством изменений, вы начнете создавать чередующиеся потоки историй: некоторые из их изменений, некоторые из моих изменений, некоторые из их изменений. Некоторые люди находят это грязным или нежелательным.

По причинам, которые я не понимаю, инструменты GUI для Git никогда не делали много усилий, чтобы представить истории слияний более чисто, абстрагируя отдельные слияния. Поэтому, если вам нужна "чистая история", вам нужно использовать rebase.

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

Пример

Я попробую объяснить это с помощью примера только слов. Скажем, другие люди в вашем проекте работают над пользовательским интерфейсом, и вы пишете документацию. Без rebase ваша история может выглядеть примерно так:

Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md

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

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

Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger

Все ваши фиксации находятся в верхней (новейшей) позиции, а затем остальные ветки master.

(Отказ от ответственности: я являюсь автором "10 вещей, которые я ненавижу о Git", упомянутых в другом ответе)

Ответ 4

В то время как принятый и наиболее одобренный ответ велик, мне также полезно использовать объяснение разницы только словами:

слияния

  • "Хорошо, у нас есть два разных развитых состояния нашего репозитория. Объедините их вместе. Два родителя, один результирующий ребенок".

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

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

summary.. По возможности, rebase почти всегда лучше. Сделать реинтеграцию в основную ветку проще.

Потому что? ➝ ваша функциональная работа может быть представлена ​​как один большой файл исправлений (aka diff) в отношении основной ветки, не нужно "объяснять несколько родителей: по крайней мере два, исходя из одного слияния, но, вероятно, еще много, если бы было несколько сливается. В отличие от слияний, множественные перестановки не складываются. (еще один большой плюс)

Ответ 5

Git rebase ближе к слиянию. Разница в rebase:

  • локальные коммиты удаляются временно из ветки.
  • запустите git pull
  • снова вставьте все ваши локальные коммиты.

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