Коли ви використовуєте Git rebase замість Git merge?


1545

Коли рекомендується використовувати Git rebase vs. Git merge?

Чи потрібно все-таки об'єднатись після успішної бази даних?




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

9
@static_rtti: Це просто неправда. Ви неправильно використовуєте потік на основі бази даних, якщо він не дозволяє регулярно натискати на зміни.
джузлін

5
Дуже шкода, що відповідь Ендрю Арнотта та відповідь Пейса не були опубліковані раніше, оскільки вони відповідають на це питання більш вичерпно, ніж попередні відповіді, які вже набрали багато голосів.
Марк Бут

Відповіді:


1135

Коротка версія

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

Отже, коли ви використовуєте будь-який з них?

Злиття

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

База даних

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

105
@Rob згадав про збереження проміжних комісій під час об'єднання. Я вважаю, що за замовчуванням об'єднання гілки B (гілка функції, над якою ви працювали) у гілку M ​​(головна гілка) створить один комікс у M для кожного комітету, який був зроблений у B з моменту розбіжності двох. Але якщо ви з’єднаєтесь за допомогою параметра --squash, всі комісії, зроблені на гілці B, будуть "зібрані разом" і об'єднані у вигляді єдиної комісії на гілці M, зберігаючи журнал на вашій головній гілці красивим та чистим. Сквошинг - це, мабуть, те, що ви хочете, якщо у вас є численні розробники, які працюють незалежно і об'єднуються назад у майстер.
spaaarky21

19
Я вважаю, що припущення @ spaaarky21 щодо об'єднання не є правильним. Якщо ви об'єднаєте гілку B у головний M, буде лише одна комісія на M (навіть якщо B має кілька комітів), незалежно від того, використовуєте ви звичайне чи - сквош злиття. Що - Squash зробить це усунути посилання на B як батьків. Гарна візуалізація тут: syntevo.com/smartgithg/howtos.html?page=workflows.merge
jpeskin

14
@jpeskin Це не те, що я бачу. Я просто зробив швидкий тест, щоб перевірити. Створіть каталог із текстовим файлом, initновим репо, addфайлом та commit. Оформити нову гілку функції ( checkout -b feature.) Змініть текстовий файл, введіть і повторіть так, щоб на гілці функції були два нові коміти. Тоді checkout masterі merge feature. В log, я бачу , моє початкове зобов'язання на господаря, а потім два , які були об'єднані з функцією. Якщо ви merge --squash feature, функція об'єднана в головний, але не скоєна, тож єдиним новим зобов’язанням майстра буде той, який ви зробите самі.
spaaarky21

21
@ spaaarky21 Схоже, ми обидва наполовину праві. Коли можливе швидке злиття вперед (як у вашому прикладі), git за замовчуванням включить усі коміти у гілку функції B (або, як ви запропонували, ви можете використовувати --squash для об'єднання в одну комісію). Але у випадку, коли є дві розбіжні гілки M і B, які ви зливаєте, git не буде включати всі індивідуальні коміти з гілки B, якщо їх об'єднати в M (незалежно від того, ви використовуєте - чи сквіш).
jpeskin

6
Чому це "(вам не байдуже підтримувати всі тимчасові зобов'язання)" осторонь цієї відповіді? У09 році це не мало сенсу, і зараз немає сенсу. Крім того, безумовно, ви хотіли б зробити повторне оновлення лише у тому випадку, якщо інший розробник вніс відповідні зміни, які вам потрібні - якщо вони внесли неспоріднені зміни, ваша галузь функцій все-таки повинна легко злитися без конфліктів, і ваша історія буде збережена.
Марк Бут

372

Це просто. За допомогою бази даних ви говорите про використання іншої гілки як нової бази для вашої роботи.

Якщо у вас є, наприклад, гілка master, ви створюєте гілку, щоб реалізувати нову функцію, і кажете, що ви її називали cool-feature, звичайно, головна гілка є базою для вашої нової функції.

Тепер у певний момент ви хочете додати нову функцію, яку ви реалізували у masterгалузі. Ви можете просто перейти на галузь masterі об'єднати її cool-feature:

$ git checkout master
$ git merge cool-feature

Але таким чином додається новий фіктивний комітет. Якщо ви хочете уникнути історії спагетті, ви можете перезавантажити :

$ git checkout cool-feature
$ git rebase master

А потім об'єднайте його в master:

$ git checkout master
$ git merge cool-feature

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


31
but this way a new dummy commit is added, if you want to avoid spaghetti-history- як це погано?
ア レ ッ ク ス

6
Також дуже корисний прапор злиття --no-ff.
Aldo 'xoen' Giambelluca

3
@ ア レ ッ ク ス, як користувач Sean Schofieldдодає це в коментарі: "Rebase також приємно, тому що, як тільки ти зрештою зливаєш ур речі назад у майстер (що тривіально, як уже було описано), ти маєш його сидіти на" вершині "історії ур. Фіксації. На більшій проекти, де функції можуть бути записані, але об'єднані через кілька тижнів, ви не хочете просто об'єднати їх у майстер, тому що вони "набиваються" на головний шлях ще в історії. Особисто мені подобається вміти робити журнал git і бачити ця остання функція прямо у верхній частині. Зверніть увагу, що дати фіксації збережені - база даних не змінює цю інформацію ".
Адріан.

4
Я думаю , що варто повторити тут - пам'ятати , що всі ці терміни ( merge, rebase, fast-forwardі т.д.) , мають в виду конкретних маніпуляцій спрямованого ациклического графа. Їм стає простіше міркувати про цю ментальну модель.
Рой Тінкер

10
@Aldo Немає нічого "чистого" чи "охайного" щодо перезавантаженої історії. Це взагалі брудно і IMHO жахливо, тому що ти поняття не маєш, що насправді відбувається. "Найчистіша" історія Git - це та, яка насправді мала місце. :)
Marnen Laibow-Koser

