Отменить изменения, сделанные слиянием
Разработчик вносил небольшие изменения в два файла. Но во время этой фиксации у него был конфликт слияния, который удалил много вещей (вероятно, не имел последней актуальной версии). Затем он был перенесен на общее репо, а некоторые другие разработчики сделали некоторые другие коммиты.
Теперь мы заметили, что слияние удалило важные файлы, и мы хотим вернуть его обратно.
Как я могу это сделать, не теряя изменений со следующих коммитов?
Я пытался git revert commitsha
, но он не внес изменений. Нужно ли возвращать обратно mergesha
? Как я могу его определить?
Ответы
Ответ 1
мерзавец вернуться --mainline
Обычно:
git revert --mainline 1 dd8cbe3e4
Куда:
-
dd8cbe3e4
- dd8cbe3e4
коммит слияния, который вы хотите отменить, и -
--mainline
сообщает вам, какой из нескольких предыдущих --mainline
нужно восстановить (помните, что коммит слияния имеет несколько родительских коммитов, и вы можете оставить только один из них). - Я не могу найти хорошее объяснение того, что означает
1
, но я предполагаю, что 1,2,3...
соответствует списку сопоставлений с dd8cbe3e4
непосредственно перед dd8cbe3e4
, отсортированным по возрастанию в хронологическом порядке (самый старый - первый - который обычно это то, к чему вы хотите вернуться).
Источник:
http://thezencoder.com/2013/09/05/how-to-correctly-revert-a-bad-merge-in-git/
Ответ 2
Короче говоря, ПРЕДУПРЕЖДЕНИЕ: нет реального безопасного способа свернуть объединение, за исключением того, что на самом деле reset ветвь должна быть зафиксирована до слияния.
Позвольте мне объяснить и просмотреть существующую ссылку.
Цитата связанного ответа от Как вы отменили ошибку git commit merge commit
В принципе, возврат слияния отменяет изменения данных, , но не изменения истории (графика). Поэтому ожидается, что возврат вашего ошибочного слияния ничего не делает.
Конечно, сброс ветки будет самым простым, но у него есть недостатки, если результат слияния уже был перенесен на общий репо (потому что вы эффективно переписываете опубликованную историю).
Вот пробой
-
git merge <someref>
для объединения (необязательно commit после разрешения конфликтов)
-
Если вы сразу узнаете, что хотите reset ветвь до слияния:
git reset [email protected]{1}
# optionally pass --hard to reset the working tree too
-
если вы узнали только позже,
-
используйте reflog, чтобы найти точку перед слиянием. ([email protected]{1}
коротко для предыдущего значения текущей ссылки головки, но reflog отслеживает ограниченную историю значений для справки головы)
git reflog
-
reset ветвь
git reset [email protected]{n} # substitute reflog entry index
-
необязательно rebase/cherry-pick коммиты, сделанные после слияния
git cherry-pick [email protected]{1} # just an example. interactive tools will make this easier
Ответ 3
Другой (более безопасный) подход - создать разницу между последним домом и текущей версией файла, а затем восстановить потерянные части с помощью copy & paste.
Это всегда работает, не требует каких-либо нечетных параметров командной строки, и это не влияет на вещи, которые вы должны оставить в покое: -)
Eclipse, например, имеет хорошие инструменты для вишни, чтобы выбрать каждую отдельную разницу и скопировать ее в любую версию. Просто используйте меню "Сравнить", чтобы открыть обе версии рядом.
Ответ 4
Короче говоря, вы можете сделать git reset --soft <commit>
где commit может быть HEAD^
(предыдущий), HEAD~2
(текущий-2), SHA и т.д.
С помощью --soft все изменения будут готовы к фиксации, поэтому вы можете действительно изменить фиксацию. С помощью - все изменения будут потеряны.
После того, как вы изменили фиксацию, вам нужно принудительно нажать на изменения в общем репо с помощью git push --force
.
Обратите внимание, что вам нужно будет сказать другим разработчикам, что они должны переупаковывать свои репозитории на общий репо. (используйте git pull --rebase
). Они могут получить некоторые конфликты слияния, хотя... Пожалуйста, имейте это в виду.