Повторное выполнение отмененного слияния в Git

Здесь у меня возникла небольшая проблема: у меня была ветка для конкретной проблемы 28s в Git, которую я объединил в общую ветку develop. Оказалось, что я сделал это слишком быстро, поэтому использовал git-revert, чтобы отменить слияние. Однако теперь пришло время объединить 28s в develop, но команда git-merge видит исходное объединение и с радостью сообщает, что все в порядке и ветви уже объединены. Что мне теперь делать? Создать коммит 'Revert "Revert" 28s -> develop ""'? Кажется, это не лучший способ сделать это, но на данный момент я не могу представить себе другого.

Как выглядит древовидная структура:

Вывод журнала Git


person Toms Mikoss    schedule 03.07.2009    source источник
comment
Это GitX (gitx.frim.nl).   -  person Toms Mikoss    schedule 06.07.2009


Ответы (8)


Вы должны «отменить возврат». В зависимости от того, как был восстановлен исходный файл, это может быть не так просто, как кажется. См. официальный документ по этому поводу тема.

---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 сделает это, даже не задумываясь.

Итак, с технической точки зрения нет ничего плохого в отмене слияния, но с точки зрения рабочего процесса этого обычно следует избегать.

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

  • разделите проблему пополам на ветку, которую вы слили, и просто исправьте ее,
  • или попробуйте отменить отдельную фиксацию, которая ее вызвала.