269

Щоб доповнити мою власну відповідь, згадану TSamper ,

  • Реалізація часто є хорошою ідеєю зробити перед об'єднанням, оскільки ідея полягає в тому, щоб ви інтегрували у свою галузь Yроботу гілки, Bна якій ви будете об'єднуватися.
    Але знову ж таки, перш ніж об’єднатись, ви вирішите будь-який конфлікт у вашій гілці (тобто: "rebase", як у "повторі моєї роботи у моїй гілці, починаючи з недавньої точки від гілки B).
    Якщо це зробити правильно, наступне злиття з вашої гілки гілка Bможе бути швидкою вперед.

  • злиття безпосередньо впливає на гілку призначення B, а це означає, що злиття краще бути тривіальними, інакше ця гілка Bможе задовго повернутися до стабільного стану (час для вирішення всіх конфліктів)


точка злиття після перезавантаження?

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

Інший сценарій ( описаний, наприклад, у Git Ready ), полягає в тому, щоб залучити вашу роботу безпосередньо за Bдопомогою ребайз (що дозволяє зберегти всі ваші приємні зобов’язання або навіть дати вам можливість повторно замовити їх через інтерактивну базу даних).
У тому випадку (де ви перезавантажуєтесь, перебуваючи у відділенні B), ви маєте рацію: більше злиття не потрібно:

Дерево Git за замовчуванням, коли ми не об'єднали і не перезавантажили

rebase1

ми отримуємо шляхом звільнення:

rebase3

Цей другий сценарій - це те, як повернути нову функцію в майстер.

Моя думка, описуючи перший сценарій перезавантаження, полягає в тому, щоб нагадати всім, що повторне використання також може бути використане як попередній крок до цього (що таке "повернення нової функції в майстер").
Ви можете використовувати ребазу для того, щоб спочатку привести головну "в" нову гілку функції: ребаза відтворить нові функції комітетів із HEAD master, але все ще в новій гілці функції, ефективно переміщуючи вихідну точку вашої гілки зі старої основної комісії HEAD-master.
Це дозволяє вирішувати будь-які конфлікти у вашій галузі (тобто, ізольовано, одночасно дозволяючи майстру продовжувати розвиватися паралельно, якщо етап розв'язання конфлікту триватиме занадто довго).
Тоді ви можете переключитися на "master" та "об'єднати" new-feature(або перезавантажити new-featureна них), masterякщо ви хочете зберегти виконані вами комісіїnew-feature відділення).

Тому:

  • "rebase та merge" можна розглядати як два способи імпортування твору, скажімо, на master.
  • Але "rebase then spage" може бути дійсним робочим процесом, щоб спочатку вирішити конфлікт у відриві, а потім повернути свою роботу.

17
злиття після повторної бази - це тривіальний швидкий шлях вперед, не потребуючи вирішення конфліктів.
obecalp

4
@obelcap: Дійсно, це така ідея: ви приймаєте всю проблему-конфлікт у своєму оточенні (майстер перезавантаження в межах вашої нової функції), а потім співпрацюєте, об'єднуєте нову функцію: 1 пікосекунд (швидко- вперед), якщо у майстра не було еволюцій
VonC

27
База даних також приємна тим, що, як тільки ви з часом з’єднаєте свої речі назад у майстер (що тривіально, як уже було описано), ви маєте його сидіти на «вершині» вашої історії комісій. У великих проектах, де функції можуть бути записані, але об'єднані через кілька тижнів, ви не хочете просто об'єднувати їх у головний, оскільки вони "забиваються" в головний шлях назад в історію. Особисто мені подобається вміти робити журнал git і бачити цю нещодавню функцію прямо вгорі. Зверніть увагу, що дати фіксації зберігаються - перезавантаження не змінює цю інформацію.
Шон Шофілд

3
@Joe: подумки, ви говорите "повторити будь-які мої зміни (зроблені окремо в моїй приватній гілці) поверх цієї іншої гілки, але залиште мене в моїй приватній гілці, коли буде виконано перезавантаження". Це гарна нагода очистити краєзнавство, уникаючи "контрольно-пропускних пунктів", порушених бісект та неправильних результатів вини. Дивіться "Git workflow": sandofsky.com/blog/git-workflow.html
VonC

4
@scoarescoare головне - побачити, наскільки локальні зміни сумісні над останньою гілкою вище. Якщо хтось із ваших зобов'язань введе конфлікт, ви побачите його відразу. Злиття вводить лише одну (злиту) комісію, яка може викликати безліч конфліктів без легкого способу зрозуміти, який із ваших власних місцевих зобов'язань додав зазначений конфлікт. Таким чином, крім більш чистої історії, ви отримуєте більш точне уявлення про зміни, які ви вводите, здійснюєте шляхом фіксації (відтворюється за допомогою повторної бази) на відміну від усіх змін, внесених гілкою вище за течією (скидається в одне єдине злиття).
VonC

229

TL; DR

Якщо у вас є сумніви, використовуйте об'єднання.

Коротка відповідь

Єдині відмінності між базою даних і об'єднанням:

  • Отримана структура дерева історії (як правило, помітна лише при перегляді графіка фіксації) відрізняється (одна матиме гілки, інша не буде).
  • Об'єднання, як правило, створить додатковий комікс (наприклад, вузол у дереві).
  • Об'єднання та повторне відновлення вирішать конфлікти по-різному. Rebase представляє конфлікти один за один раз, коли злиття представляє їх усі відразу.

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

Довга відповідь

Є кілька факторів, які слід враховувати, вибираючи, яку операцію використовувати.

Чи поділяється філія, до якої ви отримуєте зміни, від інших розробників поза вашою командою (наприклад, з відкритим кодом, загальнодоступними)?

Якщо так, не перезавантажуйте. Rebase знищує гілку, і ті розробники матимуть зламані / непослідовні сховища, якщо вони не використовують git pull --rebase. Це хороший спосіб швидко засмутити інших розробників.

Наскільки кваліфікована ваша команда розробників?

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

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

Чи сама філія представляє корисну інформацію

Деякі команди використовують модель розгалуження на особливості, де кожна гілка представляє особливість (або помилку, або підфункцію тощо). У цій моделі гілка допомагає визначити набори пов’язаних комітетів. Наприклад, можна швидко відновити функцію, повернувши об'єднання цієї гілки (якщо справедливо, це рідкісна операція). Або розрізняйте особливість, порівнюючи дві гілки (більш поширені). База даних знищила б гілку, і це не було б просто.

Я також працював над командами, які використовували модель філії на розробника (ми всі були там). У цьому випадку філія сама не передає додаткової інформації (у комітеті вже є автор). Не було б шкоди при відновленні.

Чи можете ви скасувати злиття з будь-якої причини?

Повернення (як і при скасуванні) ребазування є значно складним та / або неможливим (якщо в ребасті були конфлікти) порівняно з ревертуванням злиття. Якщо ви думаєте, що є ймовірність, що вам захочеться повернутись, скористайтеся об'єднанням.

Ви працюєте в команді? Якщо так, чи готові ви скористатися цією чи нічим підходою до цієї галузі?

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

Поширені міфи

Злиття знищує історію (стискає коміти)

Припустимо, що у вас є таке злиття:

    B -- C
   /      \
  A--------D

Деякі люди заявляють, що злиття "знищує" історію фіксації, тому що якби ви подивилися на журнал лише головного відділення (A - D), ви пропустили б важливі повідомлення комісій, що містяться в B і C.

Якби це було правдою, у нас не було б таких питань . В основному, ви побачите B і C, якщо ви прямо не попросите їх не бачити (використовуючи - first-parent). Це дуже просто спробувати на собі.

Rebase дозволяє забезпечити більш безпечне / просте злиття

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

База є крутішою / сексуальнішою / професійнішою

Якщо вам подобається псевдонім, rmщоб rm -rf"заощадити час", можливо, перезавантаження саме для вас.

Мої два центи

Я завжди думаю, що коли-небудь я натраплю на сценарій, коли Git rebase - це дивовижний інструмент, який вирішує проблему. Начебто я думаю, що я натраплю на сценарій, коли Git reflog - це чудовий інструмент, який вирішує мою проблему. Я працюю з Git вже більше п’яти років. Це не сталося.

Брудні історії ніколи насправді не були проблемою для мене. Я ніколи не просто читаю свою історію подій, як захоплюючий роман. Більшу частину часу мені потрібна історія, я все одно буду користуватися виною Git або Git bisect. У такому випадку, якщо зробити об'єкт злиття, мені фактично корисно, тому що якщо злиття запровадило проблему, це для мене змістовна інформація.

Оновлення (4/2017)

Мені потрібно обов'язково зазначити, що я особисто пом'якшив використання бази даних, хоча моя загальна порада все ще існує. Останнім часом я дуже багато взаємодію з проектом Angular 2 Material . Вони використовували базу даних, щоб зберегти дуже чисту історію фіксації. Це дозволило мені дуже легко побачити, яка фіксація виправлена ​​певним дефектом і включила чи ні ця комісія у реліз. Він слугує прекрасним прикладом правильного використання rebase.


5
Повинна бути підтверджена відповідь.
Mik378

Це, безумовно, найкраща відповідь. Особливо з уточненим зауваженням в останньому оновлення. Це допомагає зберігати історію git чистою та чистою, але безпечно користуватися нею.
zquintana

5
Я в основному люблю цю відповідь. Але: Rebase не робить "чистою" історією. Це робить більш лінійну історію, але це зовсім не те саме, адже хто зараз знає, скільки "бруду" ховається кожен комітет? Найчистіша, найясніша історія Git - це та, яка зберігає галузь і здійснює цілісність.
Marnen Laibow-Koser

3
"Поширений міф, ви бачите, що виконує B і C": Не обов'язково !! Ви фактично бачите B і C лише якщо злиття було швидким злиттям вперед, і це можливо лише тоді, коли конфліктів не було. Якщо виникають конфлікти, ви отримуєте єдине зобов’язання! Однак: Ви можете спочатку об'єднати головний елемент у функцію та вирішити там конфлікти, і якщо потім об'єднати функцію в головний, ви отримаєте компіляцію B і C, а один комікс X з (першого) злиття від головного в особливість вашої історії.
Джеремі Бенкс

дуже хороше пояснення! Це повинно підтримувати більше!
відмічає

185

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

Об'єднання не знищує ваші зобов’язання. Об’єднання зберігає історію! (просто подивіться на gitk) Rebase переписує історію, яка є поганою річчю після того, як ви її натиснули .

Використовуйте об'єднання - не перезавантажуйте кожен раз, коли ви вже натиснули.

Ось Лінус (автор Git) взяти його на себе (зараз він розміщений у моєму власному блозі, як його відновила машина Wayback ). Це справді добре прочитане.

Або ви можете прочитати мою власну версію тієї самої ідеї нижче.

Випуск філії на майстер:

  • дає неправильне уявлення про те, як створювалися комітети
  • забруднює майстра з купою проміжних комітетів, які, можливо, не були добре перевірені
  • насправді можна ввести перерви побудови для цих проміжних комітетів через зміни, які були внесені до того, коли було створено початкову галузь теми та коли вона була перезавантажена.
  • ускладнює пошук хороших місць у майстра для оформлення замовлення.
  • Причиняє, що часові позначки на комісіях не узгоджуються з їх хронологічним порядком у дереві. Отже, ви б побачили, що фіксація A передує вчиненню B у головному, але команда B спочатку була автором. (Що?!)
  • Породжує більше конфліктів, оскільки окремі вчинки у тематичній галузі можуть включати конфлікти злиття, які повинні бути вирішені індивідуально (надалі лежить в історії про те, що сталося в кожному комітеті).
  • це переписування історії. Якщо гілку, яку ви переоблаштовуєте, було висунуто куди завгодно (поділився з ким-небудь, крім вас самих), то ви накрутили всіх інших, хто має цю гілку, оскільки ви переписали історію.

На відміну від цього, об’єднання галузевої теми в головну:

  • зберігає історію створення тематичних гілок, включаючи будь-які злиття від головного до тематичного відділення, щоб допомогти підтримувати його актуальним. Ви дійсно отримуєте точне уявлення про те, з яким кодом працював розробник, коли вони будували.
  • master - це галузь, складена здебільшого злиттями, і кожен з цих об'єднань є типовими «хорошими балами» в історії, які можна перевірити, тому що саме там галузь теми була готова інтегруватися.
  • всі індивідуальні комісії теми теми зберігаються, включаючи той факт, що вони були в тематичній галузі, тому виділення цих змін є природним, і ви можете проаналізувати там, де потрібно.
  • Конфлікти злиття повинні бути вирішені лише один раз (в точці злиття), тому проміжні зміни в комісії, внесені в галузь теми, не повинні вирішуватися самостійно.
  • можна зробити багато разів плавно. Якщо ви інтегруєте свою тематичну гілку, щоб періодично освоювати, люди можуть продовжувати будувати тему, і вона може продовжувати об'єднуватися незалежно.

3
Крім того, у git merge є опція "--no-ff" (без швидкого перемотування вперед), яка дозволяє повернути всі зміни, внесені певним злиттям, дуже легко.
Тіаго

3
Тільки зробіть це більш зрозумілим: ви посилаєтесь на ситуацію, "коли ви вже натиснули" - це повинно бути сміливим. Посилання на пост Лінуса чудовий, btw., Пояснює це.
honzajde

2
але хіба не найкраща практика "оновити" від головного у своїй тематичній галузі, перш ніж об'єднати тему в головну за допомогою PR (щоб вирішити конфлікти у вашій галузі, а не головну)? Ми робимо це так, так що більшість галузевих тем мають як останню прихильність "об'єднати головну гілку в тему -...", але тут це вказано як "особливість" звільнення, і ніхто не згадує про це для об'єднання ...?
ПроблемиFoSumit

2
@AndrewArnott "Більшість тематичних гілок повинні бути спроможними об'єднатися без конфліктів у цільові гілки" Як це можливо, коли 20 розробників працюють на 30 гілках? Під час роботи над вашим буде злиття, тому, звичайно, вам доведеться оновити галузь теми від цілі, перш ніж створювати PR ... ні?
ПроблемиOfSumit

3
Не зазвичай, @Sumit. Git може добре об'єднати будь-який напрямок, навіть якщо зміни були внесені до однієї чи обох гілок. Тільки коли однакові рядки коду (або дуже близькі) будуть змінені на двох гілках, ви отримаєте конфлікти. Якщо це трапляється часто в будь-якій команді, команда повинна переосмислити, як вони розподіляють роботу, оскільки вирішення конфліктів є податком і сповільнює їх.
Ендрю Арнотт

76

TLDR: Це залежить від того, що є найважливішим - охайна історія чи правдиве подання послідовності розвитку

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

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

Об'єднання означає: Створіть нову нову комісію, яка об'єднує мої зміни в пункт призначення. Примітка. Ця нова комісія матиме двох батьків - остання фіксація з вашої рядки комітетів та остання комісія з іншої гілки, яку ви об’єднуєте.

Rebase означає: Створіть цілу нову серію комітетів, використовуючи мій поточний набір комітетів як підказки. Іншими словами, порахуйте, як виглядали б мої зміни, якби я почав вносити їх з того моменту, на який я відмовляюся. Тому після повторної бази даних, можливо, вам доведеться повторно перевірити свої зміни, і під час перезавантаження, можливо, виникнуть кілька конфліктів.

З огляду на це, чому ви б переобладнали? Просто, щоб історія розвитку була чистою. Скажімо, ви працюєте над функцією X, і коли ви закінчите, ви з’єднуєте свої зміни. Призначення тепер матиме єдиний комітет, який би сказав щось про те, що відповідає "Додана функція X". Тепер, замість злиття, якщо ви перезавантажувались, а потім об'єднувались, історія розвитку пункту призначення містила б усі індивідуальні комісії в єдиний логічний прогрес. Це набагато полегшує перегляд змін згодом. Уявіть, як важко вам переглядати історію розробок, якби 50 розробників постійно об’єднували різні функції.

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

Інший раз, коли ви захочете перезавантажити, це коли ви хочете позбутися від комісій зі своєї філії перед тим, як натиснути вище за течією. Наприклад: Коміти, які вводять якийсь код налагодження на початку, а інші здійснюють подальше очищення цього коду. Єдиний спосіб зробити це - виконати інтерактивну базу даних:git rebase -i <branch/commit/tag>

ОНОВЛЕННЯ: Ви також хочете використовувати ребазування, коли ви використовуєте Git для інтерфейсу до системи управління версіями, яка не підтримує нелінійну історію (наприклад, Subversion ). Під час використання моста git-svn дуже важливо, щоб зміни, які ви зливаєте назад у Subversion, були послідовним переліком змін на початку останніх змін у магістралі. Для цього є лише два способи: (1) відновити зміни вручну та (2) за допомогою команди rebase, що набагато швидше.

ОНОВЛЕННЯ 2: Один додатковий спосіб продумати ребайн - це те, що він дає змогу відобразити своєрідне відображення від вашого стилю розробки до стилю, прийнятого в сховищі, в яке ви збираєтесь. Скажімо, ви любите робити маленькі крихітні шматочки. У вас є одна фіксація виправлення помилки друку, одна фіксація для позбавлення від невикористаного коду тощо. На той час, коли ви закінчите те, що вам потрібно зробити, у вас є довга серія зобов'язань. Тепер скажімо, що сховище, яке ви здійснюєте, заохочує великі комісії, тому для роботи, яку ви виконуєте, можна було б очікувати одного чи, можливо, двох комітів. Як ви приймаєте рядок комітетів і стискаєте їх до того, що очікується? Ви б використовували інтерактивну базу даних і розбивали свої крихітні комбінезони на менші розміри. Те ж саме, якщо потрібен зворотній бік - якщо у вашому стилі було кілька великих змін, але сховище вимагало довгих рядків невеликих комітетів. Ви також використовуєте для цього ребазу. Якщо ви зробили об'єднання замість цього, ви тепер перенесли свій стиль фіксації в основний сховище. Якщо розробників багато, ви можете собі уявити, як важко буде прослідкувати історію з декількома різними стилями фіксації через деякий час.

ОНОВЛЕННЯ 3: Does one still need to merge after a successful rebase?Так, ви робите. Причина полягає в тому, що ребазація по суті передбачає "зміщення" комітетів. Як я вже говорив вище, ці коміти обчислюються, але якщо у вас було 14 коміттів з точки розгалуження, то припускаючи, що з вашою базою даних нічого не виходить, ви будете на 14 комірок вперед (від точки, на яку ви відновлюєте) після робиться ребаза. Ви мали відділення перед ребауз. Після цього у вас буде гілка такої ж довжини. Перед публікацією змін вам потрібно злитись. Іншими словами, перезавантажте стільки разів, скільки вам потрібно (знову ж таки, лише якщо ви не підштовхнули зміни вгору за течією). Об’єднайтеся лише після перезавантаження.


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

1
@mbx git mergeпідтримує --no-ffопцію, яка змушує її здійснити об'єднання.
Гавін С. Янцей

63

Хоча злиття, безумовно, є найпростішим і найпоширенішим способом інтеграції змін, але це не єдине: Rebase - це альтернативний засіб інтеграції.

Розуміння злиття трохи краще

Коли Git здійснює злиття, він шукає три коміти:

  • (1) Спільні предки. Якщо ви стежите за історією двох гілок у проекті, вони завжди мають принаймні одне спільне виконання: у цей момент часу обидві гілки мали однаковий зміст, а потім розвивалися по-різному.
  • (2) + (3) Кінцеві точки кожної гілки. Метою інтеграції є поєднання сучасних станів двох гілок. Тому їх відповідні останні перегляди представляють особливий інтерес. Поєднання цих трьох комітетів призведе до інтеграції, до якої ми прагнемо.

Швидкий перемотка вперед або об'єднання

У дуже простих випадках одна з двох гілок не має нових зобов’язань, оскільки відбулося розгалуження - остання фіксація все ще є загальним предком.

Введіть тут опис зображення

У цьому випадку виконання інтеграції є мертвим простим: Git може просто додати всі комітети іншої гілки на вершині загальної передачі предків. У Git цю найпростішу форму інтеграції називають "швидким вперед" злиттям. Тоді обидві гілки мають точну історію.

Введіть тут опис зображення

Однак у багатьох випадках обидві гілки рухалися вперед окремо.

Введіть тут опис зображення

Щоб здійснити інтеграцію, Git доведеться створити нову комісію, яка містить відмінності між ними - комісію злиття.

Введіть тут опис зображення

Людські коміти та об'єднання комітетів

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

Коміт злиття дещо інший: замість того, щоб створювати його розробник, він автоматично створюється Git. І замість того, щоб обгортати набір пов’язаних змін, його мета - з'єднати дві гілки, подібно до вузла. Якщо ви хочете зрозуміти операцію злиття пізніше, вам слід ознайомитись з історією обох гілок та відповідним графіком фіксації.

Інтеграція з Rebase

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

Введіть тут опис зображення

Давайте покроково проходимо операцію ребаїнгу. Сценарій такий самий, як і в попередніх прикладах: ми хочемо інтегрувати зміни з гілки B в гілку-A, але тепер, використовуючи rebase.

Введіть тут опис зображення

Ми зробимо це в три етапи

  1. git rebase branch-A // Synchronises the history with branch-A
  2. git checkout branch-A // Change the current branch to branch-A
  3. git merge branch-B // Merge/take the changes from branch-B to branch-A

По-перше, Git "скасує" всі комірки на гілці-A, що сталося після того, як рядки почали розгалужуватися (після того, як загальні предки здійснюють). Однак, звичайно, це не відкине їх: натомість ви можете вважати ці зобов'язання "тимчасово збереженими".

Введіть тут опис зображення

Далі, він застосовує комітети з гілки B, які ми хочемо інтегрувати. У цей момент обидві гілки виглядають абсолютно однаково.

Введіть тут опис зображення

На останньому кроці нові комітети для гілки-А тепер повторно застосовуються - але на новій позиції, поверх інтегрованих комітетів із гілки-В (вони засновані заново).

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

Введіть тут опис зображення

Нарешті, ви отримуєте чисту гілку гілки-A без небажаних та автоматично створених комісій.

Примітка: Взято з дивовижному поста по git-tower. У мінуси від rebaseтакож добре прочитати в тій же посаді.


+1 для дуже крутих діаграм. Я завжди хотів мати можливість подібним чином проілюструвати приклад git flow.
Мікаїл Абдуллаєв

60

Перед об'єднанням / відновленням:

A <- B <- C    [master]
^
 \
  D <- E       [branch]

Після git merge master:

A <- B <- C
^         ^
 \         \
  D <- E <- F

Після git rebase master:

A <- B <- C <- D' <- E'

(A, B, C, D, E і F - коміти)

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


30

Це речення отримує:

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

Джерело: 3.6 Git Branching - Rebasing, Rebase vs. Merge


25

Ця відповідь широко орієнтована навколо Git Flow . Таблиці були згенеровані за допомогою приємного генератора таблиць ASCII та дерев історії з цією чудовою командою ( псевдонімом як git lg):

git log --graph --abbrev-commit --decorate --date=format:'%Y-%m-%d %H:%M:%S' --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%ad%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'

Таблиці є у зворотному хронологічному порядку, щоб вони більше відповідали деревам історії. Дивіться також різницю між першим git mergeта git merge --no-ff(як правило, ви хочете використовувати git merge --no-ffйого, оскільки це робить вашу історію ближче до реальності):

git merge

Команди:

Time          Branch "develop"             Branch "features/foo"
------- ------------------------------ -------------------------------
15:04   git merge features/foo
15:03                                  git commit -m "Third commit"
15:02                                  git commit -m "Second commit"
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

* 142a74a - YYYY-MM-DD 15:03:00 (XX minutes ago) (HEAD -> develop, features/foo)
|           Third commit - Christophe
* 00d848c - YYYY-MM-DD 15:02:00 (XX minutes ago)
|           Second commit - Christophe
* 298e9c5 - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

git merge --no-ff

Команди:

Time           Branch "develop"              Branch "features/foo"
------- -------------------------------- -------------------------------
15:04   git merge --no-ff features/foo
15:03                                    git commit -m "Third commit"
15:02                                    git commit -m "Second commit"
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

*   1140d8c - YYYY-MM-DD 15:04:00 (XX minutes ago) (HEAD -> develop)
|\            Merge branch 'features/foo' - Christophe
| * 69f4a7a - YYYY-MM-DD 15:03:00 (XX minutes ago) (features/foo)
| |           Third commit - Christophe
| * 2973183 - YYYY-MM-DD 15:02:00 (XX minutes ago)
|/            Second commit - Christophe
* c173472 - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

git merge проти git rebase

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

Золоте правило git rebase- ніколи не використовувати його на громадських відділеннях.

Іншими словами :

Ніколи не переставляйте що-небудь, що десь штовхнули.

Я особисто додам: якщо це не особлива галузь І ви та ваша команда знаєте про наслідки .

Тож питання відносно git mergevs git rebaseстосується майже лише галузей функцій (у наступних прикладах --no-ffзавжди використовується при об'єднанні). Зауважте, що оскільки я не впевнений, що є одне краще рішення ( дебати існують ), я розкажу лише про те, як поводяться обидві команди. У моєму випадку я вважаю за краще використовувати, git rebaseоскільки це створює приємніше дерево історії :)

Між гілками функцій

git merge

Команди:

Time           Branch "develop"              Branch "features/foo"           Branch "features/bar"
------- -------------------------------- ------------------------------- --------------------------------
15:10   git merge --no-ff features/bar
15:09   git merge --no-ff features/foo
15:08                                                                    git commit -m "Sixth commit"
15:07                                                                    git merge --no-ff features/foo
15:06                                                                    git commit -m "Fifth commit"
15:05                                                                    git commit -m "Fourth commit"
15:04                                    git commit -m "Third commit"
15:03                                    git commit -m "Second commit"
15:02   git checkout -b features/bar
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

*   c0a3b89 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\            Merge branch 'features/bar' - Christophe
| * 37e933e - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar)
| |           Sixth commit - Christophe
| *   eb5e657 - YYYY-MM-DD 15:07:00 (XX minutes ago)
| |\            Merge branch 'features/foo' into features/bar - Christophe
| * | 2e4086f - YYYY-MM-DD 15:06:00 (XX minutes ago)
| | |           Fifth commit - Christophe
| * | 31e3a60 - YYYY-MM-DD 15:05:00 (XX minutes ago)
| | |           Fourth commit - Christophe
* | |   98b439f - YYYY-MM-DD 15:09:00 (XX minutes ago)
|\ \ \            Merge branch 'features/foo' - Christophe
| |/ /
|/| /
| |/
| * 6579c9c - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| |           Third commit - Christophe
| * 3f41d96 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/            Second commit - Christophe
* 14edc68 - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

git rebase

Команди:

Time           Branch "develop"              Branch "features/foo"           Branch "features/bar"
------- -------------------------------- ------------------------------- -------------------------------
15:10   git merge --no-ff features/bar
15:09   git merge --no-ff features/foo
15:08                                                                    git commit -m "Sixth commit"
15:07                                                                    git rebase features/foo
15:06                                                                    git commit -m "Fifth commit"
15:05                                                                    git commit -m "Fourth commit"
15:04                                    git commit -m "Third commit"
15:03                                    git commit -m "Second commit"
15:02   git checkout -b features/bar
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

*   7a99663 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\            Merge branch 'features/bar' - Christophe
| * 708347a - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar)
| |           Sixth commit - Christophe
| * 949ae73 - YYYY-MM-DD 15:06:00 (XX minutes ago)
| |           Fifth commit - Christophe
| * 108b4c7 - YYYY-MM-DD 15:05:00 (XX minutes ago)
| |           Fourth commit - Christophe
* |   189de99 - YYYY-MM-DD 15:09:00 (XX minutes ago)
|\ \            Merge branch 'features/foo' - Christophe
| |/
| * 26835a0 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| |           Third commit - Christophe
| * a61dd08 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/            Second commit - Christophe
* ae6f5fc - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

