Який найкращий спосіб скасувати злиття Git, яке видаляє файли з репо?


13

Тож уявіть, що трапляється наступне (і що ми всі використовуємо SourceTree):

  1. Ми всі працюємо на походження / розвиток.
  2. Я їду у відпустку на тиждень.
  3. Мій колега працює на місцевому рівні протягом останніх кількох днів, не зливаючись походженням / розвиваючись назад, до своєї місцевої галузі розвитку.
  4. Він намагається зробити поштовх, йому кажуть, що спочатку він повинен злитися, а потім робить потяг.
  5. У нього виникає конфлікт, зупиняючи процес автоматичного з’єднання після злиття.
  6. Припускаючи, що Git схожий на SVN, мій колега відкидає "нові" файли у своїй робочій копії, а потім здійснює злиття - витираючи ті "нові" файли з голови походження / розробки.
  7. Довершення цієї редакції триває тиждень, що вартує розробок.
  8. Повертаюсь з канікул і з’ясовую, що кілька днів моєї роботи не вистачає.

Всі ми дуже новинки в Git (це наш перший проект, який використовує його), але я зробив це, щоб виправити це:

  1. Перейменуйте "розвивати" на "розвивати_old".
  2. Об’єднайте develo_old у нову гілку "razvija_нову".
  3. Скиньте гілку develo_new до останнього комітету перед поганим злиттям.
  4. Вишня обирає кожне зобов’язання відтоді, по одному, вирішуючи конфлікти вручну.
  5. Підштовхуйте до розробки і розробляйте новіші до початку.

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

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


1
Чи можете ви опублікувати знімок екрана дерева git (відповідним чином відредагований) або вихід улюбленого git logформату з відповідними примітками про те, що сталося під час різних комітетів? (Я б редагував / коментував git log --graph --pretty=oneline --abbrev-commitта йшов звідти)

1
Для вас вже пізно, але одиничні тести це могли б наздогнати.
nalply

1
@nalply: Ні, якщо погане злиття також видалило одиничні тести.
Aaronaught

Ого, це справді підступна невдача.
nalply

Відповіді:


6

Якщо я правильно зрозумів, це ваша ситуація:

    ,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´

Після деякої спільної історії (о) ви зробили свою справу (y). Ваш колега (c) працював над його місцевим сховищем і зробив погане злиття (M). Згодом можуть бути додаткові коміти (а) поверх М.

git reset --hard develop M^2
git branch coworker M^1

Тепер ваш графік виглядає точно так, як перед поганим злиттям:

    ,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop

Зробіть хороше злиття (G):

git checkout develop
git merge coworker

Результат:

    ,-c--c--c--c-、
o--o--y--y--y--y--G ← develop

Тепер пересадіть додаткові зобов’язання:

git reset --hard X
git rebase --onto G M develop

Це дає кінцевий результат:

    ,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop

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

PS: звичайно , ви повинні замінити G, Mі Xв ваших командах з допомогою відповідної фіксації ід.


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

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

1

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

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

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

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


Я погоджуюсь, якщо цілі файли зникли, то це ви можете зробити, якщо це не переймається історією старих файлів: 1. зробіть нову гілку з поточно забрудненої гілки. 2.Відключіться до поганої гілки та зробіть ще одну нову гілку, яка є вашою гілкою порятунку. 3. З вашої гілки порятунку поверніться до комісії перед тим, як здійснити помилку. 4. Скопіюйте видалені файли десь поза git 5. Перейдіть до іншої нової гілки. 6. Скопіюйте нові версії видалених файлів у нову гілку та виконайте фіксацію. Існує більш складний спосіб збереження історії, це відомий пост Лінуса Т.
Елін

1
Насправді це показує, як можна користуватися касою jasonrudolph.com/blog/2009/02/25/… Це набагато приємніше.
Елін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.