Слияние ветки ветки после первой ветки раздавливается при объединении с мастером
Вот рабочий процесс, который я обычно рассматриваю на работе.
git checkout -b feature_branch
# Do some development
git add .
git commit
git push origin feature_branch
В этот момент ветвь функции просматривается у моих коллег, но я хочу продолжать разрабатывать другие функции, зависящие от feature_branch
. Итак, пока feature_branch
находится в обзоре...
git checkout feature_branch
git checkout -b dependent_branch
# Do some more development
git add .
git commit
Теперь я вношу некоторые изменения в ответ на обзор кода на feature_branch
git checkout feature_branch
# Do review fixes
git add .
git commit
git checkout dependent_branch
git merge feature_branch
Теперь у нас возникают проблемы. У нас есть политика squash на master, а это означает, что ветки функций, которые объединены в master, должны быть сжаты в один commit.
git checkout feature_branch
git log # Look for hash at beginning of branch
git rebase -i first_hash_of_branch # Squash feature_branch into a single commit
git merge master
Все круто, кроме dependent_branch
. Когда я пытаюсь переустановить зависимую ветвь на master или пытаюсь объединить в нее мастер, git путается переписанной/сжатой историей и в основном отмечает каждое изменение в depedendent_branch
как конфликт. Это PITA, чтобы пройти и в основном повторить или де-конфликтовать все изменения в dependent_branch
. Есть ли какое-то решение? Иногда я вручную создаю патч и применяю его к новой ветке мастера, но если есть какие-то реальные конфликты с этим, еще хуже, чтобы исправить.
git checkout dependent_branch
git diff > ~/Desktop/dependent_branch.diff
git checkout master
git checkout -b new_dependent_branch
patch -p1 < ~/Desktop/dependent_branch.diff
# Pray for a clean apply.
Любые идеи? Я знаю, что это происходит из-за переписанной истории во время сквоша, но это требование, которое я не могу изменить. Какое лучшее решение/обходное решение? Есть ли какая-то магия, которую я могу сделать? Или существует более быстрый способ выполнить все шаги, связанные с ручным созданием diff?
Ответы
Ответ 1
Немного о том, почему это происходит:
Я дам O
быть "оригинальным мастером" и FB
быть "новым мастером", после того, как ветвь функции была объединена в:
Скажите feature_branch
выглядит так:
O - A - B - C
dependent_feature
содержит несколько дополнительных коммитов:
O - A - B - C - D - E - F
Вы объединяете свою оригинальную ветку функций в мастер и выкапываете ее, давая вам:
O - FB
Теперь, когда вы пытаетесь переустановить зависимую ветвь, git попытается выяснить общий предок между этими ветвями. Хотя изначально был C
, если вы не раздавили коммиты вниз, git вместо этого находит O
в качестве общего предка. В результате git пытается воспроизвести A
, B
и C
, которые уже содержат в FB
, и вы получите кучу конфликтов.
По этой причине вы не можете действительно полагаться на типичную команду переадресации, и вы должны быть более явным образом, предоставляя параметр --onto
:
git rebase --onto master HEAD~3 # instruct git to replay only the last
# 3 commits, D E and F, onto master.
Измените параметр HEAD~3
, необходимый для ваших веток, и вам не придется иметь дело с любым избыточным разрешением конфликта.
Некоторый альтернативный синтаксис, если вам не нравится указывать диапазоны, и вы еще не удалили свою исходную ветвь функции:
git rebase --onto master feature_branch dependent_feature
# replay all commits, starting at feature_branch
# exclusive, through dependent_feature inclusive
# onto master
Ответ 2
Я искренне не согласен с политикой "mash every feature development down into one commit", но это их вызов...
Я бы сохранил ветки как есть, и создаю вымощенную фиксацию только для публикации в специальной ветке. Возможность следить за развитием шаг за шагом является ценной, даже если руководство не верит в это. Отметьте места сквоша по тегам в "реальных" ветвях, вы также можете добавить метки между сквошами с сообщениями, указывающими на реальные фиксации.
Ответ 3
В этом конкретном случае кажется, что вы "знаете", что только сжатая работа ветки, с которой вы первоначально работали, была помещена в мастер.
Таким образом, вы можете с радостью объединиться, сохраняя свои изменения каждый раз, когда есть конфликт. Для этого есть опция:
git merge -Xours master
Подробнее см. https://git-scm.com/docs/git-rebase.