Отмените Git-слияние, которое еще не было перенесено

3946

В моей основной ветке я делал git merge some-other-branchлокально, но никогда не выдвигал изменения в мастер-начало. Я не хотел сливаться, поэтому я хотел бы отменить это. При выполнении git statusпосле слияния я получал следующее сообщение:

# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.

На основании некоторых инструкций, которые я нашел , я попытался запустить

git revert HEAD -m 1

но теперь я получаю это сообщение с git status:

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

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

Мэтт Хаггинс
источник
3
Если вам нужно сохранить историю, другими словами, есть изменение, которое кто-либо когда-либо извлек из вас, или вы куда-то его подтолкнули, используйте решение в ответе Юрия Ушакова ниже!
Седрик
6
Пожалуйста, отмените текущий выигрышный ответ, это небезопасно (как многие отмечали), хотя все еще набирает голоса. Для меня "MBO" -s выглядит лучше, хотя у него гораздо меньше очков.
Зингер
5
Если вам нужно сохранить историю , используйте решение Юрия внизу ! (просто добавив ссылку на комментарий @Sedrik)
cregox
3
Это отличный ресурс прямо из Github: Как отменить (почти) что-нибудь с помощью Git
jasonleonhard

Ответы:

4462

С git reflogпроверкой, какой коммит перед слиянием ( git reflogбудет лучшим вариантом, чем git log). Затем вы можете сбросить его, используя:

git reset --hard commit_sha

Есть и другой способ:

git reset --hard HEAD~1

Это вернет вам 1 коммит.

Имейте в виду, что любые измененные и незафиксированные / неснятые файлы будут сброшены в их неизмененное состояние . Чтобы сохранить их, либо спрятать изменения, либо см. --mergeОпцию ниже.


Как @Velmont предложил ниже в своем ответе, в этом прямом случае используется:

git reset --hard ORIG_HEAD

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


Еще один совет - использовать --mergeпереключатель вместо, --hardтак как он не сбрасывает файлы без необходимости:

git reset --merge ORIG_HEAD

--merge

Сбрасывает индекс и обновляет файлы в рабочем дереве, которые отличаются между <commit> и HEAD, но сохраняет те, которые отличаются между индексом и рабочим деревом (т. Е. С изменениями, которые не были добавлены).

Марцин Гил
источник
129
Я не думаю, что это будет (всегда?) Работать - «один перед слиянием» будет самым последним коммитом, который был объединен из другой ветки - это не будет самый последний коммит в текущей ветке , Правильно? (Это может быть просто результатом того, что git logвыбрано для отображения по умолчанию - может быть, есть другой вывод git logили git reflogможет быть использовано для этого)
Джон Башир
6
Я думаю, это может зависеть от того, слите ли вы сквош.
Марцин Гил
29
@JohnBachir прав. В git logвыводе вы хотите посмотреть на два родительских коммита. Один из них - последний коммит в вашей ветке, второй - последний коммит в ветке, в которую вы вошли. Вы хотите, чтобы git reset --hardродительский коммит на ветви, в которую вы слились.
Джастин
7
@JohnBachir: до тех пор, пока «слияние» на самом деле не быстрое продвижение вперед, оно приведет к новой фиксации, которая находится в верхней части журнала, и у этой фиксации есть два родителя (или более 2, если вы делаете осьминога). слияния). Если вы удалите этот коммит слияния, то все старые коммиты, пришедшие из слияния, тоже исчезнут. Однако, чтобы быть в безопасности, после сброса git скажет вам, где находится новый заголовок: «HEAD сейчас на 88a04de <сообщение коммита>». Я всегда смотрю на это, чтобы убедиться, что я оказался там, где ожидал. Мой проект использует стандартную схему именования веток, чтобы сохранить вещи запоминающимися.
Марк Э. Хаас
44
Что я нашел полезным, так это посмотреть на «git reflog» и посмотреть последний коммит, который я сделал в master. Тогда сделайgit reset --hard <commit_sha>
Макс Уильямс
1456

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

git reset --hard origin/master

Тогда ваше местное masterотделение должно выглядеть идентично origin/master.

