Отмените слияние Git, которое еще не было перенесено - PullRequest
3492 голосов
/ 05 марта 2010

В моей основной ветке я сделал 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.

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

Ответы [ 28 ]

3887 голосов
/ 05 марта 2010

С помощью 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

- объединить

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

1369 голосов
/ 17 марта 2011

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

git reset --hard origin/master

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

1129 голосов
/ 02 июня 2011

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

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

git revert -m 1 commit_hash

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

930 голосов
/ 29 января 2013

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

git reset --merge ORIG_HEAD

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

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

352 голосов
/ 12 февраля 2013

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

git merge --abort

С man git merge:

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

121 голосов
/ 05 марта 2010

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

git reset --hard HEAD^

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

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

82 голосов
/ 19 декабря 2014

В последнее время я использую 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 заставляю эту ветку отслеживать до слияния и переносить.

49 голосов
/ 08 мая 2015

С современным 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 гораздо более мощным и полезным в повседневной работе, поэтому я всегда использую его.

36 голосов
/ 05 марта 2010

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

Делаем это ...

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
21 голосов
/ 18 января 2014

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

В частности,

$ git reflog
$ git reset --hard HEAD@{0}
...