14. Отмена локальных изменений (до индексации)
Убедитесь, что вы находитесь на последнем коммите ветки master, прежде чем продолжить работу.
Выполните:
02 Измените hello.html
Иногда случается, что вы изменили файл в рабочем каталоге, и хотите отменить последние коммиты. С этим справится команда checkout .
Внесите изменение в файл hello.html в виде нежелательного комментария.
Файл: hello.html
03 Проверьте состояние
Сначала проверьте состояние рабочего каталога.
Выполните:
Результат:
Мы видим, что файл hello.html был изменен, но еще не проиндексирован.
04 Отмена изменений в рабочем каталоге
Используйте команду checkout для переключения в версию файла hello.html в репозитории.
Выполните:
Результат:
Команда status показывает нам, что не было произведено никаких изменений, не зафиксированных в рабочем каталоге. И «нежелательный комментарий» больше не является частью содержимого файла.
Обзор команд Git для отмены изменений
![]()
Предположим, что мы случайно удалили файл, например myfile.txt :
Для его восстановления выполняем команду:
Отменяем индексирование файла
Допустим, мы по ошибке проиндексировали файл, выполнив команду git add myfilename . Для отмены этого действия воспользуемся командой:
Восстанавливаем предыдущие версии
Посмотрим, как восстановить более ранние версии в случае необходимости. С помощью команды git log переходим в историю коммитов, выбираем код SHA ранней версии (достаточно первых символов) и выполняем команду git checkout <SHA> :
Получаем следующее сообщение:
Вы увидите, что находитесь в более ранней версии. Вышеприведенная команда вывода checkout объясняет ситуацию. Эти изменения можно сохранить, если создать новую ветку.
Оказавшись в состоянии “detached HEAD” вполне можно запаниковать, не зная, как вернуться к последней версии в главной ветке master . Посмотрим, как это сделать:
Откатываем изменения на один коммит
Для отмены предыдущего коммита выполняем команду:
Удаляем неотслеживаемый файл
Допустим, вы добавили файлы, которые еще не подготовлены к коммиту. Чтобы от них избавиться, выполняем команду:
Это пробный запуск, который отображает файлы, подлежащие удалению. Подтверждаем выполнение этой операции командой:
Отменяем git init
Работая с Git, вы инициализируете проект с помощью git init . Для отмены данной операции просто удаляем файл .git из каталога.
Дополнительные команды: удаляем файл из удаленного репозитория
При работе с Git и GitHub/GitLab можно случайно отправить файл в удаленный репозиторий. В таком случае возникает необходимость его удалить. Рассмотрим ситуацию на примерах. Создаем удаленный репозиторий GitHub и локально его клонируем:
Меняем рабочий каталог на клонированный репозиторий. Как видно, здесь есть файлы README.md и .git .
Далее создаем файл wrong.txt , который мы отправим в удаленный репозиторий:
Файл wrong.txt добавлен в удаленный репозиторий.
Удаляем файл
При необходимости удалить файл как из удаленного каталога, так и локальной файловой системы выполняем команды:
Как видим, цель достигнута:
Удаляем файл из удаленного репозитория Git, но сохраняем его локально
Повторяем последовательность действий по созданию файла wrong.txt , который на этот раз мы удалим только из удаленного репозитория:
Отправляем файл wrong.txt :
Удаляем wrong.txt только из удаленного репозитория. Для этого используем тег cached .
Проверяем локальный репозиторий:
Проверяем удаленный каталог:
wrong.txt успешно удален из удаленного репозитория!
Со списком наиболее распространенных команд Git и GitHub вы можете ознакомиться по ссылке Git and GitHub Cheatsheet.
Отмена коммитов и изменений
В этом разделе мы обсудим доступные стратегии и команды Git для выполнения отмены изменений. Прежде всего необходимо отметить, что в Git не существует традиционной системы отмены, как в текстовых редакторах. Лучше воздержаться от сопоставления операций Git с какой бы то ни было традиционной концепцией отмены изменений. Кроме того, Git имеет собственную систему терминов для операций отмены, и в обсуждении лучше всего использовать их. В числе таких терминов — сброс (reset), возврат (revert), переключение (checkout), очистка (clean) и другие.
Git можно рассматривать как инструмент для управления временной шкалой. Коммиты — это снимки моментов времени или точек интереса на временной шкале истории проекта. Кроме того, с помощью веток можно управлять несколькими временными шкалами. Когда вы выполняете операцию отмены в Git, вы, как правило, перемещаетесь назад во времени или на другую временную шкалу, где ошибок не было.
Это руководство предоставляет все необходимые навыки для работы с предыдущими версиями проекта по разработке программного обеспечения. Сначала мы рассмотрим, как исследовать старые коммиты, а затем изучим разницу между отменой публичных коммитов в истории проекта и сбросом неопубликованных изменений на локальном компьютере.
Поиск утерянного: просмотр старых коммитов
В основе любой системы управления версиями лежит идея хранения «безопасных» копий проекта, чтобы у разработчиков не возникало опасений безвозвратно испортить базу кода. Когда в проекте сохранена история коммитов, можно повторно оценивать и анализировать любые ранее выполненные коммиты. Один из лучших инструментов для просмотра истории репозитория Git — команда git log . В примере ниже мы используем команду git log для получения последних коммитов популярной графической библиотеки с открытым исходным кодом.
Каждый коммит имеет уникальный идентифицирующий хеш SHA-1. Эти идентификаторы используются для перемещения по временной шкале коммитов и возвращения к коммитам. По умолчанию git log показывает только коммиты текущей выбранной ветки. Но не исключено, что искомый коммит находится в другой ветке. Для просмотра всех коммитов во всех ветках используется команда git log —branches=* . Команда git branch используется для просмотра и посещения других веток. Так, команда git branch -a возвращает список имен всех известных веток. Просмотреть весь журнал коммитов одной из этих веток можно с помощью команды git log .
После того как вы нашли ссылку на нужный коммит в истории, для перехода к нему можно использовать команду git checkout . Команда git checkout — это простой способ «загрузить» любой из этих сохраненных снимков на компьютер разработчика. При стандартном процессе разработки указатель HEAD обычно указывает на главную ветку main или другую локальную ветку. Но при переключении на предыдущий коммит HEAD указывает уже не на ветку, а непосредственно на сам коммит. Такая ситуация называется состоянием открепленного указателя HEAD , и ее можно представить так:
Переход к старой версии файла не перемещает указатель HEAD . Он остается в той же ветке и в том же коммите, что позволяет избежать открепления указателя HEAD. После этого можно выполнить коммит старой версии файла в новый снимок состояния, как и в случае других изменений. Соответственно, такое использование команды git checkout применительно к файлу позволяет откатиться к прежней версии отдельного файла. Для получения дополнительной информации об этих двух режимах посетите страницу команды git checkout .
Просмотр старых версий
В этом примере предполагается, что вы начали разработку безумного эксперимента, но не уверены, хотите его сохранить или нет. Чтобы принять решение, вы хотите взглянуть на состояние проекта до начала эксперимента. Прежде всего, нужно найти идентификатор редакции, которую вы хотите просмотреть.
Допустим, история вашего проекта выглядит примерно так:
Для просмотра коммита «Make some important changes to hello.txt» можно использовать команду git checkout в следующем виде:
Это приведет к тому, что ваш рабочий каталог будет в точности соответствовать состоянию коммита a1e8fb5 . Вы можете просматривать файлы, компилировать проект, запускать тесты и даже редактировать файлы, не боясь потерять текущее состояние проекта. Никакие внесенные здесь изменения не будут сохранены в репозитории. Чтобы продолжить разработку, необходимо вернуться к текущему состоянию проекта:
Предположим, вы ведете разработку в главной ветке main по умолчанию. При каждом возвращении в ветку main можно использовать команду git revert или git reset для отмены нежелательных изменений.
Отмена коммита снимка
Технически существует несколько стратегий отмены коммитов. В дальнейших примерах предполагается, что история коммитов выглядит следующим образом:
Займемся отменой коммита 872fa7e Try something crazy . Возможно, безумный эксперимент зашел слишком далеко.
Отмена коммита с помощью git checkout
С помощью команды git checkout мы можем перейти к предыдущему коммиту , a1e8fb5, и вернуть репозиторий в состояние, предшествовавшее этому безумному коммиту. Переход к отдельному коммиту переведет репозиторий в состояние открепленного указателя HEAD . Работа при этом перестает принадлежать какой-либо из веток. При открепленном указателе HEAD все новые коммиты будут оставаться без родителя, пока вы не вернете ветки в положенное состояние. «Сборщик мусора» в Git удаляет коммиты без родителя. Этот сервис работает с определенными интервалами и удаляет такие коммиты без возможности восстановления. Чтобы такие коммиты не были удалены «сборщиком мусора», перед их выполнением нужно убедиться, что мы работаем в ветке.
При наличии открепленного указателя HEAD можно выполнить команду git checkout -b new_branch_without_crazy_commit . Она создаст новую ветку с именем new_branch_without_crazy_commit и совершит переход в это состояние. Теперь репозиторий находится на новой временной шкале, где коммита 872fa7e не существует. На этом этапе мы можем продолжить работу в новой ветке, где коммита 872fa7e не существует и его можно считать «отмененным». К сожалению, если вам нужна предыдущая ветка (возможно, это главная ветка main ), такая стратегия не подходит. Поэтому рассмотрим другие стратегии отмены. Более детальную информацию и примеры см. в нашей подробной статье о git checkout .
Отмена публичного коммита с помощью git revert
Предположим, мы вернулись к исходному примеру истории коммитов. Истории, в которую входит коммит 872fa7e . В этот раз попробуем отмену путем обратной операции. При исполнении команды git revert HEAD Git создаст новый коммит с операцией, обратной последнему коммиту. В текущую историю ветки будет добавлен новый коммит, и она будет выглядеть следующим образом:
На этом этапе мы снова технически «отменили» коммит 872fa7e . Хотя коммит 872fa7e по-прежнему существует в истории, новый коммит e2f9a78 отменил изменения 872fa7e . В отличие от нашей предыдущей стратегии переключения с помощью команды checkout, мы можем продолжить работать с этой же веткой, поэтому данная стратегия является удовлетворительной. Это идеальный способ отмены при работе в открытых общих репозиториях, однако если у вас есть требование вести минимальную «очищенную» историю Git, эта стратегия может не подойти.
Отмена коммита с помощью git reset
Рассмотрение этой стратегии отмены мы продолжим на нашем рабочем примере. Команда git reset — это расширяемая команда с разнообразными функциями и вариантами использования. Если мы выполним команду git reset —hard a1e8fb5 , история коммитов будет сброшена до указанного коммита. Просмотр истории коммитов с помощью команды git log теперь будет выглядеть так:
Вывод команды log показывает, что коммиты e2f9a78 и 872fa7e больше не существуют в истории. На этом этапе мы можем продолжить работу и создавать новые коммиты так, словно «безумных» коммитов никогда не было. Этот метод отмены изменений оставляет историю максимально чистой. Отмена с помощью команды reset отлично подходит для локальных изменений, но при работе в общем удаленном репозитории создает сложности. Если у нас есть общий удаленный репозиторий, в котором с помощью команды push опубликован коммит 872fa7e , и мы попытаемся выполнить команду git push для ветки, в которой с помощью команды reset была сброшена история, система Git обнаружит это и выдаст ошибку. Git будет считать, что публикуемая ветка не была обновлена, поскольку в ней отсутствуют коммиты. В таких случаях лучше использовать отмену с помощью команды git revert .
Отмена последнего коммита
В предыдущем разделе мы рассмотрели различные стратегии отмены коммитов. Эти стратегии также можно применять и к последнему коммиту. Однако иногда последний коммит можно не удалять и не сбрасывать. Например, если вы просто сделали коммит преждевременно. В этом случае его можно исправить. После того как вы внесете дополнительные изменения в рабочий каталог и добавите их в раздел проиндексированных файлов с помощью команды git add , выполните команду git commit —amend . При этом Git откроет настроенный системный редактор, где вы сможете изменить комментарий к последнему коммиту. Новые изменения будут добавлены в исправленный коммит.
Отмена неотправленных изменений
Пока не выполнен коммит изменений в историю репозитория, они находятся в разделе проиндексированных файлов и в рабочем каталоге. Вам может потребоваться отменить изменения в этих двух областях. Раздел проиндексированных файлов и рабочий каталог являются внутренними механизмами управления состоянием Git. Подробную информацию о том, как работают эти два механизма, см. на странице git reset , где приводится их подробное описание.
Рабочий каталог
Рабочий каталог обычно синхронизируется с локальной файловой системой. Чтобы отменить изменения в рабочем каталоге, можно просто отредактировать файлы с помощью привычного редактора. Git имеет два инструмента для управления рабочим каталогом. Это команда git clean — удобная утилита для отмены изменений в рабочем каталоге, и команда git reset , которую можно вызвать с параметрами —mixed или —hard , чтобы сбросить изменения в рабочем каталоге.
Раздел проиндексированных файлов
Команда git add используется для добавления изменений в раздел проиндексированных файлов. Команда git reset предназначена главным образом для отмены изменений в разделе проиндексированных файлов. Команда reset с параметром —mixed перемещает все ожидающие изменения из раздела проиндексированных файлов обратно в рабочий каталог.
Отмена публичных изменений
При командной работе в удаленных репозиториях необходимо подходить к отмене изменений с особой осторожностью. Команда git reset , как правило, считается методом локальной отмены. Ее следует использовать для отмены изменений в частной ветке. Она безопасно изолирует удаление коммитов от других веток, которые могут использоваться другими разработчиками. Проблемы возникают, когда команда reset выполняется в общей ветке и затем эта ветка удаленно публикуется с помощью команды git push . В этом случае Git блокирует выполнение команды push и сообщает, что публикуемая ветка устарела, поскольку в ней отсутствуют коммиты, которые есть в удаленной ветке.
Предпочтительная команда для отмены общей истории коммитов — git revert . Команда revert безопаснее, чем reset, так как она не удаляет коммиты из общей истории. Команда revert сохраняет отменяемые вами коммиты и создает новый коммит с операцией, обратной последнему коммиту. Этот метод можно безопасно применять в общих распределенных рабочих средах, так как удаленный разработчик может выполнить пул ветки и получить новый коммит, который отменяет его нежелательный коммит.
Резюме
Мы рассмотрели множество общих стратегий отмены изменений в Git. Важно помнить, что отменить изменения в проекте Git можно несколькими способами. Кроме того, здесь были затронуты и более сложные темы, которые подробно рассматриваются на страницах, посвященных соответствующим командам Git. Наиболее часто используемые инструменты для отмены — это команды git checkout, git revert и git reset . Вот несколько ключевых моментов, о которых следует помнить.
- Обычно после коммита внесенные изменения отменить невозможно
- Используйте git checkout для переходов и просмотра истории коммитов
- Команда git revert — лучший инструмент для отмены общих публичных изменений.
- Команду git reset лучше всего использовать для отмены локальных частных изменений.
Помимо основных команд отмены, мы рассмотрели другие команды Git: git log для поиска потерянных коммитов, git clean для отмены изменений, не подтвержденных коммитами, и git add для изменения индексирования.
Каждая из этих команд имеет собственную подробную документацию. Чтобы узнать больше о той или иной команде, пройдите по соответствующим ссылкам.
Git, я хочу все отменить! Команды исправления допущенных ошибок

