Какая разница между git merge
а git rebase
?
Какая разница между git merge
а git rebase
?
Ответы:
Предположим , что первоначально было 3 фиксаций, A
, B
, C
:
Затем разработчик Dan создал commit D
, а разработчик Ed создал commit E
:
Очевидно, этот конфликт нужно как-то решить. Для этого есть 2 способа:
Мердж :
Оба коммита D
и E
все еще здесь, но мы создаем коммит слияния, M
который наследует изменения от обоих D
и E
. Тем не менее, это создает форму ромба , что многие люди находят очень запутанным.
ПЕРЕПИСКА :
Мы создаем коммит R
, фактическое содержимое файла которого совпадает с M
вышеизложенным коммитом . Но мы избавляемся от коммита E
, как будто его никогда не существовало (обозначено точками - линия исчезновения). Из-за этого уничтожения он E
должен быть локальным для разработчика Ed и никогда не должен передаваться в какой-либо другой репозиторий. Преимущество перебазирования в том, что форма ромба избегается, а история остается красивой прямой - большинству разработчиков это нравится!
git merge
не перемежает коммиты (но это может выглядеть так, глядя на них git log
). Вместо этого git merge
сохраняет обе истории развития Дэна и Эда в неизменном виде, как это было видно с каждой точки зрения за раз. git rebase
Похоже, что Дэн работал над этим первым, а Эд последовал за ним. В обоих случаях (слияние и перебазирование) фактическое результирующее дерево файлов абсолютно идентично.
Мне очень нравится этот отрывок из 10 вещей, которые я ненавижу в git (он дает краткое объяснение rebase во втором примере):
3. Дрянная документация
Страницы руководства - это одно всемогущее «f *** you» 1 . Они описывают команды с точки зрения ученого, а не пользователя. Дело в точке:
git-push – Update remote refs along with associated objects
Вот описание для людей:
git-push – Upload changes from your local repository into a remote repository
Обновление, другой пример: (спасибо 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. без цензуры в оригинале
Лично я не нахожу стандартную технику построения диаграмм очень полезной - стрелки всегда, кажется, указывают неправильный путь для меня. (Они обычно указывают на «родителя» каждого коммита, который в конечном итоге оказывается назад во времени, что странно).
Чтобы объяснить это словами:
По причинам, которые я не понимаю, инструменты GUI для Git никогда не делали больших усилий, чтобы представить истории слияний более четко, абстрагируя отдельные слияния. Так что если вы хотите «чистую историю», вам нужно использовать 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», о котором говорится в другом ответе )
Хотя принятый и получивший наибольшее количество голосов отличный ответ, я также считаю полезным попытаться объяснить разницу только словами:
слияние
перебазироваться
Резюме: когда это возможно, ребаз почти всегда лучше. Упрощение реинтеграции в основную ветку.
Потому что? Feature ваша функциональная работа может быть представлена в виде одного большого «файла патча» (он же diff) по отношению к основной ветке, без необходимости «объяснять» нескольких родителей: по крайней мере, два из одного слияния, но, вероятно, еще много, если есть было несколько слияний. В отличие от слияний, множественные ребазы не суммируются. (еще один большой плюс)
Git rebase ближе к слиянию. Разница в ребазе:
Это означает, что все ваши локальные коммиты перемещаются в конец после всех удаленных коммитов. Если у вас есть конфликт слияния, вы должны решить его тоже.
Я нашел одну действительно интересную статью о git rebase vs merge , думал поделиться ею здесь