Від developдо функції функції

git merge

Команди:

Time           Branch "develop"              Branch "features/foo"           Branch "features/bar"
------- -------------------------------- ------------------------------- -------------------------------
15:10   git merge --no-ff features/bar
15:09                                                                    git commit -m "Sixth commit"
15:08                                                                    git merge --no-ff develop
15:07   git merge --no-ff features/foo
15:06                                                                    git commit -m "Fifth commit"
15:05                                                                    git commit -m "Fourth commit"
15:04                                    git commit -m "Third commit"
15:03                                    git commit -m "Second commit"
15:02   git checkout -b features/bar
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

*   9e6311a - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\            Merge branch 'features/bar' - Christophe
| * 3ce9128 - YYYY-MM-DD 15:09:00 (XX minutes ago) (features/bar)
| |           Sixth commit - Christophe
| *   d0cd244 - YYYY-MM-DD 15:08:00 (XX minutes ago)
| |\            Merge branch 'develop' into features/bar - Christophe
| |/
|/|
* |   5bd5f70 - YYYY-MM-DD 15:07:00 (XX minutes ago)
|\ \            Merge branch 'features/foo' - Christophe
| * | 4ef3853 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| | |           Third commit - Christophe
| * | 3227253 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/ /            Second commit - Christophe
| * b5543a2 - YYYY-MM-DD 15:06:00 (XX minutes ago)
| |           Fifth commit - Christophe
| * 5e84b79 - YYYY-MM-DD 15:05:00 (XX minutes ago)
|/            Fourth commit - Christophe
* 2da6d8d - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

