Git робочий процес та перезавантаження та злиття питань


970

Я вже пару місяців використовую Git для проекту з іншим розробником. Я маю декілька років досвіду роботи зі SVN , тому, мабуть, я приношу багато багажу на стосунки.

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

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

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature

По суті, створіть функціональну гілку, ЗАВЖДИ перезавантажтеся з головного на гілку та об'єднайтеся з гілки назад у головну. Важливо зазначити, що гілка завжди залишається локальною.

Ось робочий процес, з якого я почав

clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch

Є дві суттєві відмінності (я думаю): я використовую злиття завжди замість перезавантаження, і я висуваю свою функціональну гілку (і моя гілка функцій здійснює) до віддаленого сховища.

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

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

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

Який «правильний» робочий процес для подібного? Git повинен зробити розгалуження та злиття надлегким, і я просто не бачу цього.

Оновлення 2011-04-15

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

Виявляється, початковий робочий процес є правильним, принаймні в нашому випадку. Іншими словами, це те, що ми робимо, і це працює:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature

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

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature

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

Запити на отримання Github та Bitbucket (інші?) - Якщо вам цікаво, як злиття / перезавантаження стосується Pull Requests, я рекомендую дотримуватися всіх вищезазначених кроків до тих пір, поки ви не будете готові до злиття назад до майстра. Замість того, щоб вручну зливатися з git, ви просто приймаєте PR. Зауважте, що це не призведе до злиття сквош (принаймні, не за замовчуванням), але не сквош, не швидкий перемотка вперед - це прийнята конвенція про злиття в спільноті Pull Request (наскільки я знаю). Зокрема, це працює так:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin

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


31
На жаль, нова книга програмування Pragmstic здебільшого написана з використання Git, поки ще думаєш у SVN, і в цьому випадку тебе ввели в оману. У Git перезавантаження забезпечує прості речі, коли вони можуть бути. Ваш досвід може сказати вам, що ваш робочий процес не працює в Git, не що Git не працює.
Павло

18
Я б не рекомендував злиття сквошів у цьому випадку, оскільки це не економить інформацію про об'єднане (як svn, але тут немає mergeinfo).
Маріус К

7
Любіть ноту внизу, у мене був аналогічний досвід боротьби з Git, але зараз я намагаюся уявити, щоб не використовувати її. Спасибі за остаточне пояснення, дуже допомогло з rebaseрозумінням
Джон Phenow

6
Після того, як ви закінчите цю функцію, чи не повинні ви перезавантажуватись останній раз, перш ніж об’єднати new_feature в master?
softarn