randomguy3
источник
71
@ На самом деле это не самый лучший ответ. Вполне возможно, что origin / master может опередить вашего локального мастера как раз перед слиянием некоторых коммитов, в этом случае это может не дать желаемых результатов
Дхрува Сагар
15
@ dhruva-sagar Да, но пока мерзавец не говорит, что ты позади, и ты не получаешь, у тебя все будет хорошо.
Кельвин
3
Спасибо! Это идеально, если (и только если) у вас есть удаленное хранилище.
Том
2
Нет, он не идеален для этого вопроса, см. Предложение «предположить». Ответ MBO фактически покрывает этот случай и случай, когда слияние не является единственным локальным коммитом.
Зингер
2
Еще раз, может быть, это предупреждение должно войти в сам ответ: всегда избегайте переписывания git history!
Cregox
1175

См. Главу 4 в книге Git и оригинальный пост Линуса Торвальдса .

Чтобы отменить слияние, которое уже было передано :

git revert -m 1 commit_hash

Обязательно отмените возврат, если вы снова делаете ветку, как сказал Линус.

Юрий Гейниш
источник
10
@perfectionist согласился :) Как бы хотелось, чтобы был способ перенести этот ответ на другой вопрос - (может быть, есть)
mikermcneil
для получения дополнительной информации о
возврате
1
Чтобы быть уверенным, что этот возврат сработал, вы можете выполнить git diff hash1 hash2, где hash1 - это зафиксированный возврат, а hash2 - старый коммит, в состояние которого вы пытались вернуться. Нет вывода == успех! Я смог откатить несколько коммитов, выполнив это несколько раз, начав с отмены самого последнего слияния и работая в обратном направлении. git diff показал мне, что я оказался в том состоянии, в котором хотел.
Роберт Синтон
6
Обратите внимание, что это на самом деле не решает оригинальный вопрос автора . Оригинальный постер уже используется git revert -m 1 <commit>. Проблема состоит в том, что выполнение этого не стирает случайное слияние, которое он сделал (и еще не выдвинул). Другие ответы, включающие полную перезагрузку, лучше подходят для оригинальной проблемы с постером.
Это отличный ресурс прямо из Github: Как отменить (почти) что-нибудь с помощью Git
jasonleonhard
986

Странно, что пропала самая простая команда. Большинство ответов работают, но отмена слияния, которое вы только что сделали, это простой и безопасный способ :

git reset --merge ORIG_HEAD

Ссылка ORIG_HEADбудет указывать на исходную фиксацию до слияния.

( --mergeОпция не имеет ничего общего со слиянием. Она такая же git reset --hard ORIG_HEAD, но безопаснее, поскольку не затрагивает незавершенные изменения.)

Одино - Вельмонт
источник
17
Если с git reset --merge ORIG_HEADтех пор вы загрязнили свое рабочее дерево, сохраните эти изменения.
yingted
1
Это единственный правильный ответ (я не говорю, что это лучший ответ - обратите внимание на разницу). Допустим, на мастере я сделал 3 коммита в t1, t3 и t5. Скажем, в ветке 1 я сделал 3 комментария в моменты времени t2, t4 и t6 (предположим, что t1, t2, t3, t4, t5 и t6 находятся в хронологическом порядке). Любая подобная команда git reset --hard HEAD~5сбрасывает только HEAD (может удалить коммиты как в master, так и в branch1). Только --mergeопция удаляет merge.
Ману Манджунат
@Manu --mergeОпция на самом деле не удаляет слияние, вы можете использовать --hardего также будет хорошо работать. Ключом здесь является ссылка ORIG_HEAD, она устанавливается перед тем, как выполнить слияние с тем местом, где вы стоите в этой точке. :)
Одино - Велмонт
@yingted Что вы подразумеваете под «Если вы с тех пор испортили свое рабочее дерево, git reset --merge ORIG_HEAD сохраняет эти изменения». Вы имели в виду изменение файлов после слияния? Во всяком случае, я сделал слияние, а затем сделал некоторые из разрешения конфликтов. Но затем я хотел сбросить слияние и сделал, как указано в этом ответе. Все было хорошо, и это не сохранило мои изменения, сделанные после слияния. Мой локальный репо просто похож на позицию до слияния.
Самита Чатуранга
Команда git reset --hard ORIG_HEADотлично сработала для меня - возможно, ей помог тот факт, что я не внес никаких других изменений в хранилище после того, как локальный файл git mergeя пытался отменить. Команда просто сбрасывает состояние хранилища до того, каким оно было до слияния. Спасибо за отличный совет!
Bluebinary
391