Да, это более сложно, и нет, это не всегда будет работать (иногда ответ: «ой, мне действительно не следовало объединять его, потому что он еще не был готов, и мне действительно нужно отменить все из слияния "). Итак, вам действительно следует отменить слияние, но когда вы хотите повторно выполнить слияние, вам теперь нужно сделать это, отменив откат.

person J-16 SDiZ    schedule 03.07.2009
comment
Хорошая ссылка (+1). Я взял на себя смелость скопировать часть документа в вашем ответе, чтобы читатели могли сразу увидеть соответствующие варианты в этом случае. Если вы не согласны, можете вернуться. - person VonC; 03.07.2009
comment
Мы просто столкнулись с ситуацией, когда нам нужно было это сделать, и обнаружили, что на этом веселье не заканчивается. Это была давно работающая ветка, которая была объединена, поэтому нам нужно было продолжать ее обновлять. Мой подход здесь: tech.patientslikeme.com/2010 / 09/29 / - person jdwyah; 29.09.2010
comment
Я подписался на сообщение в блоге @jdwyah, и это было великолепно (серьезно, было здорово, что это просто сработало). - person hellatan; 21.08.2013
comment
@jdwyah, это кажется неработающей ссылкой, но звучит как интересное чтение. Вот зеркало archive.org, но изображения отсутствуют: https://web.archive.org/web/20111229193713/http://tech.patientslikeme.com/2010/09/29/dealing-with-git-merge-revisions - person Alex KeySmith; 17.06.2014
comment
Другая ссылка, которая также предлагает отменить возврат: ссылка < / а>. - person funroll; 08.07.2014
comment
Я тоже подписался на пост @jdwyah. Это сработало отлично, я бы только изменил «git revert SHA_OF_THE_MERGE_REVERSION» на «SHA_OF_THE_REVERT_MERGE» или что-то подобное. - person mrmuggles; 24.10.2015
comment
отменить возврат: D. Не могу представить, что делаю это: D - person Ahmed Mahmoud; 05.06.2018

Предположим, у вас есть такая история

---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 отменен, и добавлены новые коммиты.

person Maksim Kotlyar    schedule 26.03.2013
comment
Похоже, это могло бы быть полезно, но в нем так мало деталей (что такое C, D на последней диаграмме), что это больше расстраивает, чем полезно. - person Isochronous; 29.06.2016
comment
@ Изохронные C и D кажутся коммитами, которые исправляют проблемы, представленные A и B. - person Thomas; 06.07.2017
comment
@ Томас точно - person Maksim Kotlyar; 06.07.2017
comment
Хорошо, что вы выделили использование PR в этом случае, поскольку оно может обеспечить окончательную «проверку работоспособности» перед слиянием с мастером. - person Willem van Ketwich; 05.09.2019
comment
использовать, почему вы перезапускаете ветку с исходного W? То есть, позвольте вашей теме продолжить с W, с W`, за которым следуют C и D? Это устраняет дублирование - person Erik Carstensen; 05.12.2019

Чтобы отменить возврат, не сильно нарушая рабочий процесс:

  • Создайте локальную копию файла develop
  • Отменить возвратную фиксацию на локальной копии разработки
  • Слейте эту копию в свою ветку функций и отправьте ветку функций на свой сервер git.

Теперь ваша функциональная ветка может быть объединена как обычно, когда вы будете к этому готовы. Единственным недостатком здесь является то, что у вас будет несколько дополнительных коммитов слияния / возврата в вашей истории.

person Sam Dufel    schedule 22.05.2017
comment
Чтобы предотвратить дальнейшее смешение, я также создал «мусорную» копию моей функциональной ветки и слил в нее возвращенную разработку. - person jhhwilliams; 01.02.2019
comment
Спасибо! Это единственный ответ, который на самом деле объясняет, как это делать, вместо того, чтобы говорить, что вы не должны этого делать. Действительно полезно. - person Emmy; 18.12.2019
comment
Спасибо, это мне очень помогло. :) - person Daniel; 09.04.2020
comment
это очень простой ответ. - person levi; 19.11.2020
comment
спасибо, мой случай был довольно простым, так что я полностью выполнил свою работу. Другие ответы тоже хороши, если вы находитесь в более сложной ситуации. - person subelsky; 05.02.2021

Чтобы отменить возврат в GIT:

git revert <commit-hash-of-previous-revert>
person Richard    schedule 09.08.2018
comment
Используя это в моей рабочей ветке, чтобы отменить возврат, а затем разработать новый PR. Теперь git видит все изменения, которые были в предыдущем PR, который был отменен. Спасибо. - person Danstan; 03.03.2020

Вместо использования 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).

person knweiss    schedule 05.07.2009
comment
Для тех, кто не очень хорошо знаком с git и может захотеть следовать этим инструкциям: осторожно комбинируйте reset --hard и push origin. Также имейте в виду, что принудительное нажатие на источник может действительно испортить открытые PR на GitHub. - person funroll; 08.07.2014
comment
Очень полезно для исправления некоторых проблем слияния на частном сервере git. Спасибо! - person mix3d; 25.06.2015
comment
+1 за эту технику. Потенциально разрушительно, но при разумном применении может избавить вас от головной боли (и искалечить историю). - person siliconrockstar; 25.05.2017

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

person Venkataraman R    schedule 28.02.2019

Я только что нашел этот пост, когда столкнулся с той же проблемой. Я считаю, что выше очень страшно делать сброс настроек и т. Д. Я в конечном итоге удалю то, что не хочу, и не смогу вернуть это.

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

person Claire    schedule 13.11.2017
comment
git reflog защитит вас от аппаратного сброса в течение нескольких месяцев, если вы позже обнаружите, что вам нужны потерянные коммиты. Рефлог ограничен вашим локальным репо. - person Todd; 06.01.2018

  1. создать новую ветку при фиксации до первоначального слияния - назовите ее «разработка-база»
  2. выполнить интерактивную перебазировку «develop» поверх «develop-base» (даже если она уже находится наверху). Во время интерактивной перебазировки у вас будет возможность удалить как фиксацию слияния, так и фиксацию, которая отменила слияние, то есть удалить оба события из истории git.

На этом этапе у вас будет чистая ветка «разработка», с которой вы сможете объединить свою функциональную ветвь, как вы это делаете обычно.

person Misha Mostov    schedule 17.04.2019
comment
Такой подход создаст проблему, если ветвь разработки используется совместно с другими. - person PSR; 30.03.2020
comment
Вероятно, это можно улучшить, перевернув его и принудительно перебазируя в противоположном направлении. Возьмите изменения из ветки, которая была возвращена, и воспроизведите их поверх отката, чтобы создать новую ветку, которую можно объединить после слияния, и вы получите немного более чистую историю по сравнению с довольно сложной для отслеживания откатом. - person AJ Henderson; 30.06.2021