git rebase

Команди:

Time           Branch "develop"              Branch "features/foo"           Branch "features/bar"
------- -------------------------------- ------------------------------- -------------------------------
15:10   git merge --no-ff features/bar
15:09                                                                    git commit -m "Sixth commit"
15:08                                                                    git rebase develop
15:07   git merge --no-ff features/foo
15:06                                                                    git commit -m "Fifth commit"
15:05                                                                    git commit -m "Fourth commit"
15:04                                    git commit -m "Third commit"
15:03                                    git commit -m "Second commit"
15:02   git checkout -b features/bar
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

*   b0f6752 - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\            Merge branch 'features/bar' - Christophe
| * 621ad5b - YYYY-MM-DD 15:09:00 (XX minutes ago) (features/bar)
| |           Sixth commit - Christophe
| * 9cb1a16 - YYYY-MM-DD 15:06:00 (XX minutes ago)
| |           Fifth commit - Christophe
| * b8ddd19 - YYYY-MM-DD 15:05:00 (XX minutes ago)
|/            Fourth commit - Christophe
*   856433e - YYYY-MM-DD 15:07:00 (XX minutes ago)
|\            Merge branch 'features/foo' - Christophe
| * 694ac81 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| |           Third commit - Christophe
| * 5fd94d3 - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/            Second commit - Christophe
* d01d589 - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

