Перейти к содержимому

Как удалить коммит git

  • автор:

Как отменить последний коммит в git

Drupeople.ru

Если у вас возникла ситуация, когда вы уже сделали коммит, но хотите добавить в него новые данные, можно воспользоваться командой:

git commit -a --amend

ключ —amend будет означать что нужно добавить новые изменения в последний коммит.

Если вы сделали коммит, но решили его удалить (отменить), то есть 2 варианта решения этого вопроса.

Чтобы отменить коммит, но ОСТАВИТЬ все изменения (файлы и правки в файлах НЕ будут удалены), нужно ввести команду:

git reset --soft HEAD^

ключ —soft указывает на то что изменения не будут удалены

Чтобы удалить коммит и все файлы (изменения), нужно ввести команду:

git reset --hard HEAD^

ключ —hard говорит о том, что нужно удалить и коммит и файлы

Также вместо значения HEAD^ вы можете указать hash любого другого коммита (не последнего).

Все эти способы работают если вы еще не опубликовали изменения на сервере. Если же нужно отменить коммит на сервере, нужно воспользоваться командой:

git revert *COMMIT-sha1* git push

где *COMMIT-sha1* — id вашего коммита

14. Отмена коммитов

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

Мы отменим коммит путем создания нового коммита, отменяющего нежелательные изменения.

02 Измените файл и сделайте коммит

Измените файл hello.html на следующий.

Файл: hello.html
html>  head>  head>  body>  h1>Hello, World!h1>   body> html> 
Выполните
git add hello.html git commit -m "Oops, we didn't want this commit" 

03 Сделайте коммит с новыми изменениями, отменяющими предыдущие

Чтобы отменить коммит, нам необходимо сделать коммит, который удаляет изменения, сохраненные нежелательным коммитом.

Выполните
git revert HEAD 

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

Результат
$ git revert HEAD [main 86364a1] Revert "Oops, we didn't want this commit"  Date: Tue Nov 28 05:51:38 2023 -0600 1 file changed, 1 deletion(-) 

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

04 Проверьте лог

Проверка лога показывает нежелательные и отмененные коммиты в наш репозиторий.

Выполните
git log 
Результат
$ git log 86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main) [Alexander Shvets] 6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets] b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets] 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets] 78433de 2023-11-28 | Added h1 tag [Alexander Shvets] 5836970 2023-11-28 | Initial commit [Alexander Shvets] 

Эта техника будет работать с любым коммитом (хотя, возможно, возникнут конфликты). Она безопасна в использовании даже в публичных ветках удаленных репозиториев.

05 Далее

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

Git для начинающих. Часть 9. Как удалить коммит в git?

Follow us on Google Plus Follow us on rss

