Скасувати злиття, потягнувши запит?


159

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


7
Незважаючи на поради прийнятої відповіді, БУДЬТЕ, не натискайте на сховище, якщо репортаж буде надано кому-небудь іншим. Ви ризикуєте зіпсувати роботу, яку зробили інші, і GitHub може продовжувати показувати запит на витяг як об'єднаний. Інша відповідь на це питання пояснює більш безпечний спосіб скасувати запит на витяг.
alxndr

2
Примітка: принаймні зараз (червень 2014 року) GitHub пропонує кнопку "Повернути" у своєму веб-інтерфейсі Pull Request. Дивіться мою відповідь нижче
VonC

1
Проблема з кнопкою повернення полягає в тому, що вона створює нове зобов’язання як зворотний запит на витяг, а це означає, що якщо ви хочете врешті-решт об'єднати ці зміни, використання кнопки "Повернути" може зробити це набагато складніше.
FluffySamurai

Відповіді:


159

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

Вам потрібно буде придбати та перевірити останні зміни в потоці, наприклад:

git fetch upstream
git checkout upstream/master -b revert/john/foo_and_bar

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

commit b76a5f1f5d3b323679e466a1a1d5f93c8828b269
Merge: 9271e6e a507888
Author: Tim Tom <tim@tom.com>
Date:   Mon Apr 29 06:12:38 2013 -0700

    Merge pull request #123 from john/foo_and_bar

    Add foo and bar

commit a507888e9fcc9e08b658c0b25414d1aeb1eef45e
Author: John Doe <john@doe.com>
Date:   Mon Apr 29 12:13:29 2013 +0000

    Add bar

commit 470ee0f407198057d5cb1d6427bb8371eab6157e
Author: John Doe <john@doe.com>
Date:   Mon Apr 29 10:29:10 2013 +0000

    Add foo

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

У наведеному вище прикладі комісія злиття - це головна, де написано "Об’єднаний запит на витяг № 123 ..." .

Зробіть це, щоб відновити обидві зміни ( "Додати смугу" та "Додати foo" ), і ви закінчите в одному фіксації повернення всього запиту на витяг, який ви можете пізніше відновити і зберегти історію змін:

git revert -m 1 b76a5f1f5d3b323679e466a1a1d5f93c8828b269

6
Це має бути правильна відповідь. На сторінці Man git-revert є посилання на детальнішу інформацію зі списку розсилки git тут kernel.org/pub/software/scm/git/docs/howto/…
Джастін Хамаде

2
Чому git checkout upstream/master -b revert/john/foo_and_bar? що це робить саме?
Магне

4
@Magne - ви створюєте нову гілку для відновлення, в якій потім зможете вибрати, де об'єднати реверсію. В основному просто дає більше контролю над тим, що робити з філією. У моєму випадку я подав новий запит на витяг із цієї "фіксованої" гілки, що містить зворотну сторону назад, до нашої гілки розвитку, а це означає, що мій новий запит також може бути відмінений у разі необхідності. Це було зроблено для випуску, де ми вирішили витягнути перший проект функції, який був перенесений. Ніякого поганого коду, просто не збираючись у цьому випуску.
Даніель Налбах

3
На цьому я навчився важкого уроку. Ми перенесли цю функцію в нашу галузь розробки, але зрозуміли, що виникають проблеми з даними та повернулися безпосередньо на розробку. Пізніше, коли все було виправлено, ми хотіли додати нові функції розробки до цієї гілки, щоб перевірити їх сумісність із цією функцією перед натисканням, тому я об'єднав розробку назад у гілку функцій. Сюди також застосовано реверсивний комітет, який скасовував кожну зміну, внесену до гілки функцій. > <
Грег

86

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

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


(Редагуйте після додаткової інформації в коментарях :)

Гаразд, давайте подивимось на графік:

скріншот 1

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

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

Скиньте це зобов’язання, і вам слід добре.

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

git checkout master
git reset --hard 7a62674ba3df0853c63539175197a16122a739ef
gitk 

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

git push -f origin master

(якщо ваш пульт дистанційного управління github названий origin- інакше змініть ім'я).

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

(Можливо, для Github існує певний спосіб зробити те саме, але я не надто знайомий з Github та його системою управління запитами на тягу.)

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

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

На майбутнє:

Якщо ви хочете лише деякі з філій філії RogerPaladin, подумайте про використання cherry-pickзамість merge. Або зв’яжіться з RogerPaladin, щоб перемістити їх до окремої гілки та надіслати новий запит на виклик.


Але ми маємо тону комітетів між об'єднанням та його першим зобов'язанням. Так, як ми маємо зобов'язання злиття, наші власні зобов’язання, а потім ще одне вчинення ним. Схоже, він злився у справді старих його комісіях.
Буде

Так, воно злиється у всьому, що є родоначальником об'єднаного комітету (а не є родоначальником вашого вчинку). Це не повинно перешкоджати перезавантаженню - комісії не будуть переупорядковані самі собою, якщо після цього ви не зробили перезавантаження.
Paŭlo Ebermann

1
Так, зараз це виглядає правильно (крім дивного злиття в собі - але це може бути проблемою в програмному забезпеченні мережевих графіків). :-) Я радий, що можу допомогти.
Paŭlo Ebermann