17
Ваш робочий процес втрачає всю історію фіксації зі видаленої гілки :(
Макс Нанасі,

Відповіді:


371

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

Причина, чому ребаза тоді краща за злиття, полягає в тому, що:

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

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

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


На цю тему (перезавантажте потім об'єднайте робочий процес), barraponto в коментарях згадує два цікавих дописи, обидва з сайту randyfay.com :

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

(подібна техніка існує для базару )


27
Про техніку, яка дозволяє перезавантажувати та спільно використовувати, дивіться softwareswirl.blogspot.com/2009/04/…
mhagger

2
randyfay.com/node/91 та randyfay.com/node/89 - чудові записи . ці статті дали мені зрозуміти, що було пов'язано з моїм робочим процесом, і що таке ідеальний робочий процес.
Capi Etheriel

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

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

385

TL; DR

Робочий процес відновлення git не захищає вас від людей, які погано вирішують конфлікти, або людей, які звикли до робочого процесу SVN, як це пропонується у розділі " Уникання катастроф Git: Історія горі" . Це лише робить їх вирішення більш втомливим та ускладнює одужання від поганого вирішення конфлікту. Натомість використовуйте diff3 так, що це не так вже й складно.


Робочий процес ребазування не кращий для вирішення конфліктів!

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

Якщо під час злиття воно піде "все в пекло", воно перейде "все в пекло" під час перегляду бази даних, а також, можливо, і набагато більше пекла! Ось чому:

Причина №1: Вирішуйте конфлікти один раз, а не один раз для кожного вчинення

Коли ви перезавантажуєтесь замість злиття, вам доведеться виконати вирішення конфлікту до стільки ж разів, скільки у вас є зобов’язання перезавантажити, для того ж конфлікту!

Реальний сценарій

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

Коли настав час об'єднати мою гілку назад з master, у мене є два варіанти:

git merge: у мене конфлікт. Я бачу зміну, яку вони внесли, щоб освоїти і об'єднати її з (кінцевим продуктом) моєї галузі. Зроблено.

git rebase: у мене конфлікт із моїм першим вчиненням. Я вирішую конфлікт і продовжую перезавантаження. Я отримую конфлікт зі своїм другим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. Я маю конфлікт зі своїм третім зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт із моїм четвертим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт з моїм п'ятим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт з моїм шостим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт із моєю сьомоювчинити. Я вирішую конфлікт і продовжую перезавантаження. Я маю конфлікт зі своїм восьмим зобов’язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт з моїм дев'ятим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт з десятим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт зі своїм одинадцятим зобов’язанням. Я вирішую конфлікт і продовжую перезавантаження. Я отримую конфлікт зі своїм дванадцятим зобов’язанням. Я вирішую конфлікт і продовжую перезавантаження. Я маю конфлікт зі своїм тринадцятим зобов’язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт зі своїм чотирнадцятим зобов'язанням. Я вирішую конфлікт і продовжую перезавантаження. У мене конфлікт із п’ятнадцятимвчинити. Я вирішую конфлікт і продовжую перезавантаження.

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

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

Причина №2: З ребазами немає скасування!

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

Коли ви об’єднуєте гілку, git створює злиття, яке може бути відмінено чи змінено, якщо вирішення конфлікту буде поганим. Навіть якщо ви вже натиснули неправильну комісію злиття на публічне / авторитетне репо, ви можете git revertскасувати зміни, внесені об'єднанням, та повторно повторити злиття в новій комісії злиття.

Коли ви перезавантажуєте відділення, то, швидше за все, вирішення конфлікту буде зроблено неправильно, ви зірвались. Кожна комісія тепер містить неправильне злиття, і ви не можете просто повторити ребауз *. У кращому випадку вам потрібно повернутися та змінити кожен із порушених порушень. Не смішно.

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

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

Вийміть пекло з вирішення конфлікту: використовуйте diff3

Візьмемо для прикладу цей конфлікт:

<<<<<<< HEAD
TextMessage.send(:include_timestamp => true)
=======
EmailMessage.send(:include_timestamp => false)
>>>>>>> feature-branch

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

diff3 на допомогу!

git config --global merge.conflictstyle diff3

Коли ви використовуєте diff3, кожен новий конфлікт матиме 3-й розділ, об'єднаний спільним предком.

<<<<<<< HEAD
TextMessage.send(:include_timestamp => true)
||||||| merged common ancestor
EmailMessage.send(:include_timestamp => true)
=======
EmailMessage.send(:include_timestamp => false)
>>>>>>> feature-branch

Спершу вивчіть об’єднаного спільного предка. Потім порівняйте кожну сторону, щоб визначити наміри кожної гілки. Ви можете бачити, що HEAD змінив EmailMessage на TextMessage. Його мета полягає в тому, щоб змінити клас, який використовується для TextMessage, передаючи ті самі параметри. Ви також можете бачити, що ціль філії функції полягає в тому, щоб передати помилкове замість істинного для параметра: include_timestamp. Щоб об'єднати ці зміни, поєднайте наміри обох:

TextMessage.send(:include_timestamp => false)

В загальному:

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

Альтернативно: Вирішіть, вручну застосувавши зміни гілки

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

Давайте подивимось, як ми могли б вирішити конфлікт за сценарієм, де злиття, origin/feature1де lib/message.rbконфлікти.

  1. Вирішіть, чи є наша наразі перевірена гілка ( HEADабо --ours) або гілка, яку ми об’єднуємо ( origin/feature1або --theirs), - це більш проста зміна, яку слід застосувати. Використання diff з потрійною крапкою ( git diff a...b) показує зміни, що відбулися з bмоменту останнього розходження a, або, іншими словами, порівняйте спільного предка a і b з b.

    git diff HEAD...origin/feature1 -- lib/message.rb # show the change in feature1
    git diff origin/feature1...HEAD -- lib/message.rb # show the change in our branch
    
  2. Перевірте складнішу версію файлу. Це видалить усі маркери конфлікту і скористається обраною вами стороною.

    git checkout --ours -- lib/message.rb   # if our branch's change is more complicated
    git checkout --theirs -- lib/message.rb # if origin/feature1's change is more complicated
    
  3. Коли перевірена складна зміна, підтягніть відмінність простішої зміни (див. Крок 1). Застосовуйте кожну зміну з цієї різниці до конфліктуючого файлу.


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

8
Я відчуваю, що я вирішив причину в №1. Якщо окремі зобов’язання не є логічно послідовними, тим більше підстав об’єднати логічно послідовну гілку, щоб ви насправді мали сенс конфлікту. Якщо комірка 1 є помилковою, а фіксація 2 - виправляє її, об'єднання комірок 1 буде заплутаним. Є законні причини, через які ви можете отримати 15 конфліктів поспіль, як той, який я окреслив вище. Також ваш аргумент щодо того, що база даних не є гіршою, є дещо необгрунтованою. Rebase змішує погані злиття з початковими хорошими зобов’язаннями і не залишає хороших зобов’язань навколо, щоб ви могли спробувати ще раз. Злиття робить.
Едвард Андерсон

6
Я повністю згоден з вами нільбусом. Чудовий пост; що очищає деякі речі. Цікаво, чи не буде тут корисна допомога. Крім того, дякую за пропозицію щодо використання diff3, я обов'язково зараз перемкну його.
derick

45
+1 за те, що розповів мені про diff3 поодинці - як часто дивився на незрозумілий конфлікт, проклинаючи того, хто несе відповідальність за те, що він не сказав мені, що мав сказати спільний предок. Дуже дякую.
Іван,

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

32

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

Однак навіть у робочому процесі, що базується на ребазі, є місце для злиття.

Нагадаємо, що злиття фактично створює вузол, який має двох батьків. Тепер розглянемо таку ситуацію: у мене є два незалежні бренда A і B, і тепер я хочу розробити матеріали про функціональну галузь C, яка залежить як від A, так і від B, а A і B переглядаються.

Що я тоді роблю, це наступне:

  1. Створіть (і замовіть) відділення C поверх A.
  2. Об’єднайте його з B

Тепер гілка C включає зміни як A, так і B, і я можу продовжувати її розвивати. Якщо я зміню A, я реконструюю графік гілок таким чином:

  1. створити гілку T на новій вершині A
  2. злиття Т з В
  3. відновити C на T
  4. видалити гілку T

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


1
Тебе можна було досягти лише за допомогою ребасів. Злиття насправді тут не потрібне (за винятком випадків, коли ви не хочете дублювати коміти - але я навряд чи сприймаю це як аргумент).
odwl

1
Дійсно, я не хочу дублювати коміти. Я хотів би зберегти структуру польоту моєї роботи максимально чистою. Але це питання особистого смаку і не обов’язково підходить для всіх.
Алекс Гонтахер

Я на 100% погоджуюся з першим пунктом. (@ Відповідь Едварда працює там, де це не так, але я б краще, щоб усі проекти у світі працювали так, як ви пропонуєте). Решта відповіді здається трохи надуманою в тому сенсі, що робота над C, поки A і B триває, вже є настільки ризикованою (принаймні, наскільки це дійсно залежить від A і B), і навіть зрештою ви ймовірно, не буде тримати злиття (C буде переобладнано на вершину останніх та найкращих).
Алоїс Магдал

22

НЕ використовуйте git push origin --mirror ПІД ЧАС БУДЬ-ЯКОГО ВИСТАВКИ.

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

http://twitter.com/dysinger/status/1273652486


6
Або не робіть те, що ви не впевнені, який буде результат? Машина, яку я використовував для адміністрування, була Instructions to this machine may lead to unintended consequences, loss of work/data, or even death (at the hands of the sysad). Remember that you are solely responsible for the consequences of your actions в MOTD.
Річо

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

14

У мене є одне запитання, прочитавши ваше пояснення: Можливо, ви ніколи цього не робили

git checkout master
git pull origin
git checkout my_new_feature

перед тим як робити "git rebase / merge master" у своїй функції;

Оскільки ваша головна гілка не оновлюватиметься автоматично зі сховища вашого друга. Ви повинні це зробити з git pull origin. Тобто, ви б завжди базувались на ніколи не мінливій місцевій головній галузі? А потім настає час наштовхування, ви натискаєте на сховище, яке (локальне) здійснює ви ніколи не бачили, і, таким чином, натискання не вдається.


13

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

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

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

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


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

Ви не повинні дзеркально відображатись origin, ви повинні дзеркально відображатись у третьому виділеному резервному сховищі.
Міраль

12

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

Ні в партнері, ні в запропонованих робочих процесах ви не повинні стикатися з конфліктами, які не мали сенсу. Навіть якщо ви мали місце, якщо ви дотримуєтесь запропонованих робочих процесів, після розв’язання не потрібно вимагати «примусового» натискання. Це говорить про те, що ви насправді не злили гілку, до якої ви натискали, але вам довелося просунути гілку, яка не була нащадком віддаленого кінчика.

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

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


Ви маєте на увазі, що в ОП є якась невиявлена ​​база чи помилка в його процесі, правда?
krosenvold

7

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


7

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

  • Створіть нову гілку B із існуючої гілки A

  • Додати / ввести зміни у відділенні B

  • Оновлення бази даних у відділенні A

  • Об’єднання змін із гілки B у гілку A "

https://www.atlassian.com/git/tutorials/merging-vs-rebasing/


3

З Git немає "правильного" робочого процесу. Використовуйте все, що пливе ваш човен. Однак якщо у вас постійно виникають конфлікти під час об’єднання гілок, можливо, вам слід краще узгодити свої зусилля з колегами-розробниками? Схоже, що ви двоє продовжуєте редагувати одні і ті ж файли. Також слідкуйте за ключовими словами пробілу та підриву (наприклад, "$ Id $" та іншими).


0

Я використовую лише робочий процес rebase, тому що він візуально чіткіший (не тільки в GitKraken, але і в Intellij та в gitk, але я рекомендую найбільше перше): у вас є гілка, вона бере початок від master, і вона повертається до master . Коли діаграма буде чистою і красивою, ви будете знати, що ніколи нічого не йде в пекло .

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

Мій робочий процес майже такий самий, як і у вас, але лише з однією невеликою різницею: я squashвводяться в один у своєму місцевому відділенні, перш ніж rebaseмоя філія, щоб отримати останні зміни master, оскільки:

rebaseпрацює на основі кожного комітету

це означає, що якщо у вас 15 команд, змінюючи ту саму лінію master, що і ви, вам доведеться перевірити 15 разів, чи ви не сквош, але що важливо, це кінцевий результат, правда?

Отже, весь робочий процес такий:

  1. Отримайте замовлення masterта потягніть, щоб мати останню версію

  2. Звідти створіть нове відділення

  3. Робіть там свою роботу, ви можете вільно здійснювати кілька разів і натискати на віддалений, не хвилюйтесь, адже це ваша галузь.

  4. Якщо хтось скаже вам: "Ей, мій PR / MR затверджений, тепер він об'єднаний з головним", ви можете взяти їх / витягнути. Ви можете це зробити будь-коли або на етапі 6.

  5. Виконуючи всю свою роботу, виконайте їх, і якщо у вас є кілька комітетів, приберіть їх (вони всі ваші роботи, і скільки разів ви змінюєте рядок коду, значення не має; єдине важливе - остаточна версія). Натискати чи ні, не має значення.

  6. Зверніться до master, pullзнову ж таки, щоб переконатися, що у вас є найновіші masterмісцеві дані. Ваша схема повинна бути подібною до цієї:

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

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

  1. Отримайте замовлення назад у свою філію та перезавантажте майстер. Тепер у вас буде лише одна фіксація, тож ви вирішите конфлікти лише один раз . (І в GitKraken вам потрібно лише перетягнути свою гілку на masterта вибрати "Rebase"; ще одна причина, чому мені це подобається.) Після цього ви будете подібно до:

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

  1. Отож, у вас є всі зміни, що відбулися останні master, разом із змінами у вашій філії. Тепер ви можете натиснути на пульт, і, якщо ви натиснули раніше, вам доведеться змусити натиснути; Git скаже вам, що ви не можете просто просунутися вперед. Це нормально, через ребазу ви змінили початкову точку своєї філії. Але не варто боятися: використовуйте силу, розумно . Зрештою, пульт - це також ваша гілка, тому ви не впливатимете, masterнавіть якщо зробите щось не так.

  2. Створіть PR / MR та зачекайте, поки його буде затверджено master. Вітаю! Тепер ви можете оформити замовлення master, витягнути зміни та видалити локальну гілку, щоб очистити діаграму. Видалену гілку слід також видалити, якщо цього не зробити, коли ви об’єднаєте її в головний.

Кінцева схема знову чиста і чітка:

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

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