Бічні нотатки

git cherry-pick

Коли вам просто потрібна одна конкретна фіксація, git cherry-pickце приємне рішення ( -xопція додає рядок із написом " (вишня, вибрана з фіксації ...) " до початкового органу повідомлення про фіксацію, тому зазвичай корисно використовувати це - git log <commit_sha1>побачити це):

Команди:

Time           Branch "develop"              Branch "features/foo"                Branch "features/bar"
------- -------------------------------- ------------------------------- -----------------------------------------
15:10   git merge --no-ff features/bar
15:09   git merge --no-ff features/foo
15:08                                                                    git commit -m "Sixth commit"
15:07                                                                    git cherry-pick -x <second_commit_sha1>
15:06                                                                    git commit -m "Fifth commit"
15:05                                                                    git commit -m "Fourth commit"
15:04                                    git commit -m "Third commit"
15:03                                    git commit -m "Second commit"
15:02   git checkout -b features/bar
15:01   git checkout -b features/foo
15:00   git commit -m "First commit"

Результат:

*   50839cd - YYYY-MM-DD 15:10:00 (XX minutes ago) (HEAD -> develop)
|\            Merge branch 'features/bar' - Christophe
| * 0cda99f - YYYY-MM-DD 15:08:00 (XX minutes ago) (features/bar)
| |           Sixth commit - Christophe
| * f7d6c47 - YYYY-MM-DD 15:03:00 (XX minutes ago)
| |           Second commit - Christophe
| * dd7d05a - YYYY-MM-DD 15:06:00 (XX minutes ago)
| |           Fifth commit - Christophe
| * d0d759b - YYYY-MM-DD 15:05:00 (XX minutes ago)
| |           Fourth commit - Christophe
* |   1a397c5 - YYYY-MM-DD 15:09:00 (XX minutes ago)
|\ \            Merge branch 'features/foo' - Christophe
| |/
|/|
| * 0600a72 - YYYY-MM-DD 15:04:00 (XX minutes ago) (features/foo)
| |           Third commit - Christophe
| * f4c127a - YYYY-MM-DD 15:03:00 (XX minutes ago)
|/            Second commit - Christophe
* 0cf894c - YYYY-MM-DD 15:00:00 (XX minutes ago)
            First commit - Christophe

