it-roy-ru.com

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

В моей основной ветке я сделал git merge some-other-branch локально, но никогда не отправлял изменения в Master master. Я не хотел сливаться, поэтому я хотел бы отменить это. При выполнении 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.

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

3349
Matt Huggins

С помощью 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, но сохраняет те, которые отличаются между индексом и рабочим деревом (то есть с изменениями, которые не были добавлены). 

3709
Marcin Gil

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

git reset --hard Origin/master

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

1335
randomguy3

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

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

git revert -m 1 commit_hash

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

1109
Yuri Geinish

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

git reset --merge ORIG_HEAD

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

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

897
odinho - Velmont

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

git merge --abort

От man git merge:

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

342
Travis Reeder

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

git reset --hard HEAD^

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

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

117
MBO

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

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

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

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

81
Parris

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

48
Martin G

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

Делая это...

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
36
Matt Huggins

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

В частности,

$ git reflog
$ git reset --hard [email protected]{0}
21
stephjang

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

$ git checkout -f

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

13
Idealmind

Попал к этому вопросу также, пытаясь вернуться, чтобы соответствовать Origin (то есть, NO фиксирует перед Origin). В дальнейшем, обнаружив, что есть команда reset именно для этого:

git reset --hard @{u}

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

12
leanne

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

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

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

10
Damien Byrne

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

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

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

10
Matheus Abreu

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

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

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

git Push Origin HEAD --force

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

8
Harsha

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

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

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

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

7
Stephan

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

git reset --hard remotes/Origin/HEAD

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

6
Ralph Ritoch

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

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

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

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

Обоснование: Трудно вернуть слияние. Существует слишком много решений, в зависимости от многих факторов, таких как то, совершили ли вы слияние или отменили его, или были ли новые коммиты с момента вашего слияния. Также вам все еще нужно иметь относительно глубокое понимание 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. Фиксация: git commit

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

4
pyb

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

2
llioor

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

1
tychoish

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

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard
1
Dorian
  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
        

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

1
kenorb

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

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

0
Luis
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

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

0
Siva Kumar

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

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

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

0
Nesha Zoric

Если вы заметили, что вам нужно вернуться сразу после объединения, и вы ничего не сделали после попытки объединения, вы можете просто выполнить эту команду: git reset --hard [email protected]{1}.

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

0
Dut A.