↓Перейти к содержанию
  1. Git: руководства и команды/

git merge --abort: как отменить merge с конфликтами

··7 минут·

Процесс слияния веток в Git может быть сложным. Когда две ветки содержат конфликтующие изменения, Git входит в специальное состояние “merging” и просит вас разрешить конфликты.

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

Команда git merge --abort делает именно это: она отменяет текущий процесс слияния и возвращает ваш репозиторий в состояние до начала merge. Все изменения отменяются, конфликты забываются, и вы можете начать с чистого листа.

Когда нужен git merge –abort #

Давайте посмотрим на типичный сценарий когда требуется отмена merge:

Сценарий 1: Много конфликтов, слишком сложно #

# Вы начинаете слияние
$ git merge feature-large-refactor
Auto-merging src/core.js
Auto-merging src/utils.js
Auto-merging src/config.js
CONFLICT (content): Merge conflict in src/api.js
CONFLICT (content): Merge conflict in src/database.js
CONFLICT (content): Merge conflict in src/cache.js
Automatic merge failed; fix conflicts and then commit the merge.

# Смотрите на конфликты... Их же 20! Это слишком сложно.
# Пришла горячая задача, нужна срочно
$ git merge --abort

# Всё отменено, вы назад на чистой ветке
$ git status
On branch main
nothing to commit, working tree clean

Сценарий 2: Неправильно выбрали ветку #

# Вы думали что сливаете develop, но случайно слили experimental
$ git merge experimental
Auto-merging src/main.js
CONFLICT (content): Merge conflict in src/main.js
Automatic merge failed; fix conflicts and then commit the merge.

# Упс, это не та ветка!
$ git merge --abort

# Пробуем ещё раз с нужной веткой
$ git merge develop

Сценарий 3: Слияние с неправильной веткой, нужно переделать #

# На main, сливаем hotfix который был на feature-branch
$ git merge feature-branch
Auto-merging package.json
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js

# Потом начинаете решать конфликты, но понимаете:
# - hotfix должен был идти на develop, не на main
# - нужно сначала всё обновить на develop

$ git merge --abort

# Делаем правильно
$ git switch develop
$ git merge feature-branch

Что делает git merge –abort: пошагово #

Давайте разберёмся что происходит во время merge и как –abort это отменяет.

До merge #

$ git status
On branch main
nothing to commit, working tree clean

$ git branch
* main
  feature-login

Во время merge (с конфликтами) #

$ git merge feature-login
Auto-merging src/auth.js
CONFLICT (content): Merge conflict in src/auth.js
Automatic merge failed; fix conflicts and then commit the merge.

$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  both modified:   src/auth.js

# Git создал специальный файл MERGE_HEAD который отслеживает merge
$ cat .git/MERGE_HEAD
abc1234567890def1234567890def1234567890

# И файл с сообщением
$ cat .git/MERGE_MSG
Merge branch 'feature-login'

Выполняем git merge –abort #

$ git merge --abort
Merge aborted.

$ git status
On branch main
nothing to commit, working tree clean

# MERGE_HEAD файл удалён
$ ls .git/MERGE_HEAD
No such file or directory

# Всё вернулось в исходное состояние
$ git branch
* main
  feature-login

Использование git merge –abort в реальной ситуации #

Полный пример: сложный merge со множеством конфликтов #

# Ваша рабочая ветка main чистая
$ git log --oneline -n 3
d7f8e9a Latest commit on main
c4b3a2d Previous commit
b1c2d3e Earlier commit

# Коллега просит смержить feature-big-changes
$ git merge feature-big-changes
Auto-merging src/api.js
Auto-merging src/models.js
Auto-merging src/utils.js
CONFLICT (content): Merge conflict in src/services/auth.js
CONFLICT (content): Merge conflict in src/services/payment.js
CONFLICT (content): Merge conflict in src/controllers/user.js
CONFLICT (content): Merge conflict in src/controllers/admin.js
CONFLICT (content): Merge conflict in src/routes.js
Automatic merge failed; fix conflicts and then commit the merge.

# Смотрите на количество конфликтов... слишком много

$ git status | grep "Unmerged paths" -A 20
Unmerged paths:
  both modified:   src/services/auth.js
  both modified:   src/services/payment.js
  both modified:   src/controllers/user.js
  both modified:   src/controllers/admin.js
  both modified:   src/routes.js

# Нет времени разбираться с этим прямо сейчас
# Приходит срочный баг-фикс

$ git merge --abort
Merge aborted.

$ git status
On branch main
nothing to commit, working tree clean

# Теперь можете заняться срочным багом
$ git switch -c hotfix-payment
# ... работаете на hotfix ...

# Потом вернётесь к big-changes когда будет время

Альтернативы: что если –abort не работает #

В редких случаях git merge --abort может не работать или вызвать ошибки. Вот альтернативы:

Альтернатива 1: git reset –merge #

# Это почти то же самое что git merge --abort
git reset --merge HEAD

# Или если merge HEAD не существует
git reset --merge ORIG_HEAD