git pull --rebase

Я не впевнений, що можу це пояснити краще, ніж Дерек Гурлай ... В основному, використовуйте git pull --rebaseзамість git pull:) Однак, що у статті не вистачає, це те, що ви можете ввімкнути це за замовчуванням :

git config --global pull.rebase true

git rerere

Знову добре, тут пояснили . Але простіше кажучи, якщо ви це увімкнете, вам більше не доведеться вирішувати один і той же конфлікт кілька разів.


15

У книзі Pro Git є дійсно гарне пояснення на перезавантажувальній сторінці .

В основному злиття займе два коміти та об'єднає їх.

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

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

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


1
Злиття не поєднують коміти - це було б переписуванням історії. Rebase це робить.
kellyfj

4

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

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

Зробивши ребауз, ми також позбудемося додаткової комісії, яку ми звикли бачити, чи робимо ми нормальне злиття.

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


4

Якщо ви лише один розробник, ви можете використовувати rebase замість об'єднання, щоб мати чітку історію

введіть тут опис зображення


3

Деякі практичні приклади, дещо пов'язані з масштабною розробкою, де Герріт використовується для інтеграції огляду та доставки:

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

git fetch
git checkout origin/my_feature
git merge origin/master
git commit
git push origin HEAD:refs/for/my_feature