Git — удобная, но довольно сложная система. Сложность, прежде всего, в том, что по невнимательности можно допустить ошибку, которую затем сложно или вообще невозможно исправить. Документация Git предоставляет описание множества команд, которые дают возможность исправить ошибку.
Но вся штука в том, что для исправления проблемы нужно знать точное название команды. И здесь у нас возникает типичная проблема курицы и яйца. В этой статье рассказывается о командах, которые помогают решить проблемные ситуации.
Черт, я сделал что-то не то. Дайте мне волшебную машину времени!

Эта команда позволяет восстановить случайно удаленные данные, откатив слияние, после которого случилась неприятность. refLog используется ну очень часто — давайте скажем спасибо тому, что предложил добавить эту команду.
Я сделал коммит, но сразу же заметил ошибку, ее нужно исправить!
Команда дает возможность поправить неприятные мелочи — когда вы что-то закоммитили, а потом увидели проблему вроде отсутствующего пробела после знака » plaintext»>git commit —amend # follow prompts to change the commit message
Это просто… глупые требования к оформлению сообщений.
Я случайно закоммитил в мастер, хотя это должен был в новую ветку!
Если вы уже закоммитили в публичную ветку, команды не сработают. В этом случае поможет git reset HEAD@ <укажите количество коммитов, на которое нужно вернуться>вместо HEAD
Ну вот, я ошибочно закоммитил не в ту ветку
Есть еще один способ, который использует большое количество разработчиков — это cherry-pick.
Мне нужно запустить diff, но ничего не получается
Если вы уверены в том, что изменения были внесены, но diff пустой, вполне может быть, что вы индексировали изменения через add. Поэтому стоит использовать специальный флаг.
git diff —staged
В общем, это не баг, а фича, но она чертовски неочевидная ¯\_(ツ)_/¯
Мне срочно нужно отменить коммит, который сделан 5 коммитов назад
К счастью, не нужно отказываться назад на 5 коммитов, занимаясь копипастом старых и новых файлов. Отменить все это можно при помощи revert.
Кроме того, откатить можно не только коммит, но и целый файл. Правда, это уже будут другие команды…
Отменить изменения в файле
А вот и они, эти другие команды.
Когда я впервые нашел эту возможность, это было КРУТО, КРУТО, К-Р-У-Т-О. Но если задуматься — почему именно checkout — лучший вариант для отмены изменений в файле? :shakes-fist-at-linus-torvalds:
Все, я сдаюсь
Спасибо Eric V. За этот способ. И все жалобы по поводу использования sudo адресуйте ему.
Если вам нужно обнулить изменения и полностью откатиться до исходной версии, то можно попробовать сделать именно так. Но помните — эти команды разрушительны и необратимы.
Внимание! Эта статья не является исчерпывающим руководством. И да, есть и другие способы сделать то же самое, причем еще лучше. Но я пришел именно к этим вариантам методом проб и ошибок. Потом у меня появилась сумасшедшая идея поделиться находками. Берите это или уходите!

Комментарий эксперта
Даниил Пилипенко, директор центра подбора IT-специалистов SymbioWay и евангелист бэкенд-направления онлайн-университета Skillbox, дополнил перевод мнением о Git и его актуальности для разработчиков.
Git появился в 2005-ом году, и он далеко не сразу занял рынок. Помню, когда мы ещё в 2008-ом году в команде разработчиков внедряли SVN. И даже в 2012-ом одна близкая ко мне компания усиленно внедряла Mercurial. С годами для многих стало очевидным, что Git — это лучшая система контроля версий, и её теперь используют практически все разработчики.
Если вы начинающий разработчик и собираетесь устраиваться на работу, обязательно изучите Git! Вы должны знать, что такое система контроля версий и зачем она нужна, что такое коммит, ветка, как клонировать репозиторий и отправлять сделанные изменения на сервер, как получать новые изменения с сервера, как делать merge, какие бывают виды “reset”. Поначалу эта тема вам может показаться непонятной и сложной, но вам нужно лишь привыкнуть пользоваться Git, и отвыкнуть вы уже не сможете.