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

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

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

Ответы

Ответ 1

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

Ответ 2

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

git reset --hard origin/master

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

Ответ 4

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

git reset --merge ORIG_HEAD

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

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

Ответ 5

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

git merge --abort

От man git merge:

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

Ответ 6

Вы должны reset выполнить предыдущую фиксацию. Это должно работать:

git reset --hard HEAD^

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

Если у вас возникли проблемы, и ваша главная ветвь не имела локальных изменений, вы можете reset до origin/master.

Ответ 7

В последнее время я использовал 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

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

Ответ 8

С помощью современных Git вы можете:

git merge --abort

Более старый синтаксис:

git reset --merge

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

git reset --hard

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

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

Ответ 9

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

Выполнение этого...

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

Ответ 10

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

В частности,

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

Ответ 11

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

Ответ 12

Если вы еще не сделали этого, вы можете использовать

$ git checkout -f

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

Ответ 13

Получил этот вопрос, также обратившись к тому, чтобы вернуться к совпадению с началом (т.е. НЕТ берет начало до начала). Изучая далее, нашел там команду reset для этого:

git reset --hard @{u}

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

Ответ 14

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

git reset --hard remotes/origin/HEAD

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

Ответ 15

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

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

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

Ответ 16

Вы можете использовать только две команды для возврата слияния или перезапуска с помощью определенной фиксации:

  • git reset --hard commitHash (вы должны использовать фиксацию, которую хотите перезапустить, например, 44a587491e32eafa1638aca7738)
  • git push origin HEAD --force (Отправка новой локальной ведущей ветки в начало/мастер)

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

Ответ 17

Самый простой ответ - тот, который дается odinho - Velmont

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

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

git push origin HEAD --force

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

Ответ 18

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

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

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

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

Ответ 19

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

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

  • Отключить gitk (из командной строки или щелкнуть правой кнопкой мыши в браузере файлов, если у вас есть)
  • Вы можете легко определить фиксацию слияния - первый node сверху с двумя родителями
  • Следуйте ссылке на первый/левый родитель (тот, который находится в вашей текущей ветке до слияния, обычно красный для меня)
  • В выбранном коммите щелкните правой кнопкой мыши раздел "Reset", выберите жесткий reset там

Ответ 20

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

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

Решение:

Предположим, вы хотите объединить dev в feature-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
    
  • Проверьте это (вернитесь назад):

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

    git checkout -b feature-1
    

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

  • Объединить: git merge dev

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

  • Commit: git commit

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

Ответ 21

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

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

First of all what is HEAD?

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

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


detached HEAD

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

enter image description here

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

enter image description here

enter image description here

Несколько вариантов восстановления после отсоединения 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, а проверка нужной записи журнала повторного вызова вернет HEAD к этой фиксации.

Каждый раз, когда заголовок изменяется, в reflog будет добавляться новая запись

git reflog
git checkout [email protected]{...}

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

enter image description here


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 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.

enter image description here

Ответ 22

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

Ответ 23

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

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

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

git merge --abort

2) Сбросить HEAD в удаленную ветку

Если вы работаете с удаленной веткой разработки, вы можете сбросить 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

Ответ 24

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

Ответ 25

  • Во-первых, убедитесь, что вы все сделали.

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

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

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

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

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

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

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  • Примените свои права на верхнюю часть нужной версии вашего репозитория:

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

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

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

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

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

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

Ответ 26

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

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard

Ответ 27

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

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

Ответ 28

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

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

Ответ 29

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

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

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

Ответ 30

  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

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