В более новых версиях Git, если вы еще не совершили слияние и у вас есть конфликт слияния , вы можете просто сделать:

git merge --abort

От man git merge:

[Это] можно запустить только после того, как слияние привело к конфликтам. git merge --abortпрервет процесс слияния и попытается восстановить состояние перед слиянием.

Трэвис Ридер
источник
8
Его слияние совершено, но не передано (см. Заголовок), он уже слился, ваша команда работает только тогда, когда он все еще находится в середине слияния
JBoy
135

Вы должны сбросить до предыдущего коммита. Это должно работать:

git reset --hard HEAD^

Или даже HEAD^^отменить этот возвратный коммит. Вы всегда можете дать полную ссылку на SHA, если не уверены, сколько шагов назад вы должны сделать.

В случае, если у вас возникли проблемы и в вашей основной ветке не было локальных изменений, вы можете выполнить сброс на origin/master.

MBO
источник
5
Лучший ответ IMHO, включает в себя собственный ОП (при условии, что только один шаг для возврата, что, как кажется, имеет место в Q), а также ярлык randomguy3 (который работает, когда «ваша основная ветвь не имела локальных изменений»). ")
Зингер
4
Вы комментаторы, @Inger и @Konstantin, почему? Вы пришли сюда после того, как мой ответ был создан, и это более правильно. Просто подняться на ГОЛОВУ на один шаг часто неправильно, и вам действительно нужно посчитать, как далеко вы должны пройти. Git уже устанавливает ORIG_HEADдля вас, почему бы не использовать его?
Одино - Велмонт
будет ли сбрасывать локальные изменения? #Пожалуйста обновите.
CoDe
Для меня это отлично сработало, так как сброс настроек головы имеет гораздо больше смысла, чем половина ответов здесь.
Варда Элентари
HEAD ^ равно совершать до HEAD? а ^^ это два коммита до? Догадываетесь, что это не сработает с ускоренным слиянием?
Маркус Леон
87

В последнее время я использую, git reflogчтобы помочь с этим. В основном это работает только в том случае, если произошло слияние, и оно было на вашей машине.

git reflog может вернуть что-то вроде:

fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

Первая строка указывает, что произошло слияние. 2-я строка - время до моего слияния. Я просто git reset --hard 43b6032заставляю эту ветку отслеживать до слияния и переносить.

Parris
источник
Отличный ответ, спасибо! Нужно было отменить слияние, но другие ответы только испортили его, используя, reflogчтобы получить SHA и передать это в работу git reset.
Lankymart
51

С современным Git вы можете:

git merge --abort

Старый синтаксис:

git reset --merge

Старая школа:

git reset --hard

Но на самом деле, стоит заметить, что git merge --abortэто эквивалентно только тому, git reset --mergeчто MERGE_HEADприсутствует. Это можно прочитать в справке Git для команды слияния.

git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

После неудачного слияния, когда его нет MERGE_HEAD, неудачное слияние может быть отменено git reset --merge, но не обязательно git merge --abort, так что они не только имеют старый и новый синтаксис для одной и той же вещи .

Лично я нахожу git reset --mergeгораздо более мощным и полезным в повседневной работе, поэтому я всегда использую это.

Мартин Г
источник
Отлично сработало для меня. Любой другой пост говорит, что это так сложно, но это именно то, что ожидается. Я полагаю, это сработало только потому, что были конфликты, что не совсем отвечает на первоначальный вопрос.
Джереми
Этот ответ не фокусируется на ситуации ОП и оставляет важный контекст.
Бен Уилер
37

Хорошо, ответы, которые мне дали другие люди, были близки, но это не сработало. Вот что я сделал.

Делая это...

