Отменить определенный коммит в 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.