Я зливаюсь, коли готую доставку.

git fetch
git checkout origin/master
git merge --squash origin/my_feature
git commit
git push origin HEAD:refs/for/master

Я перезавантажую, коли моя доставка з будь-якої причини не вдається інтегрувати, і мені потрібно оновити її до нового віддаленого майстра.

git fetch
git fetch <gerrit link>
git checkout FETCH_HEAD
git rebase origin/master
git push origin HEAD:refs/for/master

3

Неодноразово пояснювалося, що таке база даних і що таке злиття, але коли слід використовувати що?

Коли слід використовувати rebase?

  • коли ви не відсунули гілку / ніхто більше не працює над нею
  • ви хочете повної історії
  • Ви хочете уникнути всіх автоматично створених повідомлень "злиття .."

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

Переконайтеся, що ви використовуєте git merge feature-branch --ff-onlyдля того, щоб не було конфліктів, створюючи єдиний фіксатор, коли ви об’єднуєте свою функцію до основної. Це цікаво, якщо ви використовуєте гілки функцій для кожного завдання, над яким ви працюєте, коли ви отримуєте історію гілки функцій, але не виконуються "об'єднані .."

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

Коли слід використовувати злиття?

  • коли ви відсунули гілку / інші теж працюють над нею
  • вам не потрібна повна історія
  • просто злиття досить добре для вас

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


-4

Коли я використовую git rebase? Майже ніколи, бо вона переписує історію. git mergeмайже завжди є кращим вибором, оскільки він поважає те, що насправді відбулося у вашому проекті.


1
@benjaminhull Дякую! - крім я сподіваюся, що моя відповідь заснована на фактах. Думка ІМХО мало місця в подібних речах: це факт, що втрата фактичної історії згодом ускладнює життя.
Marnen Laibow-Koser

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