git reset --hard HEAD^
git status

... дал мне следующий статус.

# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

Затем мне пришлось вводить одну и ту же git resetкоманду еще несколько раз. Каждый раз, когда я это делал, сообщение менялось на единицу, как вы можете видеть ниже.

> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

В этот момент я увидел, что сообщение о статусе изменилось, поэтому я попытался сделать git pull, и это, похоже, сработало:

> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

Короче говоря, мои команды сводятся к следующему:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull
Мэтт Хаггинс
источник
19
или вы могли бы использоватьHEAD^^^^
hasen
17
может быть, даже сбросить до origin/master;)
hasen
23

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

В частности,

$ git reflog
$ git reset --hard HEAD@{0}
stephjang
источник
1
Спасибо! Вы сэкономили полдня моей работы. Однако я не мог выйти из режима reflog ни одной командой.
Катаржина,
1
@Katarzyna использует клавишу "q", чтобы выйти из reflog
Амджед Бэйг,
21

Если вы находитесь в процессе слияния, вы всегда можете прервать его git merge --abort

llioor
источник
2
спасибо братан, и я собирался сделать этот страшный материал правильный ответ. повезло, что я прокрутил вниз. Я просто хочу удалить голову слияния
Nyuu
15

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

git reset --hard remotes/origin/HEAD

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

Ральф Ритох
источник
Точно! Сбрасывает ваши изменения в ГОЛОВУ ветки! Не делать по одному
Карлос Зинато
не работает для меня фактически закончили тем, что отправили местное отделение назад месяц или два. К счастью, все это локально, поэтому я всегда могу уничтожить ветку и получить ее снова. Просто хотел указать на это, если другие попробуют это.
Мэтт Пенджли
@MattPengelly - этот метод в значительной степени недокументирован и обычно работает, если ваша ветвь синхронизирована с удаленной ветвью до того, как вы выполните слияние. Прошли ли месяцы с тех пор, как ваша ветка синхронизировалась с удаленной веткой?
Ральф Ритох
@MattPengelly, это также зависит от того, на какую ветку указывает HEAD. Я использую gitflow в одном из моих проектов, и, хотя я нахожусь в разработке, удаленные / origin / HEAD указывают на origin / master, поэтому, если мне нужно отменить слияние, мне, вероятно, придется сбросить на удаленные / Происхождение / развитие
Ральф Ритох
14

Если вы еще не совершили это, вы можете использовать только

$ git checkout -f

Это отменит слияние (и все, что вы сделали).

Idealmind
источник
Попробовал это, и это фактически увеличило число коммитов, которые опередил мой местный филиал
Барклай
14

Добрался до этого вопроса также, пытаясь вернуться к исходному совпадению (т. Е. NO фиксирует перед началом координат). Исследуя далее, обнаружил, что есть resetкоманда именно для этого:

git reset --hard @{u}

Примечание: @{u}это сокращение от origin/master. (И, конечно, вам нужен этот удаленный репозиторий, чтобы это работало.)

Лиан
источник
14

Вы должны изменить свою ГОЛОВУ, Не свою конечно, но мерзавца ГОЛОВУ ....

Поэтому, прежде чем ответить, давайте добавим некоторую предысторию, объясняющую, что это такое HEAD.

First of all what is HEAD?

HEADэто просто ссылка на текущий коммит (последний) в текущей ветке.
Там может быть только один HEADв любой момент времени. (без учетаgit worktree )

Содержимое HEADхранится внутри .git/HEADи содержит 40 байтов SHA-1 текущего коммита.


detached HEAD

Если вы не используете последний коммит, то HEADесть он указывает на предыдущий коммит в истории detached HEAD.

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

В командной строке это будет выглядеть так - SHA-1 вместо имени ветви, так как HEADне указывает на конец текущей ветви

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

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

Несколько вариантов того, как восстановить систему с отключенной HEAD:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

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

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Вы всегда можете использовать reflogтакже.
git reflogбудет отображаться любое изменение, которое обновило, HEADи проверка желаемой записи reflog установитHEAD вернет этот коммит.

Каждый раз, когда ГОЛОВКА изменяется, в reflog

