Повторне відновлення злиття в Git


231

Тут я зіткнувся з певною проблемою: у мене була спеціальна гілка 28sв Git, що я об'єднався в загальну developгілку. Виявляється, я зробив це занадто швидко, тому я використав git-revert для скасування злиття. Тепер, однак, прийшов час , щоб об'єднати 28sв develop, але команда ГИТ-злиття бачить оригінальне злиття, і з радістю оголошує , що все добре і гілки були вже об'єднані. Що я зараз роблю? Створити команду "Повернути" Повернути "28 - -> розвинути" "? Здається, це не гарний спосіб зробити це, але наразі я не можу уявити жодного іншого.

Як виглядає структура дерева:

Вихід з журналу Git


Відповіді:


169

Ви повинні "повернути повернення". Залежно від вас, як повернувся оригінал, це може бути не так просто, як це звучить. Подивіться офіційний документ на цю тему .

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

дозволяти:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Але чи все це працює? Звичайно, це і є. Ви можете повернути злиття, і з чисто технічного кута, git зробив це дуже природно і не мав справжніх проблем.
Він просто вважав це зміною від "стану перед об'єднанням" до "стану після злиття", і це було все.
Нічого складного, нічого дивного, нічого насправді небезпечного. Git зробить це, навіть не думаючи про це.

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

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

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

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


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

5
Ми просто натрапили на випадок, коли нам це потрібно було зробити, і виявили, що веселощі не зовсім зупиняються тут. Це було об'єднане довге відділення, тому нам потрібно було продовжувати його оновлювати. Мій підхід тут: tech.patientslikeme.com/2010/09/29/…
jdwyah

Я пішов за публікацією в блозі @ jdwyah, і це було славно (серйозно, це було приголомшливо, що це просто працювало).
Геллатан

2
@jdwyah здається, що це зламане посилання, але це звучить як цікаве прочитання. Ось дзеркало archive.org, але у ньому відсутні зображення: web.archive.org/web/20111229193713/http://…
Alex KeySmith

15
Повідомлення в блозі було відновлено, дякую: blog.jdwyah.com/2015/07/dealing-with-git-merge-reitions.html
jdwyah

53

Припустимо, у вас така історія

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

Де A, B не вдалося здійснити, а W - повернення M

Тому перед тим, як почати виправляти знайдені проблеми, я роблю вишневий вибір W, щоб передати свою гілку

git cherry-pick -x W

Тоді я повертаю W-зобов’язання на своєму відділенні

git revert W 

Після того, як я можу продовжити виправлення.

Фінальна історія може виглядати так:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

Коли я надсилаю PR, це буде чітко видно, що PR скасовує, і додає деякі нові комісії.


3
Схоже, це може бути корисним, але настільки рідкісне в деталях (що таке C, D в останній схемі), що це більше засмучує, ніж корисно
Ізохронний

4
@Isochronous C і D, здається, є зобов'язаннями, які вирішують проблеми, введені A і B.
Томас

@Thomas точно
Максим Котляр

Добре, що ви виділили використання PR в цьому випадку, оскільки він може забезпечити остаточну перевірку здоровості перед тим, як повернутися до головного.
Віллем ван Кетвіч

використовуйте, чому ви перезапускаєте відділення з початкового W? Тобто, дозвольте вашій темі продовжуватись із W, з W`, а потім C і D? Це знімає деяке дублювання
Ерік Карстенсен

12

Щоб відновити відновлення, не надто сильно розкручуючи робочий процес:

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

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


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

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

Дякую, це мені справді допомогло. :)
Даніель Стракабошко

11

Щоб відновити відновлення в GIT:

git revert <commit-hash-of-previous-revert>

1
Використовуючи це у своїй робочій галузі, щоб повернути ревертування, а потім розвивати новий PR. Тепер git бачить усі зміни, які були в попередньому PR, який був повернений. Дякую.
Данстан

3

Замість використання git-revertви могли використовувати цю команду у develгілці, щоб викинути (скасувати) неправильну комісію злиття (а не просто повернути її).

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

Це також буде відповідно коригувати вміст робочого каталогу. Будьте уважні :

  • Збережіть свої зміни у гілці розробки (оскільки неправильне злиття), оскільки вони також буде стерто git-reset. Усі зобов’язання після того, який ви вказали як git resetаргумент, не буде!
  • Крім того, не робіть цього, якщо ваші зміни вже були витягнуті з інших сховищ, оскільки скидання перепише історію.

Рекомендую git-resetуважно вивчити цю сторінку, перш ніж спробувати.

Тепер, після скидання, ви можете повторно застосувати свої зміни, develа потім зробити

git checkout devel
git merge 28s

Це буде реальним злиття з 28sв develяк вихідної (який тепер стертого з історії Git і ).


8
Для всіх, хто не дуже добре знайомий з git і, можливо, захоче дотримуватися цих інструкцій: обережно з комбінуванням reset --hardта push origin. Також майте на увазі, що сильний поштовх до походження може дійсно придушити відкриті PR на GitHub.
funroll

Дуже корисно для вирішення деяких проблем з об'єднанням на приватному сервері git. Дякую!
mix3d

1
+1 для цієї методики. Потенційно руйнівно, але може заощадити чимало головного болю (і грізну історію), коли застосовувати його з розумом.
siliconrockstar

1

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

Замість цього я перевірив зобов’язання, на якому я хотів, щоб гілка повернулася до напр git checkout 123466t7632723. Потім перетворюється на відділення git checkout my-new-branch. Потім я видалив гілку, яку більше не хотів. Звичайно, це спрацює лише в тому випадку, якщо ви зможете викинути гілку, яку ви зіпсували.


1
git reflogЗахищатиме вас на жорсткий скидання в протягом декількох місяців в разі , якщо ви пізніше виявити , що вам потрібні втрачені коммітов. Рефлог обмежений місцевим репо.
Тодд

1

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

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote

Тепер створіть PR для галузі users/yourname/revertOfSHA1


1
  1. створити нову гілку на фіксації перед початковим злиттям - назвіть її "розвиваючою базою"
  2. виконувати інтерактивну базу даних «розвивати» поверх «розвивати-базу» (навіть якщо вона вже знаходиться на вершині). Під час інтерактивної бази даних ви матимете змогу видалити як комісію злиття, так і команду, яка перетворила злиття, тобто видалити обидві події з історії git

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


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