Рассмотрим довольно важный вопрос: как удалить коммит в git? Начнем с вопроса отмены изменений в рабочей директории, после этого перейдем к репозиторию. В рамках этой темы изучим вопросы удаления и замены последнего коммита, работу с отдельными файлами и использование команд git revert и git reset.

  • Отмена изменений в файлах в рабочей директории
  • Удаление коммитов в git
    • Работа с последним коммитом
    • Отмена изменений в файле в выбранном коммите
    • Использование git revert для быстрой отмены изменений
    • Удаление группы коммитов
      • Удаление коммитов из репозитория (без изменения рабочей директории) (ключ –soft)
      • Удаление коммитов из репозитория и очистка stage (без изменения рабочей директории) (ключ –mixed)
      • Удаление коммитов из репозитория, очистка stage и внесение изменений в рабочую директорию (ключ –hard)

      Отмена изменений в файлах в рабочей директории

      Если вы сделали какие-то изменения в файле и хотите вернуть предыдущий вариант, то для этого следует обратиться к репозиторию и взять из него файл, с которым вы работаете. Таким образом, в вашу рабочую директорию будет скопирован файл из репозитория с заменой. Например, вы работаете с файлом main.c и внесли в него какие-то изменения. Для того чтобы вернуться к предыдущей версии (последней отправленной в репозиторий) воспользуйтесь командой git checkout.

      > git checkout -- main.c

      Ключ “- -” означает, что нас интересует файл в текущем бранче (ветке).

      Отмена коммитов в git

      Работа с последним коммитом

      Для демонстранции возможностей git создадим новый каталог и инициализируем в нем репозиторий.

      > git init

      Добавим в каталог файл main.c.

      > touch main.c

      Отправим изменения в репозиторий.

      > git add main.c > git commit -m "first commit" [master (root-commit) 86f1495] first commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 main.c

      Внесем изменения в файл.

      > echo "// main.c file" > main.c

      И сделаем еще один коммит.

      > git add main.c > git commit -m "second commit" [master d142679] second commit 1 file changed, 1 insertion(+)

      В репозиторий, на данный момент, было сделано два коммита.

      > git log --oneline d142679 second commit 86f1495 first commit

      Теперь удалим последний коммит и вместо него отправим другой. Предварительно изменим содержимое файла main.c.

      > echo "// author: Writer" > main.c

      Отправим изменения в репозиторий с заметой последнего коммита.

      > git add main.c > git commit --amend -m "third commit" > git log --oneline 18411fd third commit 86f1495 first commit

      Как вы можете видеть: из репозитория пропал коммит с id=d142679, вместо него теперь коммит с id=18411fd.

      Отмена изменений в файле в выбранном коммите

      Сделаем ещё несколько изменений в нашем файле main.c, каждое из которых будет фиксироваться коммитом в репозиторий.

      > echo "// Some text 1" > main.c > git add main.c > git commit -m "fourth commit" [master dcf7253 ] fourth commit 1 file changed, 1 insertion(+), 1 deletion(-) > echo "// Some text 2" > main.c > git add main.c > git commit -m "fifth commit" [master 7f2eb3a ] fifth commit 1 file changed, 1 insertion(+), 1 deletion(-) > git log --oneline 7f2eb3a fifth commit dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Помните, что в предыдущем разделе мы поменяли коммит с сообщением “second commit” на “third commit”, поэтому он идет сразу после “first commit”.

      Представим ситуацию, что два последних коммита были неправильными, и нам нужно вернуться к версии 18411fd и внести изменения именно в нее. В нашем примере, мы работаем только с одним файлом, но в реальном проекте файлов будет много, и после коммитов, в рамках которых вы внесли изменения в интересующий вас файл, может быть ещё довольно много коммитов, фиксирующих изменения в других файлах. Просто так взять и удалить коммиты из середины ветки не получится – это нарушит связность, что идет в разрез с идеологией git. Одни из возможных вариантов – это получить версию файла из нужного нам коммита, внести в него изменения и сделать новый коммит. Для начала посмотрим на содержимое файла main.c из последнего, на текущий момент, коммита.

      > git checkout main.c > cat main.c // Some text 2

      Для просмотра содержимого файла в коммите с id=18411fd воспользуемся правилами работы с tree-ish (об этом подробно написано здесь)

      > git show 18411fd:main.c // author: Writer

      Переместим в рабочую директорию файл main.c из репозитория с коммитом id=18411fd.

      > git checkout 18411fd -- main.c > cat main.c // author: Writer

      Мы видим, что теперь содержимое файла main.c соответствует тому, что было на момент создания коммита с id=18411fd. Сделаем коммит в репозиторий и в сообщении укажем, что он отменяет два предыдущих.

      > git add main.c > git commit -m "return main.c from third commit" [master cffc5ad] return main.c from third commit 1 file changed, 1 insertion(+), 1 deletion(-) > git log --oneline cffc5ad return main.c from third commit 7f2eb3a fifth commit dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Таким образом мы вернулись к предыдущей версии файла main.c и при этом сохранили всю историю изменений.

      Использование git revert для быстрой отмены изменений

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

      В нашем примере, отменим коммит с id=cffc5ad. После того как вы введете команду git revert (см. ниже), система git выдаст сообщение в текстовом редакторе, если вы согласны с тем, что будет написано в открытом файле, то просто сохраните его и закройте. В результате изменения будут применены, и автоматически сформируется и отправится в репозиторий коммит.

      > git revert cffc5ad [master 81499da] Revert "return main.c from third commit" 1 file changed, 1 insertion(+), 1 deletion(-)

      Если вы хотите поменять редактор, то воспользуйтесь командой.

      > git config core.editor "notepad.exe"

      Обратите внимание, что в этом случае будут изменены настройки для текущего репозитория. Более подробно об изменении настроек смотрите в “Git для начинающих. Часть 3. Настройка Git”

      Проверим, применялась ли настройка.

      > git config core.editor notepad.exe

      Посмотрим на список коммитов в репозитории.

      > git log --oneline 81499da Revert "return main.c from third commit" cffc5ad return main.c from third commit 7f2eb3a fifth commit dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Содержимое файла вернулось к тому, что было сделано в рамках коммита с >

      > cat main.c // Some text 2 > git show 7f2eb3a:main.c // Some text 2

      Отмена группы коммитов

      ВНИМАНИЕ! Используйте эту команду очень аккуратно!

      Если вы не знакомы с концепцией указателя HEAD, то обязательно прочитайте статью “ Git для начинающих. Часть 7. Поговорим о HEAD и tree-ish“. HEAD указывает на коммит в репозитории, с которого будет вестись дальнейшая запись, т.е. на родителя следующего коммита. Существует три опции, которые можно использовать с командой git reset для изменения положения HEAD и управления состоянием stage и рабочей директории, сейчас мы все это подробно разберем.

      Удаление коммитов из репозитория (без изменения рабочей директории) (ключ –soft)

      Для изменения положения указателя HEAD в репозитории, без оказания влияния рабочую директорию (в stage, при этом, будет зафиксированно отличие рабочей директории от репозитория), используйте ключ –soft. Посмотрим ещё раз на наш репозиторий.

      > git log --oneline 81499da Revert "return main.c from third commit" cffc5ad return main.c from third commit 7f2eb3a fifth commit dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Содержимое файла main.с в рабочей директории.

      > cat main.c // Some text 2

      Содержимое файла main.с в репозитории.

      > git show HEAD:main.c // Some text 2

      Теперь переместим HEAD в репозитории на коммит с id=dcf7253.

      > git reset --soft dcf7253

      Получим следующий список коммитов.

      > git log --oneline dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Содержимое файла main.c в репозитории выглядит так.

      > git show HEAD:main.c // Some text 1

      В рабочей директории файл main.c остался прежним (эти изменения отправлены в stage).

      > cat main.c // Some text 2

      Для того, чтобы зафиксировать в репозитории последнее состояние файла main.c сделаем коммит.

      > git commit -m "soft reset example" [master db1a8b0] soft reset example 1 file changed, 1 insertion(+), 1 deletion(-)

      Посмотрим на список коммитов.

      > git log --oneline db1a8b0 soft reset example dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Как видите из репозитория пропали следующие коммиты:

      81499da Revert "return main.c from third commit" cffc5ad return main.c from third commit 7f2eb3a fifth commit
      Удаление коммитов из репозитория и очистка stage (без изменения рабочей директории) (ключ –mixed)

      Если использовать команду git reset с аргументом –mixed, то в репозитории указатель HEAD переместится на нужный коммит, а также будет сброшено содержимое stage. Отменим последний коммит.

      > git reset --mixed dcf7253 Unstaged changes after reset: M main.c

      В результате изменилось содержимое репозитория.

      > git log --oneline dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Содержимое файла main.c в последнем коммите выглядит так.

      > git show HEAD:main.c // Some text 1

      Файл main.c в рабочей директории не изменился.

      > cat main.c // Some text 2

      Отправим изменения вначале в stage, а потом в репозиторий.

      > git add main.c > git commit -m "mixed reset example" [master ab4ef00] mixed reset example 1 file changed, 1 insertion(+), 1 deletion(-)
      Удаление коммитов из репозитория, очистка stage и внесение изменений в рабочую директорию (ключ –hard)

      Если вы воспользуетесь ключем –hard, то обратного пути уже не будет. Вы не сможете восстановить данные из рабочей директории. Все компоненты git (репозиторий, stage и рабочая директория) будут приведены к одному виду в соответствии с коммитом, на который будет перенесен указатель HEAD.

      Текущее содержимое репозитория выглядит так.

      > git log --oneline ab4ef00 mixed reset example dcf7253 fourth commit 18411fd third commit 86f1495 first commit

      Посмотрим на содержимое файла main.c в каталоге и репозитории.

      > cat main.c // Some text 2 > git show HEAD:main.c // Some text 2

      Содержимое файлов идентично.

      Удалим все коммиты до самого первого с id=86f1495.

      > git reset --hard 86f1495 HEAD is now at 86f1495 first commit
      > git log --oneline 86f1495 first commit

      Состояние рабочей директории и stage.

      > git status On branch master nothing to commit, working tree clean

      Содержимое файла main.c в репозитории и в рабочей директории.

      > cat main.c > git show HEAD:main.c

      Т.к. мы воспользовались командой git reset с ключем –hard, то восстановить прежнее состояние нам не получится.

      БУДЬТЕ ОЧЕНЬ АККУРАТНЫ С ЭТОЙ КОМАНДОЙ!

      Отличный курс по git делают ребята из GeekBrains , найдите в разделе “Курсы” курс “Git. Быстрый старт” , он бесплатный!

      Раздел: Git Git для начинающих Метки: Git, Git для начинающих, Уроки по Git

      Git для начинающих. Часть 9. Как удалить коммит в git? : 2 комментария

      1. Paul 12.04.2018 Работа с последним коммитом:
        git commit –amend -m “third commit” Это отменяет последний коммит, но не возвращает файл в исходное состояние.
        А в какой задаче это может быть полезно?
      1. adminka 14.04.2018 Эта команда перезаписывает последний коммит (т.е. последний удаляется и на его место встает новый), файл в исходное состояние не возвращается.

      А в какой задаче это может быть полезно?

      хм… хороший вопрос! Даже затрудняюсь на него ответить. Ну например, вы закоммитили какой-то “ужас” и не хотите, чтобы он стал достоянием общественности))

      Как удалить commit на Github?

      1. Как удалить самый первый тестовый комит на гитхаб
      пробывал git reset —hard HEAD, но он один, и поэтому не могу нигде найти как его удалить
      И как это сделать так что бы на гитхабе его тоже не было.
      p.s только начал пользоваться гитом поэтому сори за возможно глупые вопросы

      • Вопрос задан более двух лет назад
      • 6930 просмотров

      Комментировать
      Решения вопроса 2

      sergey-kuznetsov

      Сергей Кузнецов @sergey-kuznetsov Куратор тега Git
      Автоматизатор

      Раз первый коммит единственный и он тебе не нужен, то можно просто удалить репозиторий на GitHub и создать заново. Но можно и не пересоздавать:

      # удалить все файлы в рабочей копии git rm -r * # создать на месте первого коммита пустой коммит git commit --allow-empty --amend --message "Initial commit" # отправить текущую ветку на GitHub git push --force

      Получишь чистый репозиторий с начальным пустым коммитом.
      Сам пустой коммит можно использовать как основу для построения своего дерева коммитов.
      Либо через ключ —amend замени его на что-то более осмысленное.

      А ещё лучше не заниматься ерундой, исправить код и исправить коммит ключиком —amend

      Ответ написан более двух лет назад
      Нравится 1 14 комментариев
      ebaysher @ebaysher Автор вопроса

      $ git rm *
      fatal: not removing ‘Chess’ recursively without -r
      Сделал:
      git rm -r Chess
      git commit —allow-empty —amend —all —message «Initial commit»
      git push —force,
      Содержимое коммита не изменилось (кроме названия),
      а весь код в файле Chess удалился
      Как откатить теперь назад и вернуть код?

      sergey-kuznetsov

      Сергей Кузнецов @sergey-kuznetsov Куратор тега Git

      Тогда так
      git rm -r .
      Удалить желательно всё

      Потом закоммитить факт удаления и посмотреть содержимое коммита перед тем как пушить.

      Что значит код в файле удалился? Должен был удалиться не код, а сам файл. Точнее все файлы по маске .

      ebaysher @ebaysher Автор вопроса

      Сергей Кузнецов, У меня почему то после команды git rm -r, студия загрузилась и удалились неколько файлов с классами. Теперь пытаюсь разобраться как назад откатить.

      sergey-kuznetsov

      Сергей Кузнецов @sergey-kuznetsov Куратор тега Git

      Если речь про https://github.com/ebaysher/chess
      то там вообще нет такого файла или папки. Удали всё руками просто в проводнике.
      И потом коммит.

      Ты точно уверен что надо удалить коммит? Вариант с исправлением кода на нужный не подходит?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *