Отменить запрос на слияние?


159

Кто-то принял запрос на удаление, который не должен был быть. Теперь у нас есть куча неработающего кода. Как вы отмените запрос на удаление? Я просто собирался отменить изменения в коммите непосредственно перед слиянием, но я заметил, что он слился в кучу коммитов. Так что теперь есть все эти коммиты от этого человека за несколько дней до слияния. Как вы отмените это?


7
Несмотря на рекомендацию о принятом ответе, ПОЖАЛУЙСТА, не форсируйте принудительно в репозиторий, если репозиторий предоставлен кому-либо еще. Вы рискуете испортить работу, которую сделали другие, и GitHub может продолжать показывать этот запрос на слияние как слитый. Другой ответ на этот вопрос объясняет более безопасный способ отменить запрос на извлечение.
alxndr

2
Примечание: по крайней мере сейчас (июнь 2014 г.) GitHub предлагает кнопку «Возврат» в веб-интерфейсе запроса на извлечение. Смотрите мой ответ ниже
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
Это должен быть правильный ответ. На странице руководства 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 или аналогичной программы). Вы увидите коммиты из запроса на получение, и вы увидите свои собственные коммиты и коммит слияния (если это не было слияние с ускоренной перемоткой вперед). Вам просто нужно найти последний из ваших собственных коммитов перед слиянием и сбросить ветку на этот коммит.

(Если у вас есть ветвь reflog, еще проще найти коммит до слияния.)


(Изменить после получения дополнительной информации в комментариях :)

Хорошо, давайте посмотрим на график:

скриншот 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, чтобы переместить их в отдельную ветку и отправить новый запрос на извлечение.


Но у нас есть тонна коммитов между слиянием и его первым коммитом. Итак, у нас есть коммит слияния, наши коммиты и еще один коммит. Похоже, это слилось в его действительно старых коммитах.
Будет

Да, он слится со всем, что является предком объединенного коммита (а не предком вашего коммита). Это не должно помешать вам сбросить настройки - коммиты не будут переупорядочены сами по себе, если впоследствии вы не сделали ребаз.
Пауло Эберманн

1
Да, теперь это выглядит правильно (кроме странного слияния с самим собой - но это может быть сбой в программном обеспечении сетевого графика). :-) Я рад, что смог помочь.
Пауло Эберманн

6
Я думаю, что это может быть проблематично, если кто-то извлек плохие коммиты, и они позже отправляют запрос на извлечение, который содержит те же самые плохие коммиты, таким образом, они крадутся, но в репо. Не будет ли безопаснее создать новый коммит, который перевернет плохие коммиты? Таким образом, если плохие фиксации были перенесены в другие ветви / вилки, они будут эффективно удалены другим ветвлением в эту другую ветку / вилку? Я не констатирую это как факт, это то, что я думаю, может быть правдой, находясь в той же позиции, что и ФП, и потратил час или около того, рассматривая мои варианты.
Майлс МакДоннелл

4
@ Я бы предложил не принимать этот ответ. Это хорошо для кода, который еще не был передан (в этом случае это более актуальный вопрос SO, но для кода, который открыт для общего доступа, выполняя команду git, которая переписывает историю (в данном случае, reset --hardи принудительное нажатие очень плохая практика.) Ответ @errordeveloper ниже показывает способ сделать это без переписывания истории или принудительного толкания
asmeurer

34

Если тяга была последним, что он сделал, то

git reset --hard HEAD~1

3
будьте осторожны, следуя этой инструкции, она фактически отбросила мне 2 шага, а не один.
szeitlin

1
@szeitlin Как могло случиться, что тебе понадобилось 2 шага, а не один? Я знаю, что этот комментарий был оставлен 4+ года назад, но мне любопытно, если кто-нибудь знает ответ, как это могло бы произойти. Это очень важно для меня. Спасибо.
Городенец

Я не помню сейчас, но я предполагаю, что это могло произойти, если бы я сделал новый коммит, когда я попытался сбросить? Я бы просто проверил это с фиктивным репо, если вы беспокоитесь об этом.
Сейтлин

Этот работал хорошо для меня. Он удалил недавно слитый запрос на извлечение. После git reset --hard HEAD~1я использовал git push origin -fдля обновления удаленного хранилища. Но будьте осторожны, будьте осторожны, прежде чем делать это.
Денис Олука

24

Начиная с 24 июня 2014 года, вы можете легко отменить пиар (см. «Отмена запроса на удаление ») с помощью:

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

Вы можете легко отменить запрос на загрузку на GitHub, нажав «Восстановить»:

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

Вам будет предложено создать новый пул-запрос с отмененными изменениями:

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

Остается проверить, использует ли это возвращение -mили нет (также для отмены слияний)

Но Адиль Раза добавляет в комментариях (декабрь 2019):

Это ожидаемое поведение, он создал новую ветку, и вы можете создать PR из этой новой ветки в свою master.
Таким образом, в будущем вы можете отменить отмену, если это необходимо, это самый безопасный вариант, а не изменение напрямую master.


Предупреждение : Кораем отмечает в комментариях, что:

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

Кораем отсылает нас к « Github: Изменения игнорируются после возврата ( git cherry-pick, git rebase) » для более.


Я попробовал это, и он создал новую ветку вместо удаления PR на мастера?
Грозный

Странный. Не могли бы вы задать новый вопрос, чтобы проиллюстрировать это поведение?
VonC

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

1
@ AdilH.Raza Спасибо. Я включил ваш комментарий в ответ для большей наглядности.
VonC

1
Скрестив пальцы @VonC, это спасет разработчиков по всему миру от излишней агонии и потери времени
Кораем

8

Чтобы отменить GitHub Pull-запрос с коммитами, которые вы не хотите удалять, вы должны выполнить:

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

хеш коммита является коммитом перед слиянием запроса на извлечение. Это удалит все коммиты из запроса извлечения, не влияя на коммиты в истории.

Хороший способ найти это - перейти к теперь закрытому запросу и найти это поле:

Pull Request Image Pull Request Image

После того, как вы запустите git reset, выполните:

git push origin --force <branch name>

Это должно вернуть ветку обратно перед запросом извлечения, БЕЗ влияния на любые коммиты в ветви, переданные в историю коммитов между коммитами из запроса на извлечение.

РЕДАКТИРОВАТЬ:

Если вы нажмете кнопку возврата в запросе извлечения, это создаст дополнительную фиксацию в ветви. Он НЕ УСТАВЛЯЕТ и не растворяет. Это означает, что если вы нажмете кнопку возврата, вы не сможете открыть новый запрос на повторное добавление всего этого кода.


Отличный способ
уладить

Спасибо! Это было то, что я планировал сделать, но это было бы около ~ 200 коммитов, чтобы выбрать вишню.
FluffySamurai

1

Я использую это место все время, спасибо.

Я искал, как отменить запрос на получение и попал сюда.

Я собирался просто git reset --hard«давным-давно» и сделать перемотку назад туда, где я был, прежде чем сделать запрос на извлечение.

Помимо просмотра здесь, я также спросил своего коллегу, что он будет делать, и у него был типично хороший ответ: используя пример выходных данных в первом ответе выше:

git reset --hard 9271e6e

Как и в большинстве вещей в Git, если вы делаете это каким-то непростым способом, вы, вероятно, делаете это неправильно.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.