git reflog
git checkout HEAD@{...}

Это вернет вас к желаемой фиксации

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


git reset --hard <commit_id>

«Переместите» ГОЛОВУ назад к желаемому коммиту.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Примечание: ( начиная с Git 2.7 )
    вы также можете использовать git rebase --no-autostash.

git revert <sha-1>

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

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Эта схема иллюстрирует, какая команда что делает.
Как вы можете видеть там, reset && checkoutизмените HEAD.

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

CodeWizard
источник
Это сокровище J
Джаванд Сингх
12

Самый простой ответ - тот, который дал Одино - Велмонт

Сначала сделай git reset --merge ORIG_HEAD

Для тех, кто хочет выполнить сброс после отправки изменений, сделайте это (потому что это первый пост, увиденный для всех вопросов по git reset слиянию)

git push origin HEAD --force

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

Harsha
источник
10

Просто чтобы посмотреть на дополнительную опцию, я в основном следовал описанной здесь модели ветвления: http://nvie.com/posts/a-successful-git-branching-model/ и поэтому объединялся с--no-ff (нет перемотка вперед) обычно.

Я только что прочитал эту страницу, так как я случайно слил ветку тестирования вместо своей ветки релиза с мастером для развертывания (сайт, мастер - это то, что работает). Ветвь тестирования объединена с двумя другими ветвями и насчитывает около шести коммитов.

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

Дэмиен Бирн
источник
10

Вы можете использовать только две команды, чтобы отменить слияние или перезапустить с помощью определенного коммита:

  1. git reset --hard commitHash (вы должны использовать коммит, который хотите перезапустить, например, 44a587491e32eafa1638aca7738)
  2. git push origin HEAD --force (Отправка новой локальной ветки master в origin / master)

Удачи и вперед!

Матеус Абреу
источник
10

Это можно сделать несколькими способами.

1) Прервать слияние

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

git merge --abort

2) Сбросить ГОЛОВУ в удаленную ветку

Если вы работаете из удаленной ветки разработки, вы можете сбросить HEAD до последнего коммита в удаленной ветке, как показано ниже:

git reset --hard origin/develop

3) Удалить текущую ветку и снова оформить заказ из удаленного хранилища.

Учитывая, что вы работаете над веткой разработки в локальном репо, которая синхронизируется с удаленной веткой / веткой разработки, вы можете сделать следующее:

git checkout master 
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :) 

git branch -D develop
git checkout -b develop origin/develop
Амит Канерия
источник
что «1) Abort Merge» было достаточно симпатичным. Upvoting.
CodeToLife
1
Быть осторожен! git merge --abort "может быть запущен только после того, как слияние привело к конфликтам. git merge --abort прервет процесс слияния и попытается восстановить состояние перед слиянием"
Педро Гарсия Медина
8

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

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

git checkout develop
git branch -D master
git branch -t master origin/master

Вуаля! Мастер находится на той же стадии, что и источник, и ваше неправильно объединенное состояние стирается.

Stephan
источник
1
Примечание: это не только отменяет слияние, но также и любые локальные коммиты, которые были сделаны с момента последнего нажатия на источник.
Мартейн Химельс
4

Если вам нужно решение для командной строки, я предлагаю просто ответить на вопрос MBO.

Если вы новичок, вам может понравиться графический подход:

  1. Подать мяч gitk (из командной строки или щелкните правой кнопкой мыши в браузере файлов, если он у вас есть)
  2. Вы можете легко обнаружить коммит слияния там - первый узел сверху с двумя родителями
  3. Перейдите по ссылке на первого / левого родителя (та, что находится в вашей текущей ветке до слияния, обычно красная для меня)
  4. На выбранном коммите щелкните правой кнопкой мыши «Reset branch to here», выберите там hard reset
Ингер
источник
4

Стратегия: создать новую ветку, где все было хорошо.