6
Я думаю, що це може бути проблематично, якщо хтось потягнув погані зобов’язання, і вони пізніше надсилають запит на витяг, який містить такі самі погані зобов’язання, таким чином вони підкрадаються, але потрапляють у репо. Чи не було б безпечніше створити нове зобов'язання, яке скасовує погані зобов'язання? Таким чином, якщо погані комірки були перетягнуті на інші гілки / вилки, вони будуть ефективно усунені іншим потягом до цієї іншої гілки / вилки? Я не констатую це як факт, я вважаю, що це може бути правдою, перебуваючи в тому самому становищі, що і ОП, витративши годину або близько того, розглядаючи свої варіанти.
Майлз МакДоннелл

4
@ Я б запропонував не прийняти цю відповідь. Це добре для коду, який ще не було натиснуто (у такому випадку це більш відповідне питання SO, але для коду, який публікується публічно, виконуючи команду git, яка переписує історію (у цьому випадку, reset --hardа натискання - це Дуже погана практика). Відповідь від @errordeveloper нижче показує спосіб зробити це без переписування історії або примусового натискання.
asmeurer

34

Якщо витяг був останнім, що він зробив тоді

git reset --hard HEAD~1

3
Будьте уважні, дотримуючись цієї інструкції, вона насправді повернула мені два кроки, а не один.
szeitlin

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

Зараз я не пам’ятаю, але гадаю, що це могло б статися, якби я зробив нове зобов’язання, коли спробував скинути? Я б просто випробував це з фіктивним репо, якщо ви переживаєте за це.
szeitlin

Цей добре працював на мене. Це видалено нещодавно об'єднаний запит на витяг. Після цього git reset --hard HEAD~1я git push origin -fоновлював віддалений сховище. Але будьте обережні, будьте обережні, перш ніж це робити.
Денис Олука

24

Починаючи з 24 червня 2014 року, ви можете легко спробувати скасувати PR (див. " Повернення запиту на виклик ") за допомогою:

Представляємо кнопку повернення

Ви можете легко відновити запит на витяг на GitHub, натиснувши Відновити:

https://camo.githubusercontent.com/0d3350caf2bb1cba53123ffeafc00ca702b1b164/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656c702f70756c6c5f72657175657374732f7265766572742d70756c6c2d726571756573742d6c696e6b2e706e67

Вам буде запропоновано створити новий запит на витягнення з відміненими змінами:

https://camo.githubusercontent.com/973efae3cc2764fc1353885a6a45b9a518d9b78b/68747470733a2f2f6769746875622d696d616765732e73332e616d617a6f6e6177732e636f6d2f68656c702f70756c6c5f72657175657374732f7265766572742d70756c6c2d726571756573742d6e65772d70722e706e67

Залишається перевірити, хоча це відновлення використовує -mчи ні (також для відновлення злиття)

Але Аділ Н Раза додає у коментарях (грудень 2019 р.):

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


Попередження : Кораєм вказує у коментарях , що:

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

Korayem посилається на нас " Github: Зміни, ігноровані після відновлення ( git cherry-pick, git rebase) ", можна отримати більше.


Я спробував це, і це створило нову гілку замість того, щоб скасовувати PR на майстра?
Грозный

Дивно. Чи можете ви задати нове запитання, щоб проілюструвати таку поведінку?
VonC

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

1
@ AdilH.Raza Дякую Я включив ваш коментар у відповідь для більшої наочності.
VonC

1
@VonC пальці перетнули це врятує розробників по всьому світу від занадто великої агонії та марної
трати

8

Щоб скасувати запит на тягнення github з комісіями, які ви не хочете видаляти, потрібно виконати:

git reset --hard --merge <commit hash>

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

Хороший спосіб знайти це - перейти до закритого запиту на витягнення та знайти це поле:

Витягніть Запит зображення Витягніть Запит зображення

Після запуску програми git resetзапустіть:

git push origin --force <branch name>

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

Редагувати:

Якщо ви хочете натиснути кнопку повернення у запиті про витягнення, це створює додаткову комісію для гілки. Він НЕ розмикає і не відриває. Це означає, що якщо ви натиснули кнопку повернення, ви не зможете відкрити новий запит на повторне додавання всього цього коду.


Чудовий спосіб виправити речі, не потребуючи божевільної реверсії або вишні
Cumulo Nimbus

Дякую! Це те, що я планував робити, але це було б близько ~ 200 зобов’язань, щоб вишня вибирала.
FluffySamurai

1

Я постійно користуюся цим місцем, дякую.

Я шукав, як скасувати запит на витяг, і потрапив сюди.

Я збирався просто git reset --hard"давно" і зробити швидкий перемотка назад туди, де я був, перш ніж робити запит на тягу.

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

git reset --hard 9271e6e

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

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