Как отменить локальный коммит


745

Моя проблема в том, что я изменил файл, например: README, добавил новую строку ' это для моей строки тестирования » и сохранил файл, затем я выполнил следующие команды

 git status

 # On branch master
 # Changed but not updated:
 #   (use "git add <file>..." to update what will be committed)
 #   (use "git checkout -- <file>..." to discard changes in working directory)
 #
 #  modified:   README
 #
 no changes added to commit (use "git add" and/or "git commit -a")


 git add README

 git commit -a -m 'To add new line to readme'

Я не отправлял код в github, теперь я хочу отменить этот коммит.

Для этого я использовал

   git reset --hard HEAD~1

Но я потерял недавно добавленную строку « это для моей строки тестирования » из файла README. Этого не должно быть. Мне нужен контент, чтобы быть там. Есть ли способ сохранить контент и отменить мой локальный коммит?


3
Похоже, что вы определенно не просите git revert, что создает новый коммит с обратным дифференциалом от обратного коммита. Сброс просто указывает текущую ветвь на другой коммит, в данном случае тот, что перед коммитом, который вы хотите «забыть».
Каскабель

1
NB: Стоит упомянуть, что git-commitможет прерваться, если вы оставите сообщение пустым, поэтому, если вы еще не закончили коммит, это может быть полезно.
GKFX

Ответы:


1425

Просто используйте git resetбез --hardфлага:

git reset HEAD~1

PS: в системах на основе Unix вы можете использовать HEAD^что равно HEAD~1. На Windows HEAD^не будет работать, потому что ^сигнализирует о продолжении строки. Так что ваша командная строка просто спросит вас More?.


13
Кстати, это называется --mixed в руководстве .
Джош Ли

10
Более новые версии Git даже позволяют @^в качестве сокращения HEAD^.
Koraktor

Я не знаю, что это сделало, но в моем списке изменений появилось много файлов, файлов, которых я не трогал
FRR

@feresr Если вы действительно не трогали эти файлы во время последнего коммита или в рабочем дереве, это вызвано другими несоответствиями в вашем рабочем дереве, например, в Windows, и окончания файлов не совпадают.
Koraktor

1
Можно ли сбросить все коммиты с одной стороны?
веб-женщина

185

Используйте --softвместо --hardфлага:

git reset --soft HEAD^

18
Можете ли вы объяснить разницу между 2 флагами?
Джон Джотта

1
Если вы откроете консоль диспетчера пакетов и запустите этот «git reset --soft HEAD ^», он сделает то, что вы хотите (и то, что мне было нужно).
Дэвид Корнельсон

54
@JohnGiotta - git reset --soft HEAD^удалит последний локальный (unpushed) совершить , но будет держать изменения , которые вы сделали
Fider

@fider Спаситель! Не уверен, что принятый ответ все еще работает, но это должен быть точный ответ, необходимый ОП.
Бабу

git reset --soft HEAD~на окнах
Jack0fshad0ws

34

Если вы находитесь в середине коммита (т.е. уже в редакторе), вы можете отменить его, удалив все строки выше первой #. Это прервет коммит.

Таким образом, вы можете удалить все строки, чтобы сообщение о фиксации было пустым, а затем сохранить файл:

Это должно выглядеть так.

Затем вы получите сообщение, которое говорит Aborting commit due to empty commit message..

РЕДАКТИРОВАТЬ :

Вы также можете удалить все строки, и результат будет точно таким же.

Чтобы удалить все строки в vim (если это ваш редактор по умолчанию), как только вы окажетесь в редакторе, напечатайте, ggчтобы перейти к первой строке, а затем dGудалить все строки. Наконец, напишите и выйдите из файла, wqи ваш коммит будет прерван.


3
Это именно то , что я искал! Этот ответ нуждается в большем количестве голосов :)
jdunk

К вашему сведению, это также работает, если вы пытаетесь прерватьrebase -i mybranchname
Иностия

18

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

Используйте git logдля отображения текущих сообщений о коммите, затем найдите commit_id перед коммитом, который вы хотите удалить, а не коммит, который вы хотите удалить.

Если вы хотите сохранить локально измененные файлы и просто удалить сообщение о коммите:

git reset --soft commit_id

Если вы хотите удалить все локально измененные файлы и сообщение о коммите:

git reset --hard commit_id

В этом разница мягкого и жесткого


1
Я думаю, что это наоборот.
Ruff9

9

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

--soft: Будут сброшены только коммиты, а индекс и рабочий каталог не изменены.

--mixed: При этом индекс будет сброшен в соответствии с заголовком, а рабочий каталог не будет затронут. Все изменения останутся в рабочем каталоге и появятся как измененные.

--hard: Он сбрасывает все (коммиты, индекс, рабочий каталог) в соответствии с заголовком.

В вашем случае я бы использовал git reset --softваши измененные изменения в индексе и рабочем каталоге. Не забудьте проверить это для более подробного объяснения.


1

Используйте команду ниже:

$ git reset HEAD~1

После этого вы также можете просматривать файлы, которые возвращаются обратно, как показано ниже.

Unstaged changes after reset:
M   application/config/config.php
M   application/config/database.php
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.