Обоснование: отменить слияние сложно. Существует слишком много решений, в зависимости от многих факторов, таких как то, совершили ли вы слияние или выдвинули его или были ли новые коммиты с момента вашего слияния. Кроме того, вам все еще нужно иметь относительно глубокое понимание git, чтобы адаптировать эти решения к вашему случаю. Если вы слепо следуете некоторым инструкциям, вы можете получить «пустое слияние», при котором ничто не будет объединено, и дальнейшие попытки слияния заставят Git сказать вам «Уже в курсе».

Решение:

Допустим, вы хотите слиться devс feature-1.

  1. Найдите ревизию, которую вы хотите получить слияние:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. Проверьте это (вернитесь во времени):

    git checkout e5f6g7h8
    
  3. Создайте новую ветку оттуда и проверьте ее:

    git checkout -b feature-1
    

Теперь вы можете перезапустить слияние:

  1. Объединение: git merge dev

  2. Исправьте ваши конфликты слияния.

  3. Commit: git commit

  4. Когда вы будете удовлетворены результатами, удалите старую ветку: git branch --delete feature-1

PYB
источник
2

Просто создайте новую ветку, а затем выберите нужные коммиты.

Это делает его более безопасным и простым после сброса, описанным во многих ответах выше.

деви
источник
1
Я согласен с этим предложением, особенно если вы не совсем довольны перечисленными командами git. Это может быть медленнее с большим количеством «тяжелого труда», но если это не подходит, и вы обеспокоены потерей работы, это стоит усилий.
Грег
1

Я думаю, что вы можете указать, git rebase -i [hash] [branch_name] где [hash]находится хеш-идентификатор для того места, которое вы хотите перемотать назад, плюс один (или сколько коммитов вы хотите вернуть), а затем удалить строки для коммитов в редакторе, которые вам больше не нужны. , Сохраните файл. Выход. Молиться. И это должно быть перемотано. Возможно, вам придется сделатьgit reset --hard , но это должно быть хорошо на этом этапе. Вы также можете использовать это для извлечения определенных коммитов из стека, если вы не хотите сохранять их в своей истории, но это может оставить ваш репозиторий в состоянии, которое вы, вероятно, не хотите.

tychoish
источник
1

Если вы совершили слияние:

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
Дориан
источник
1
  1. Во-первых, убедитесь, что вы все совершили.

  2. Затем верните ваш репозиторий в предыдущее рабочее состояние:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    или используя --hard( это удалит все локальные, не зафиксированные изменения! ):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

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

  3. Проверьте, какие коммиты вы хотите повторно зафиксировать в верхней части предыдущей правильной версии:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. Примените свои правые коммиты в верхней части правой версии вашего хранилища:

    • Используя cherry-pick (изменения, внесенные некоторыми существующими коммитами)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • Или путем выбора диапазона коммитов:

      • Сначала проверьте правильные изменения, прежде чем объединять их:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • Сначала проверьте правильные изменения, прежде чем объединять их:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        где это диапазон правильных коммитов, которые вы совершили (исключая ошибочно совершенное слияние).

kenorb
источник
1
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

Это сработало для меня .. !!

Шива Кумар
источник
0

Если вы заметили , что нужно вернуться сразу после слияния , и вы не сделали ничего , после попытки слияния, вы можете просто выполнить следующую команду: git reset --hard HEAD@{1}.

По сути, ваше слияние shaбудет указывать на HEAD@{0}то, что после слияния не было зафиксировано ничего другого, и поэтому HEAD@{1}будет предыдущим пунктом перед слиянием.

Дут А.
источник
0

Самый простой из самых простых шансов, намного проще, чем все сказанное здесь:

Удалите локальную ветку (локальную, а не удаленную) и снова потяните. Таким образом, вы отмените изменения в своей основной ветке, и любое изменение будет затронуто вами, которое вы не хотите вносить. Начни это сначала.

Луис
источник
0

В этом случае вы захотите сбросить ветку с помощью git reset --hard <branch_name>. Если вы хотите сохранить изменения перед их сбросом, обязательно создайте новую ветку и git checkout <branch_name>.

Вы также можете сбросить состояние до определенного коммита git reset --hard <commit_id>.

Если изменения были перенесены, вы можете использовать git revert <branch_name>вместо этого. Обязательно узнайте, как использовать git revert и git checkout в других сценариях.

Неша Зорич
источник