Git: как отменить коммит *и* вернуться к последней ветке

О, о ... Я по ошибке совершил довольно сложное изменение (включая переименование подкаталогов и файлов), не зная, что я делаю (или что будет делать Git).

Теперь я хочу отменить все, что:

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

Я нашел ссылки на git reset --soft и git reset --hard но я уже доказал себе, что я может нанести реальный ущерб, преждевременно используя команду, не полностью ее понимая. :)

Я нашел справочную страницу git reset, но я все еще не понимаю:

  1. Что такое HEAD?
  2. В чем разница между HEAD и * master?
  3. В моей ситуации (см. выше) мне нужно использовать --soft, --hard или другие (еще 3 варианта)?
  4. Нужно ли запускать другую команду (после выполнения git reset), чтобы "финализировать" реверсирование?

ОБНОВЛЕНИЕ: после прочтения ответа ниже:

  1. Правильно ли я понимаю, что все, что мне нужно сделать в моей ситуации, это ввести одну команду git reset --hard HEAD^?
  2. Как проверить правильность выполнения реверсирования?

person WinWin    schedule 08.07.2011    source источник
comment
Поскольку вы изучаете git, позвольте мне порекомендовать вам две книги: книга сообщества git и pro git, которые полностью доступны онлайн.   -  person shelhamer    schedule 08.07.2011


Ответы (2)


  1. HEAD — это последняя фиксация проверенной ветки.
  2. master — это ветвь (главная ветвь, по соглашению), тогда как HEAD — это место в истории для проверенной ветки. HEAD относится к ветке, в которой вы находитесь.
  3. git reset --soft оставит ваши изменения в рабочем дереве незафиксированными, чтобы вы могли делать с ними все, что захотите. git reset --hard восстановит рабочее дерево до состояния, в котором оно было при фиксации, к которой вы сбросились.
  4. Никакой другой команды не требуется.

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

git checkout -b my_bad_commit

(или, альтернативно, сделайте git branch my_bad_commit, как указано в комментарии Ларсмана.)

Затем вернитесь к master или любой другой ветке, в которой вы были, и выполните сброс:

git checkout branch_with_bad_commit
git reset --hard HEAD^

HEAD^ переводится как «родитель HEAD», который вы даже можете сложить для HEAD^^ = 2 коммитов. Дополнительную информацию по этой теме можно найти в главе книги сообщества git, посвященной отмене действий в git.

person shelhamer    schedule 08.07.2011
comment
Последовательность checkout -b; checkout можно выполнить с помощью одной команды branch. - person Fred Foo; 08.07.2011
comment
Хороший момент, чтобы упомянуть об этом. У меня так много псевдонимов, что я просто делаю git cob new_branch_name, что иногда забываю настоящие. - person shelhamer; 08.07.2011
comment
@Shelhamer Выполнение git checkout master и git reset --hard HEAD^ вернуло меня на два коммита. Это не то, чего я хотел. Мне нужно было пройти всего один шаг назад. Что-то, должно быть, было неясно в моем вопросе. - person WinWin; 08.07.2011
comment
@WinWin, возможно, произошло некоторое недопонимание, если ваша главная ветка не содержала плохой фиксации (именно поэтому я сказал ... или в любой другой ветке, на которой вы были, имея в виду проверить эту ветку. Если вы потеряли немного истории, вы нужно вернуть, используйте git reflog, чтобы восстановить его.В нем будут перечислены предыдущие HEAD, которые вы можете проверить или сбросить. - person shelhamer; 08.07.2011
comment
@Shelhamer Спасибо за совет git reflog. Ссылки на книги бесценны. Однако мне потребуется время, чтобы их проглотить. Я все еще не уверен, почему одного git reset --hard HEAD^ будет недостаточно (поскольку я действительно не хочу сохранять фиксацию. В этом суть). - person WinWin; 08.07.2011
comment
@WinWin, в своем вопросе вы упомянули, что хотите где-то сохранить фиксацию (возможно, удалив ее историю или нет). Если вас действительно не волнует коммит, вы можете просто выполнить git reset --hard HEAD^ на ветке с плохим коммитом, чтобы указать HEAD на коммит перед плохим, как будто плохого никогда не существовало. - person shelhamer; 08.07.2011

  1. HEAD — это конец текущей ветки.
  2. Разница между HEAD и master заключается в том, что HEAD изменяется при извлечении ветки (или фиксации).
  3. --soft оставит изменения, поэтому вы можете повторно добавить/фиксировать их или отменить их, выполнив git checkout для измененных файлов. --hard сбросит рабочую область до состояния коммита, к которому вы сбрасываете.
  4. Нет, если вы reset --hard. Возможно, вам придется git push --force использовать удаленные репозитории (хотя, если внесенные вами изменения уже находятся на удаленном репозитории, настоятельно не рекомендуется переписывать историю).
person Fred Foo    schedule 08.07.2011
comment
Спасибо +1. К счастью, я еще ничего не нажимал. Значит, git reset --hard HEAD^ в одиночку поможет мне? - person WinWin; 08.07.2011
comment
Если вы хотите отменить только последний коммит, да. Чтобы быть в безопасности, вы также можете сделать git branch mistake перед git reset --hard; если что-то пойдет не так, вы можете git merge mistake вернуть ошибочную фиксацию. - person Fred Foo; 08.07.2011
comment
OMG, после стольких лет использования CVS я чувствую себя полным новичком в этом мире git. :) - person WinWin; 08.07.2011
comment
Как ни странно, я никогда не мог понять CVS или SVN, но переключившись на Git, я словно вернулся домой ;) - person Fred Foo; 08.07.2011