Об'єднання гілки гілки після першої гілки стискається при об'єднанні в майстер


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

Зараз у нас виникають проблеми. У нас є політика сквошу щодо master, що означає, що гілки об’єктів, які об’єднані в master, повинні бути згорнуті в один коміт.

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 .
меагар

1
Після внесення змін до огляду коду вам слід перебазувати depend_branch на гілку функції. Потім, коли будете готові перейти до мастерингу, перебазуйте гілку об’єкта на мастер і розімніть коміти, а потім об’єднайте гілку об’єкта в майстер.
Тім,

Відповіді:


108

Трохи про те, чому це відбувається:

Я дозволю 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

Я сподівався побачити, як дерево git для master відрізняється при використанні --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 та залежної_галузі, можливо, що функціональна_галузь може бути об'єднана та висунута, а хтось інший може додати щось суперечливе до того, як буде приземлено залежну-гілку.
Майк

0

Я щиро не погоджуюся з політикою "змішувати кожну розробку функцій у єдине комітування", але це їх заклик ...

Я б зберігав гілки як є, і створював змішаний коміт лише для публікації в спеціальній гілці. Можливість крок за кроком стежити за розробкою є цінною, навіть якщо керівництво не вірить у це. Позначте місця кабачків тегами у "реальних" гілках, ви також можете додати теги між сквошами з повідомленнями, що вказують назад на реальні коміти.


Мені насправді подобається це стиснення, але це тому, що його насправді робив арканіст, і весь огляд розробки / коміту / коду для гілки функції зберігається у фабрикаторі ... але я бачу вашу думку точно.
Mike
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.