Предположим , что первоначально было 3 фиксаций, A, B, C:
Затем разработчик Dan создал commit D, а разработчик Ed создал commit E:
Очевидно, этот конфликт нужно как-то решить. Для этого есть 2 способа:
Мердж :
Оба коммита Dи Eвсе еще здесь, но мы создаем коммит слияния, Mкоторый наследует изменения от обоих Dи E. Тем не менее, это создает форму ромба , что многие люди находят очень запутанным.
ПЕРЕПИСКА :
Мы создаем коммит R, фактическое содержимое файла которого совпадает с Mвышеизложенным коммитом . Но мы избавляемся от коммита E, как будто его никогда не существовало (обозначено точками - линия исчезновения). Из-за этого уничтожения он Eдолжен быть локальным для разработчика Ed и никогда не должен передаваться в какой-либо другой репозиторий. Преимущество перебазирования в том, что форма ромба избегается, а история остается красивой прямой - большинству разработчиков это нравится!
Хорошие иллюстрации. Тем не менее, я не полностью согласен с положительным тоном, что обрабатывается ребаз. При слиянии и перебазировании могут возникать конфликты, требующие ручного разрешения. И, как всегда, когда участвуют программисты, существует немаловажная вероятность ошибок, таких как ошибки. Если происходит ошибка слияния, вся команда или сообщество могут увидеть слияние и проверить, не была ли там введена ошибка. История перебазирования сохраняется в репозитории 1 разработчика, и даже там он имеет ограниченный срок службы в reflog. Это может выглядеть лучше, но никто другой не может так легко увидеть, что пошло не так.
Уве Гедер,
> «Тем не менее, это создает форму ромба, что многие люди находят очень запутанным». Хм ... можешь уточнить?
Грег Малетик
@GregMaletic: форма ромба - нелинейная история. Я не знаю о вас, но я не люблю нелинейные вещи в целом. Тем не менее, вы можете использовать слияние с бриллиантами, если вы действительно предпочитаете это - никто не заставляет вас.
MVP
1
Хотя этот ответ чрезвычайно полезен, было бы лучше, если бы вы добавили реальные команды git с простыми файлами foo.txt, чтобы воспроизводить их локально. Как сказал последний пользователь, не очевидно, кто делает ребаз.
Vortex
1
@pferrel: Я не думаю, что вы правильно поняли. git mergeне перемежает коммиты (но это может выглядеть так, глядя на них git log). Вместо этого git mergeсохраняет обе истории развития Дэна и Эда в неизменном виде, как это было видно с каждой точки зрения за раз. git rebaseПохоже, что Дэн работал над этим первым, а Эд последовал за ним. В обоих случаях (слияние и перебазирование) фактическое результирующее дерево файлов абсолютно идентично.
Проблема не в языке или в том, является ли пользователь компьютерным специалистом или нет. Хотя его переписывание другим способом помогает прояснить цели (то есть, что происходит), оно не дает объяснения средств (как это происходит). Git требует понимания средств, чтобы понять цели. Именно понимание средств делает Git таким трудным. Как инструмент, который используется для упрощения или уменьшения усилий, необходимых для выполнения задачи, Git ужасно терпит неудачу. К сожалению, слишком много разработчиков не осознают этого.
ATL_DEV
128
Лично я не нахожу стандартную технику построения диаграмм очень полезной - стрелки всегда, кажется, указывают неправильный путь для меня. (Они обычно указывают на «родителя» каждого коммита, который в конечном итоге оказывается назад во времени, что странно).
Чтобы объяснить это словами:
Когда вы перемещаете свою ветку на их ветку, вы говорите Git, чтобы она выглядела так, как будто вы аккуратно проверили их ветку, а затем выполнили всю свою работу, начиная с нее. Это делает чистый, концептуально простой пакет изменений, который кто-то может просмотреть. Вы можете повторить этот процесс еще раз, когда в их ветке появятся новые изменения, и у вас всегда будет чистый набор изменений «на кончике» их ветки.
Когда вы объединяете их ветку с вашей веткой, вы соединяете две истории ветвей вместе на этом этапе. Если вы сделаете это снова позже с большим количеством изменений, вы начнете создавать чередующийся поток историй: некоторые их изменения, некоторые мои изменения, некоторые их изменения. Некоторые люди считают это грязным или нежелательным.
По причинам, которые я не понимаю, инструменты 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», о котором говорится в другом ответе )
Хотя принятый и получивший наибольшее количество голосов отличный ответ, я также считаю полезным попытаться объяснить разницу только словами:
слияние
«Хорошо, у нас есть два разных состояния нашего хранилища. Давайте объединим их вместе. Двое родителей, один ребёнок.
перебазироваться
«Передать изменения основной ветви (независимо от ее имени) моей функциональной ветви. Сделайте так, притворившись, что моя работа с функциями началась позже, по сути, над текущим состоянием главной ветви ».
«Переписать историю моих изменений, чтобы отразить это». (нужно принудительно их толкать, потому что обычно управление версиями - это не вмешательство в данную историю)
«Скорее всего - если изменения, которые я совершил, не имеют ничего общего с моей работой, - история на самом деле не сильно изменится, если я посмотрю на мои коммиты diff по diff (вы также можете подумать о« патчах »)».
Резюме: когда это возможно, ребаз почти всегда лучше. Упрощение реинтеграции в основную ветку.
Потому что? Feature ваша функциональная работа может быть представлена в виде одного большого «файла патча» (он же diff) по отношению к основной ветке, без необходимости «объяснять» нескольких родителей: по крайней мере, два из одного слияния, но, вероятно, еще много, если есть было несколько слияний. В отличие от слияний, множественные ребазы не суммируются. (еще один большой плюс)
Это означает, что все ваши локальные коммиты перемещаются в конец после всех удаленных коммитов. Если у вас есть конфликт слияния, вы должны решить его тоже.
Rebase изменит хеш коммита, поэтому, если вы хотите избежать большого количества конфликтов, просто используйте rebase, когда эта ветвь сделана / завершена как стабильная.
Я нашел одну действительно интересную статью о git rebase vs merge , думал поделиться ею здесь
Если вы хотите увидеть историю полностью такой же, как она произошла, вы должны использовать слияние. Слияние сохраняет историю, тогда как rebase переписывает ее.
Слияние добавляет новый коммит в вашу историю
Перебазирование лучше упростить сложную историю, вы можете изменить историю фиксации с помощью интерактивной перебазировки.
Ответы:
Предположим , что первоначально было 3 фиксаций,
A
,B
,C
:Затем разработчик Dan создал commit
D
, а разработчик Ed создал commitE
:Очевидно, этот конфликт нужно как-то решить. Для этого есть 2 способа:
Мердж :
Оба коммита
D
иE
все еще здесь, но мы создаем коммит слияния,M
который наследует изменения от обоихD
иE
. Тем не менее, это создает форму ромба , что многие люди находят очень запутанным.ПЕРЕПИСКА :
Мы создаем коммит
R
, фактическое содержимое файла которого совпадает сM
вышеизложенным коммитом . Но мы избавляемся от коммитаE
, как будто его никогда не существовало (обозначено точками - линия исчезновения). Из-за этого уничтожения онE
должен быть локальным для разработчика Ed и никогда не должен передаваться в какой-либо другой репозиторий. Преимущество перебазирования в том, что форма ромба избегается, а история остается красивой прямой - большинству разработчиков это нравится!источник
git merge
не перемежает коммиты (но это может выглядеть так, глядя на нихgit log
). Вместо этогоgit merge
сохраняет обе истории развития Дэна и Эда в неизменном виде, как это было видно с каждой точки зрения за раз.git rebase
Похоже, что Дэн работал над этим первым, а Эд последовал за ним. В обоих случаях (слияние и перебазирование) фактическое результирующее дерево файлов абсолютно идентично.Мне очень нравится этот отрывок из 10 вещей, которые я ненавижу в git (он дает краткое объяснение rebase во втором примере):
И тогда у нас есть
это хорошее описание.
1. без цензуры в оригинале
источник
Лично я не нахожу стандартную технику построения диаграмм очень полезной - стрелки всегда, кажется, указывают неправильный путь для меня. (Они обычно указывают на «родителя» каждого коммита, который в конечном итоге оказывается назад во времени, что странно).
Чтобы объяснить это словами:
По причинам, которые я не понимаю, инструменты GUI для Git никогда не делали больших усилий, чтобы представить истории слияний более четко, абстрагируя отдельные слияния. Так что если вы хотите «чистую историю», вам нужно использовать rebase.
Кажется, я вспомнил, что читал сообщения в блоге от программистов, которые используют только rebase, и других, которые никогда не используют rebase.
пример
Я попытаюсь объяснить это на примере только слова. Допустим, другие люди в вашем проекте работают над пользовательским интерфейсом, а вы пишете документацию. Без перебазирования ваша история может выглядеть примерно так:
То есть слияния и пользовательский интерфейс фиксируются в середине вашей документации.
Если вы перенесете свой код на master вместо слияния, это будет выглядеть так:
Все ваши коммиты находятся вверху (самые новые), за ними следуют остальные
master
ветви.( Отказ от ответственности: я являюсь автором поста «10 вещей, которые я ненавижу в Git», о котором говорится в другом ответе )
источник
Хотя принятый и получивший наибольшее количество голосов отличный ответ, я также считаю полезным попытаться объяснить разницу только словами:
слияние
перебазироваться
Резюме: когда это возможно, ребаз почти всегда лучше. Упрощение реинтеграции в основную ветку.
Потому что? Feature ваша функциональная работа может быть представлена в виде одного большого «файла патча» (он же diff) по отношению к основной ветке, без необходимости «объяснять» нескольких родителей: по крайней мере, два из одного слияния, но, вероятно, еще много, если есть было несколько слияний. В отличие от слияний, множественные ребазы не суммируются. (еще один большой плюс)
источник
Git rebase ближе к слиянию. Разница в ребазе:
Это означает, что все ваши локальные коммиты перемещаются в конец после всех удаленных коммитов. Если у вас есть конфликт слияния, вы должны решить его тоже.
источник
Для легкого понимания можно увидеть мою фигуру.
Rebase изменит хеш коммита, поэтому, если вы хотите избежать большого количества конфликтов, просто используйте rebase, когда эта ветвь сделана / завершена как стабильная.
источник
Я нашел одну действительно интересную статью о git rebase vs merge , думал поделиться ею здесь
источник