Объединение ветки ветки после того, как первая ветка сжимается при объединении с мастером

81

Вот рабочий процесс, с которым я обычно сталкиваюсь на работе.

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

Вот здесь и возникают проблемы. У нас есть политика сжатия для мастера, что означает, что ветки функций, которые объединены в мастер, должны быть объединены в одну фиксацию.

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 или попытаться слить с ней master, git смущен переписанной / сжатой историей и в основном отмечает каждое изменение depedendent_branchкак конфликт. Это PITA, чтобы пройти и, по сути, переделать или разрешить конфликты всех изменений вdependent_branch . Есть ли какое-то решение? Иногда я вручную создаю патч и применяю его к новой ветке master, но если с этим есть какие-то реальные конфликты, исправить это еще хуже.

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.

Есть идеи? Я знаю, что это происходит из-за переписывания истории во время сквоша, но это требование я не могу изменить. Какое лучшее решение / обходной путь? Могу ли я творить волшебство? Или есть более быстрый способ выполнить все шаги, связанные с созданием разницы вручную?

Майк
источник
Кроме того, git add .это полностью зло и в конечном итоге укусит вас, когда вы закончите совершать поступки, которых не хотели. Вы должны использовать git add -pили, по крайней мере,git add -u .
meagar
1
После того, как вы внесли изменения в обзор кода, вы должны переназначить зависимую_бранку в ветку функций. Затем, когда будете готовы перейти к мастеру, переустановите функциональную ветвь на master и раздавите коммиты, а затем объедините функциональную ветку с master.
Тим

Ответы:

108

Немного о том, почему это происходит:

Я позволю Oбыть «оригинальным хозяином» и FB«новым хозяином» после того, как ветка функции будет объединена:

Say feature_branchвыглядит так:

O - A - B - C 

dependent_feature Кроме того, есть несколько дополнительных коммитов:

O - A - B - C - D - E - F

Вы объединяете свою исходную ветку функций в master и подавляете ее, давая вам:

O - FB

Теперь, когда вы пытаетесь перебазировать зависимую ветвь, git попытается выяснить общего предка между этими ветвями. Хотя изначально это было бы так C, если бы вы не раздавили коммиты, вместо этого git находит Oобщего предка. В результате git пытается воспроизвести A, Bи Cкоторые уже содержатся в FB, и вы получите кучу конфликтов.

По этой причине вы не можете действительно полагаться на типичную команду rebase, и вам нужно более четко указать ее, указав --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
joshtkling
источник
Я надеялся увидеть, чем отличается дерево git для мастера при использовании --onto. Или, возможно, какой-то другой способ узнать больше о том, чем --onto отличается.
Абхишек Ананд
3
--onto просто позволяет вам более избирательно выбирать, какие коммиты вы хотели бы воспроизвести в ветке. По умолчанию git пытается «выяснить», какие коммиты следует воспроизвести. Когда вы используете --onto, вы явно указываете git воспроизводить определенный диапазон коммитов . В моем примере, если вы не использовали --onto, вы бы получили O - FB - A - B - C - D - E - F и многочисленные конфликты слияния, поскольку FB и A - B - C содержат одинаковые изменения. Используя --onto и указав последние 3 коммита, вы получите O - FB - D - E - F, как искал исходный запросчик.
joshtkling
2

В данном конкретном случае кажется, что вы «знаете», что только в мастер передана сжатая работа ветки, над которой вы изначально работали.

Таким образом, вы можете с радостью объединиться, сохраняя свои изменения каждый раз, когда возникает конфликт. Для этого есть вариант:

git merge -Xours master

См. Https://git-scm.com/docs/git-rebase для получения более подробной информации.

нха
источник
1
К сожалению, это может быть не так. Если есть время между проверками кода для feature_branch и independent_branch, возможно, feature_branch может быть объединен и передан, и кто-то другой может добавить что-то конфликтующее до того, как зависимая_branch будет достигнута.
Майк
0

Я категорически не согласен с политикой «объединить каждую разработку функции в одну фиксацию», но это их призыв ...

Я бы оставил ветки как есть и создал бы коммит только для публикации в специальной ветке. Возможность следить за развитием шаг за шагом очень ценно, даже если руководство в это не верит. Отметьте места сквоша тегами в «настоящих» ветках, вы также можете добавить теги между сквошами с сообщениями, указывающими на настоящие коммиты.

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