В чем разница между "git merge" и "git rebase"?

в чем разница между git merge и git rebase?

6 ответов


предположим, первоначально было 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 все еще здесь, но мы create merge commit M, который наследует изменениями от D и E. Однако, это создает Алмаз формы, многие люди находят очень запутанной.

REBASE:

A-B-C-D-E-R

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


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

3. Дерьмовая документация

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

git-push – Update remote refs along with associated objects

Вот описание для человека:

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

обновление, другой Пример: (Спасибо ГКР)

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. без цензуры в оригинале


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

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

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

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

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

пример

я попытаюсь объяснить это с помощью примера just-words. Предположим, другие люди в вашем проекте работают над пользовательским интерфейсом, и вы пишете документацию. Без 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", упомянутого в другом ответе)


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

слияние

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

rebase

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

резюме: когда это возможно, rebase почти всегда лучше. Облегчение реинтеграции в основную отрасль.

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


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

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

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


для легкого понимания можно увидеть мою фигуру.

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

enter image description here