Отменить определенный коммит в Git, который был передан в удаленные репозитории


789

Какой самый простой способ отменить конкретный коммит, это:

  • не в голову или голову
  • Был сдвинут в пульт.

Потому что, если это не последний коммит,

git reset HEAD

не работает И потому, что он был перенесен на пульт,

git rebase -i

а также

git rebase --onto

вызовет некоторые проблемы в пульте.

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

Другими словами, что такое Git- эквивалент следующих команд SVN:

svn merge -r 303:295 http://svn.example.com/repos/calc/trunk

который удаляет все изменения с 295 до 302 путем обратного объединения всех изменений в этих ревизиях в качестве нового коммита.

svn merge -c -302 ^/trunk

что отменяет фиксацию 302, конечно, добавляя еще один коммит, который отменяет объединение изменений из этого соответствующего коммита.

Я подумал, что это должна быть довольно простая операция в Git и довольно распространенный вариант использования. В чем еще смысл атомных коммитов?

У нас есть поэтапное копирование и все для того, чтобы коммиты были абсолютно атомарными, разве вы не можете легко отменить один или несколько атомных коммитов?

Ответы:


1211

Определите хеш коммита, используя git log, затем используйте git revert <commit>для создания нового коммита, который удаляет эти изменения. В некотором смысле, git revertобратное утверждение git cherry-pick- последний применяет патч к ветке, в которой он отсутствует, первый удаляет его из ветви, в которой он есть.


237
И используйте ключ -n, если вы хотите, чтобы код был возвращен, но не был автоматически зафиксирован снова
jaygooby

17
Что делает опция «m»? Я попробовал git revert 8213f7d, но получил вместо этого: error: Commit 8213f7dad1ed546b434a0d8a64cb783b530a5a30 - это слияние, но опция -m не была указана. фатальный: возврат не удался
Малкольм

10
Чтобы отменить слияние: git revert -m 1 <hash>
brunozrk

31
Предупреждение для тех, кто хочет отменить слияние: git revert отменит все изменения данных (т. Е. Изменения файла будут отменены), но слияние по-прежнему остается в истории. Из-за этого, если вы попытаетесь объединить эту ветвь позже, она не будет включать в себя какие-либо коммиты из ветви слияния до отмененного слияния. Скорее всего, это не то, что вы хотите. Чтобы снова полностью объединить ветку, вам нужно сначала отменить коммит, в котором вы отменили исходное слияние. Узнайте больше здесь: kernel.mirrors.pair.com/pub/software/scm/git/docs/howto/…
etreworgy

3
Ссылка в комментарии @etreworgy - 404. Я подозреваю, что это актуальная версия ссылки: kernel.org/pub/software/scm/git/docs/howto/…
Тим Смит

368

Мне не нравится автоматическая фиксация, git revertкоторая может быть полезна для некоторых.

Если вы просто хотите, чтобы измененные файлы не были автоматически зафиксированы , вы можете использовать--no-commit

% git revert --no-commit <commit hash>

который так же, как -n

% git revert -n <commit hash>

9
Вы также можете сделать, git reset HEAD~1 --softесли вы уже вернулись без-n
Даниэль

1
Но git reset HEAD~nне решит проблему отмены любого коммита, не достижимого постоянно из головы. Запрос состоит в том, чтобы отменить любой конкретный коммит.
sangeethkumarp

Я использовал это решение, но столкнулся с конфликтом в середине восстановления. После разрешения конфликта я поступил так, git revert --continueкак ему велели. Это сработало, но, к сожалению, покорило результаты. Возможно, мне нужно было сделать git revert --no-commit --continue.
mareoraft

1
@sangeethkumarp комментарий Даниэля - это дополнительный шаг, который вы можете предпринять после git revert, если вы забыли -n; потому что в этот момент последний коммит является реверсией, поэтому программный сброс отменяет этот коммит, но не связанные изменения кода возврата
Оливер

@Daniel предоставил мне решения по работе с комментариями. Большое спасибо '' git reset HEAD ~ 1 --soft ''
Md. Abu Sayed

41

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


1

Если вы хотите совершить , чтобы вернуться является слиты обязательство (было уже слиты), то вы должны либо -m 1или -m 2опции , как показано ниже. Это позволит git знать, какой родительский коммит из объединенного коммита использовать. Более подробную информацию можно найти ЗДЕСЬ .

  • git revert <commit> -m 1
  • git revert <commit> -m 2
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.