У нас есть следующая ситуация:
A --- B --- C --- ... --- iphone
/
... --- last-working --- ... --- master
Между последней работой и iPhone, были сделаны 32 фиксации. Между последней работой и ведущим устройством, было сделано много фиксаций.
Что я хочу, теперь новое ответвление, где у меня есть iPhone и текущее ведущее устройство, объединенное вместе. И в некоторое более позднее время, это должно быть объединено в ведущее устройство.
Во-первых, я запланировал сделать:
git checkout iphone -b iphone31
git merge master
Но затем я думал, если будет лучше сделать:
git checkout master -b iphone31
git merge iphone
Теперь я задаюсь вопросом. Каково было бы различие в результате? Слияние вело бы себя отличающееся?
Я уже попробовал обоих и как я ожидал, я получил много конфликтов, потому что iPhone действительно стар по сравнению с ведущим устройством. Теперь интересно о самом легком способе объединить их.
Возможно, даже запуск с ведущего устройства и слияние каждой единственной фиксации iPhone в него были бы легче? Как выполнение этого:
git checkout master -b iphone31
git merge A
git merge B
git merge C
...
git merge iphone
В самом конце, когда это слияние сделано (т.е. все конфликты разрешены и это работает), я хочу сделать это:
git checkout master
git merge iphone31
Наилучший подход действительно зависит от того, есть ли у других людей удаленные копии вашего кода. Если ветка master находится только на вашем локальном компьютере, вы можете использовать команду rebase для интерактивного применения коммитов из ветки функции в master:
git checkout master -b iphone-merge-branch
git rebase -i iphone
Обратите внимание, что это изменяет историю фиксации вашего нового ] iphone-merge-branch ветвь, которая может вызвать проблемы у всех, кто позже попытается перенести ваши изменения в свою кассу. Напротив, команда слияния применяет изменения как новую фиксацию, что более безопасно при совместной работе, поскольку не влияет на историю веток. См. в этой статье несколько полезных советов по использованию rebase.
Если вам нужно синхронизировать историю коммитов, лучше выполнить слияние. Вы можете использовать git mergetool для интерактивного устранения конфликтов один за другим с помощью инструмента визуального сравнения (учебное пособие по этому вопросу можно найти здесь ):
git checkout master -b iphone-merge-branch
git merge iphone
git mergetool -t kdiff3
Третий вариант, если если вам нужен полный контроль над процессом, можно использовать git cherry-pick . Вы можете использовать gitk (или вашу любимую программу просмотра истории), чтобы просмотреть хэши коммитов в ветке iphone, записать их и выбрать их по отдельности в ветке слияния, устраняя конфликты по ходу дела. Объяснение этого процесса можно найти здесь . Этот процесс будет самым медленным, но может быть лучшим вариантом, если другие методы не сработают:
gitk iphone
<note down the 35 commit SHA hashes in this branch>
git checkout master -b iphone-merge-branch
git cherry-pick b50788b
git cherry-pick g614590
...
Что касается альтернатив
git checkout iphone -b iphone31
git merge master
и
git checkout master -b iphone31
git merge iphone
, они будут иметь одинаковую легкость или сложность, это все равно что спорить, наполовину полон стакан или наполовину пуст.
То, как мы смотрим на деревья версий, в некотором смысле просто наше произвольное восприятие. Допустим, у нас есть дерево версий, подобное следующему:
A----------+
| |
| |
\_/ \_/
B X
| |
| |
\_/ \_/
C Y
|
|
\_/
D
|
|
\_/
E
И допустим, что мы хотим сделать новую версию Z извлеченной из Y на основе изменений с C на E, но не включая изменения, сделанные с A до C.
"О, это будет сложно, потому что нет общей отправной точки. " Ну, не совсем. Если мы просто разместим объекты немного по-другому в графическом макете, как этот
/
C+---------+
| \ |
| |
\_/ |
D B
| / \
| |
\_/ |
E A
|
|
\_/
X
|
|
\_/
Y
, то теперь все станет выглядеть многообещающе. Обратите внимание, что здесь я не менял никаких взаимосвязей, все стрелки указывают так же, как на предыдущем рисунке, и версия A по-прежнему является общей базой. Только макет изменено.
Но теперь тривиально представить себе другое дерево
C'---------+
| |
| |
\_/ \_/
D B'
| |
| |
\_/ \_/
E A
|
|
\_/
X
|
|
\_/
Y
, где задача состояла бы в обычном слиянии версии E.
Таким образом, вы можете объединить все, что захотите, единственное, что влияет на легкость или сложность, - это совокупность изменений, сделанных между тем местом, где вы выбираете в качестве отправной точки или общей основы, и тем, где вы объединить с. Вы не ограничены использованием естественной отправной точки, которую предлагает ваш инструмент управления версиями.
Это может быть непросто с некоторыми системами / инструментами контроля версий,
но если все остальное не помогает,
ничто не мешает вам сделать это вручную,
проверяя версию C и сохраните файл как file1,
извлеките версию E и сохраните файл как file2,
извлеките версию Y и сохраните файл как file3,
и запустите kdiff3 -o merge_result файл1 файл2 файл3
.
Теперь для вашей конкретной ситуации трудно точно сказать, какая стратегия вызовет наименьшее количество проблем, но если есть много изменений, которые создают какие-то конфликт , вероятно, легче разделить и объединить более мелкие части.
Я предлагаю , поскольку между последней работающей и iphone 32 фиксации, вы можете, например, начать с разветвления мастера, а затем выполнить слияние в первом 16 коммитов. Если окажется, что слишком много проблем, вернитесь и попробуйте объединить 8 первых коммитов. И так далее. В худшем случае вы закончите слияние каждого из 32 коммитов один за другим, , но это, вероятно, будет проще, чем обрабатывать все накопленные конфликты за одну операцию слияния (и {{1 }} в этом случае вы работаете с действительно расходящейся кодовой базой).
Нарисуйте на бумаге дерево версий и отметьте стрелками, что вы хотите объединить. Вычеркивайте вещи по мере их выполнения, если вы разделите процесс на несколько этапов. Это даст вам более четкое представление о том, чего вы хотите достичь, что вы уже сделали и что осталось.
Я действительно могу порекомендовать KDiff3 , это отличный инструмент для сравнения / слияния.
Вы говорите:
ветка iphone очень старая по сравнению с главной
Вы действительно хотите объединить их обе в новую ветку?
Назначение веток master и iphone теперь было бы совсем другим (потому что iphone очень старый). Было бы лучше создать новую ветку, объединяющую iphone с предком мастера ? Подумай об этом.
Я настоятельно рекомендую вам прочитать Забавы со слиянием и назначением веток .
Если после прочтения этой статьи вы все еще чувствуете, что хотите объединить iphone и master, @seanhodges объяснит, как действительно хорошо справляться с конфликтами.