Чи порушує запит на витягування алгоритм злиття git?


17

Зараз я працюю в компанії, яка використовує VSTS для управління git-кодом. "Рекомендований" спосіб об'єднання гілки Майкрософт - це зробити "злиття сквош", це означає, що всі зобов'язання для цієї гілки стискаються в один новий документ, який включає всі зміни.

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

Я можу створити гілку для цього елемента відставання та базувати її на першій гілці. Все йде нормально. Однак, коли настає час створити запит на тягу для мене другої гілки, перша гілка вже була об'єднана в головний і тому, що це було зроблено як злиття сквош, git розгортає купу конфліктів. Це тому, що git не бачить оригінальних комісій, на яких була заснована друга гілка, вона просто бачить одну велику сквош-злиття, і тому для того, щоб злити другу гілку в майстер, вона намагається відтворити всі зобов'язання першої гілки верх сквош зливається, викликаючи безліч конфліктів.

Отже, моє питання полягає в тому, чи є спосіб обійти це (окрім того, що ніколи не засновувати одну гілку функції на іншій, що обмежує мій робочий процес) або злиття сквош просто порушує алгоритм злиття git?

Відповіді:


15

З Git, чинить

  • незмінні,
  • і формують спрямований ациклічний графік.

Кабачки не поєднують комітів. Натомість він записує нове зобов’язання зі змінами з кількох інших комітетів. Випуск схожий, але не поєднує коміти. Запис нового комітету з тими ж змінами, що і існуючий комітет, називається переписуванням історії . Але оскільки існуючі комісії незмінні, це слід розуміти як "написання альтернативної історії".

Об’єднання намагається поєднати зміни двох історій (гілок) комірок, починаючи від спільного вчинку предків.

Тож давайте розглянемо вашу історію:

                                 F  feature2
                                /
               1---2---3---4---5    feature1 (old)
              /
-o---o---o---A---o---o---S          master

A - це загальний пращур, 1-5 - початкова гілка функції, F - нова гілка функції та S - стискається комірка, яка містить ті самі зміни, що й 1–5. Як бачимо, загальним предком F і S є А. Що стосується git, то між S та 1-5 немає зв’язку. Тож злиття майстра з S на одній стороні та функція2 з 1–5 з іншого буде суперечити. Вирішити ці конфлікти не складно, але це зайва, копітка робота.

Через ці обмеження існує два підходи для боротьби зі злиттям / розчавленням:

  • Або ви використовуєте переписування історії, і в цьому випадку ви отримаєте декілька комітетів, які представляють однакові зміни. Потім ви будете перезавантажувати другу гілку функції на стиснуту комітку:

                                     F  feature2 (old)
                                    /
                   1---2---3---4---5    feature1 (old)
                  /
    -o---o---o---A---o---o---S          master
                              \
                               F'       feature2
    
  • Або ви не використовуєте переписування історії, і в цьому випадку ви можете отримати додаткові об'єднання:

                                     F  feature2
                                    /
                   1---2---3---4---5    feature1 (old)
                  /                 \
    -o---o---o---A---o---o-----------M  master
    

    Коли об'єднати element2 та master, спільним предком буде 5.

В обох випадках ви докладете певних зусиль для об'єднання. Ці зусилля не сильно залежать від обраної із двох вищеописаних стратегій. Але переконайтесь у цьому

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

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


2
Ваша відповідь, схоже, не стосується того, що трапиться, якщо ви спершу з’єднаєте скрізь feature1на майстер, а потім хочете об'єднатись feature2пізніше. У такому випадку, чи не призведе перший підхід до конфліктів, оскільки git намагається повторно застосувати feature1комітети на вершині розбитого комітету, тоді як другий дозволить git визначити, що ці комісії не потрібно об'єднувати?
Jez

@Jez Це саме те, що відбувається, коли ти стискаєш PR. Нещодавно мені довелося вручну переписати PR на проект OSS (за git cloneдопомогою репо та копіювання змінених файлів!), Тому що я відгалужився від гілки, а потім супровідник видав першу гілку. На моїй роботі вони також роблять сквош злиття. Це означає, що я не можу працювати над функцією, bяка залежить від функції, aпоки функція aне об'єднана.
Викиньте рахунок

1
І хіба це не насправді дратівливий зрив чогось, що інакше спрацювало б, як покликаний git? Дивіться, я бачу, що різні організації, такі як Microsoft та Github, фактично рекомендують ці злиття сквош, і вони здаються мені німими.
Jez

1
@Jez У початковому сценарії так, ви отримаєте конфлікти при об'єднанні елемента2 у головний, оскільки об'єднання комірок 1–5 буде вступати в конфлікт із тими ж змінами в S. Рішення полягає в перезавантаженні функції2 (рішення 1) або не використовувати сквош / перезавантаження на всі (рішення 2).
амон

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

11

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

Ось чому наше неписане правило тут - це добре гасити, доки ніхто більше ніколи не залежав від вашої гілки, але це може бути 90% часу. Інакше пряме злиття допомагає всім уникати проблем.


Один із способів зберегти неповторний фільтр в історії історії та особливість гілки, щоб зробити окрему гілку, придатну лише для сквош. Припустимо, у вас є feature-xyzфілія. Ви можете створити feature-xyz-squashedгілку , починаючи з тим же зобов'язанням , як feature-xyzгілки, git cherry-pickщо здійснюють від feature-xyzдо feature-xyz-squashed, сквош їх там, і злиття feature-xyz-squashedз master. feature-xyzТоді ви не повинні зливатися . Іноді вищезгадане має сенс (наприклад, ви не хочете включати коміти з прокраданням пароля), але це обхідне рішення, навряд чи найкраща практика.
9000
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.