Разница в том что git reset --merge более интеллектуальный и пытается сохранить изменения которые не конфликтуют. Но обычно git merge --abort предпочтительнее.

Альтернатива 2: git reset –hard HEAD #

# Полностью откатывает к состоянию HEAD
# Удаляет ВСЕ изменения включая те что были до merge
git reset --hard HEAD

# ОПАСНО! Только если уверены!

Это опаснее чем --abort потому что теряются все unsaved изменения.

Полный пример с альтернативами:

$ git merge feature-branch
CONFLICT (content): Merge conflict in src/main.js
Automatic merge failed; fix conflicts and then commit the merge.

# Попробуем отменить merge
$ git merge --abort
error: There is no merge to abort (MERGE_HEAD missing).

# Merge может быть в странном состоянии
# Используем альтернативу

$ git reset --merge ORIG_HEAD
Switched to a new branch 'backup'

# Или если ничего не помогает
$ git reset --hard HEAD
HEAD is now at d7f8e9a Latest commit

Отменить уже завершённый merge (слишком поздно!) #

Что если вы уже выполнили merge, коммитили это, но потом поняли что это была ошибка?

К сожалению git merge --abort уже не поможет. Но у вас есть другие опции:

Вариант 1: git revert для merge коммита (рекомендуется) #

# Найдите хеш merge коммита
git log --oneline | grep -i merge

# Предположим это d7f8e9a
$ git revert -m 1 d7f8e9a

# Это создаст новый коммит который отменяет merge

Это самый безопасный способ если merge уже запушен.

Вариант 2: git reset –hard для локального merge #

# ТОЛЬКО если merge локальный и не запушен!
git reset --hard HEAD~1

# Это удалит merge коммит полностью

Полный пример:

$ git log --oneline -n 5
d7f8e9a Merge branch 'feature-broken' (HEAD -> main)
f4e5d6c Some other commit
8x9y0z1 Another commit
a1b2c3d Old commit
5a6b7c8 Even older

# Ой, merge d7f8e9a был ошибкой!
# Но мы уже закоммитили

# Если это локально и не запушено:
$ git reset --hard HEAD~1
HEAD is now at f4e5d6c Some other commit

# Если это уже запушено в origin:
$ git revert -m 1 d7f8e9a
# Создаст коммит отмены
# Потом git push

Подробнее об этом в /ru/git/git-revert-merge-commit/.

Практическое руководство: step-by-step #

Правильный способ отменить merge #

# Шаг 1: Вы в процессе merge с конфликтами
$ git status
On branch main
You have unmerged paths.

# Шаг 2: Проверьте какую ветку сливаете
$ git merge --no-commit --no-ff <branch-to-merge>  # уже выполнено

# Шаг 3: Решили что это ошибка
$ git merge --abort

# Шаг 4: Проверьте что всё чисто
$ git status
On branch main
nothing to commit, working tree clean

# Шаг 5: Если нужно, повторите merge правильно
$ git merge correct-branch

Когда НЕ использовать –abort #

# НЕ используйте --abort если:

# 1. Merge уже завершён и закоммичен
$ git status
On branch main
nothing to commit, working tree clean
# Используйте git revert вместо этого

# 2. Вы находитесь не в процессе merge
$ git merge --abort
error: There is no merge to abort (MERGE_HEAD missing).

FAQ: Частые вопросы про merge –abort #

Q: Теряются ли изменения при git merge –abort?

A: Нет! Все изменения которые были в вашей рабочей директории ДО merge сохраняются. Отменяются только изменения которые были внесены merge операцией.

Q: Можно ли отменить merge после того как запушил его?

A: Нет, --abort работает только во время merge (когда статус показывает “Unmerged paths”). Если merge уже завершён и закоммичен, используйте git revert вместо этого.

Q: Что если у меня были changes до merge?

A: Если у вас были несохранённые изменения в файлах до merge, Git не позволит вам начать merge. Вам нужно сначала заккоммитить или отложить (git stash) эти изменения.

Q: Отличается ли –abort от –no-commit?

A: Да! --no-commit завершает merge но не создаёт коммит (изменения в staging). --abort полностью отменяет merge. Используйте --no-commit если хотите просмотреть результат перед коммитом.

Q: Могу ли я отменить merge если уже решил все конфликты?

A: Да, даже если вы решили все конфликты но ещё не закоммитили, git merge --abort полностью отменит merge:

$ git status
On branch main
All conflicts fixed but you are still merging.

$ git merge --abort
Merge aborted.

Заключение #

git merge --abort — это простой и безопасный способ отменить текущий процесс слияния:

  • Используйте git merge --abort когда вы в процессе merge и хотите его отменить
  • Все ваши изменения ДО merge сохраняются
  • История не переписывается, и с точки зрения других разработчиков ничего не произошло
  • Для уже завершённого merge используйте git revert вместо этого

Это очень безопасная операция — не бойтесь её использовать если merge пошёл не так!

Для более глубокого понимания merge процесса см. /ru/git/git-merge/, и /ru/git/konflikty-git-merge/.