How to Undo a Git Add

To undo git add before a commit, run git reset <file> or git reset to unstage all changes.
In older versions of Git, the commands were git reset HEAD <file> and git reset HEAD respectively. This was changed in Git 1.8.2
You can read more about other commonly used Git actions in these helpful articles:
Here’s a bit more background information about Git
Understand the Three Sections of a Git Project
A Git project will have the following three main sections:
- Git directory
- Working directory (or working tree)
- Staging area
The Git directory (located in YOUR-PROJECT-PATH/.git/ ) is where Git stores everything it needs to accurately track the project. This includes metadata and an object database which includes compressed versions of the project files.
The working directory is where a user makes local changes to a project. The working directory pulls the project’s files from the Git directory’s object database and places them on the user’s local machine.
The staging area is a file (also called the “index”, “stage”, or “cache”) that stores information about what will go into your next commit. A commit is when you tell Git to save these staged changes. Git takes a snapshot of the files as they are and permanently stores that snapshot in the Git directory.
With three sections, there are three main states that a file can be in at any given time: committed, modified, or staged. You modify a file any time you make changes to it in your working directory. Next, it’s staged when you move it to the staging area. Finally, it’s committed after a commit.
Install Git
- Ubuntu: sudo apt-get install git
- Windows: Download
- Mac: Download
Configure the Git Environment
Git has a git config tool that allows you to customize your Git environment. You can change the way Git looks and functions by setting certain configuration variables. Run these commands from a command line interface on your machine (Terminal in Mac, Command Prompt or Powershell in Windows).
There are three levels of where these configuration variables are stored:
- System: located in /etc/gitconfig , applies default settings to every user of the computer. To make changes to this file, use the —system option with the git config command.
- User: located in
If there are settings that conflict with each other, the project-level configurations will override the user-level ones, and the user-level configurations will override the system-level ones.
Note for Windows users: Git looks for the user-level configuration file ( .gitconfig ) in your $HOME directory ( C:\Users\$USER ). Git also looks for /etc/gitconfig , although it’s relative to the MSys root, which is wherever you decide to install Git on your Windows system when you run the installer. If you are using version 2.x or later of Git for Windows, there is also a system-level config file at C:\Documents and Settings\All Users\Application Data\Git\config on Windows XP, and in C:\ProgramData\Git\config on Windows Vista and newer. This config file can only be changed by git config -f FILE as an admin.
Add Your Name and Email
Git includes the user name and email as part of the information in a commit. You’ll want to set this up under your user-level configuration file with these commands:
Change Your Text Editor
Git automatically uses your default text editor, but you can change this. Here’s an example to use the Atom editor instead (the —wait option tells the shell to wait for the text editor so you can do your work in it before the program moves on):
Add Color to Git Output
You can configure your shell to add color to Git output with this command:
To see all your configuration settings, use the command git config —list .
Initialize Git in a Project
Once Git is installed and configured on your computer, you need to initialize it in your project to start using its version control powers. In the command line, use the cd command to navigate to the top-level (or root) folder for your project. Next, run the command git init . This installs a Git directory folder with all the files and objects Git needs to track your project.
It’s important that the Git directory is installed in the project root folder. Git can track files in subfolders, but it won’t track files located in a parent folder relative to the Git directory.
Get Help in Git
If you forget how any command works in Git, you can access Git help from the command line several ways:
This displays the manual page for the command in your shell window. To navigate, scroll with the up and down arrow keys or use the following keyboard shortcuts:
Отмена коммитов и изменений
В этом разделе мы обсудим доступные стратегии и команды 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 для изменения индексирования.
Каждая из этих команд имеет собственную подробную документацию. Чтобы узнать больше о той или иной команде, пройдите по соответствующим ссылкам.
2.4 Основы Git — Операции отмены
В любой момент вам может потребоваться что-либо отменить. Здесь мы рассмотрим несколько основных способов отмены сделанных изменений. Будьте осторожны, не все операции отмены в свою очередь можно отменить! Это одна из редких областей Git, где неверными действиями можно необратимо удалить результаты своей работы.
Отмена может потребоваться, если вы сделали коммит слишком рано, например, забыв добавить какие-то файлы или комментарий к коммиту. Если вы хотите переделать коммит — внесите необходимые изменения, добавьте их в индекс и сделайте коммит ещё раз, указав параметр —amend :
Эта команда использует область подготовки (индекс) для внесения правок в коммит. Если вы ничего не меняли с момента последнего коммита (например, команда запущена сразу после предыдущего коммита), то снимок состояния останется в точности таким же, а всё что вы сможете изменить — это ваше сообщение к коммиту.
Запустится тот же редактор, только он уже будет содержать сообщение предыдущего коммита. Вы можете редактировать сообщение как обычно, однако, оно заменит сообщение предыдущего коммита.
Например, если вы сделали коммит и поняли, что забыли проиндексировать изменения в файле, который хотели добавить в коммит, то можно сделать следующее:
В итоге получится единый коммит — второй коммит заменит результаты первого.
Очень важно понимать, что когда вы вносите правки в последний коммит, вы не столько исправляете его, сколько заменяете новым, который полностью его перезаписывает. В результате всё выглядит так, будто первоначальный коммит никогда не существовал, а так же он больше не появится в истории вашего репозитория.
Очевидно, смысл изменения коммитов в добавлении незначительных правок в последние коммиты и, при этом, в избежании засорения истории сообщениями вида «Ой, забыл добавить файл» или «Исправление грамматической ошибки».
Отмена индексации файла
Следующие два раздела демонстрируют как работать с индексом и изменениями в рабочем каталоге. Радует, что команда, которой вы определяете состояние этих областей, также подсказывает вам как отменять изменения в них. Например, вы изменили два файла и хотите добавить их в разные коммиты, но случайно выполнили команду git add * и добавили в индекс оба. Как исключить из индекса один из них? Команда git status напомнит вам:
Прямо под текстом «Changes to be committed» говорится: используйте git reset HEAD <file>… для исключения из индекса. Давайте последуем этому совету и отменим индексирование файла CONTRIBUTING.md :
Команда выглядит несколько странно, но — работает! Файл CONTRIBUTING.md изменен, но больше не добавлен в индекс.
Команда git reset может быть опасной если вызвать её с параметром —hard . В приведенном примере файл не был затронут, следовательно команда относительно безопасна.
На текущий момент этот магический вызов — всё, что вам нужно знать о команде git reset . Мы рассмотрим в деталях что именно делает reset и как с её помощью делать действительно интересные вещи в разделе Раскрытие тайн reset главы 7.
Отмена изменений в файле
Что делать, если вы поняли, что не хотите сохранять свои изменения файла CONTRIBUTING.md ? Как можно просто отменить изменения в нём — вернуть к тому состоянию, которое было в последнем коммите (или к начальному после клонирования, или еще как-то полученному)? Нам повезло, что git status подсказывает и это тоже.
В выводе команды из последнего примера список изменений выглядит примерно так:
Здесь явно сказано как отменить существующие изменения. Давайте так и сделаем:
Как видите, откат изменений выполнен.
Важно понимать, что git checkout — <file> — опасная команда. Все локальные изменения в файле пропадут — Git просто заменит его версией из последнего коммита. Ни в коем случае не используйте эту команду, если вы не уверены, что изменения в файле вам не нужны.
Если вы хотите сохранить изменения в файле, но прямо сейчас их нужно отменить, то есть способы получше, такие как ветвление и припрятывание — мы рассмотрим их в главе Ветвление в Git.
Помните, все что попало в коммит почти всегда Git может восстановить. Можно восстановить даже коммиты из веток, которые были удалены, или коммиты, перезаписанные параметром —amend (см. Восстановление данных). Но всё, что не было включено в коммит и потеряно — скорее всего, потеряно навсегда.
Отмена действий с помощью git restore
Git версии 2.23.0 представил новую команду: git restore . По сути, это альтернатива git reset, которую мы только что рассмотрели. Начиная с версии 2.23.0, Git будет использовать git restore вместо git reset для многих операций отмены.
Давайте проследим наши шаги и отменим действия с помощью git restore вместо git reset .
Отмена индексации файла с помощью git restore
В следующих двух разделах показано, как работать с индексом и изменениями рабочей копии с помощью git restore . Приятно то, что команда, которую вы используете для определения состояния этих двух областей, также напоминает вам, как отменить изменения в них. Например, предположим, что вы изменили два файла и хотите зафиксировать их как два отдельных изменения, но случайно набираете git add * и индексируете их оба. Как вы можете убрать из индекса один из двух? Команда git status напоминает вам:
Прямо под текстом «Changes to be committed», написано использовать git restore —staged <file> … для отмены индексации файла. Итак, давайте воспользуемся этим советом, чтобы убрать из индекса файл CONTRIBUTING.md :
Файл CONTRIBUTING.md изменен, но снова не индексирован.
Откат измененного файла с помощью git restore
Что, если вы поймете, что не хотите сохранять изменения в файле CONTRIBUTING.md ? Как легко его откатить — вернуть обратно к тому, как он выглядел при последнем коммите (или изначально клонирован, или каким-либо образом помещён в рабочий каталог)? К счастью, git status тоже говорит, как это сделать. В выводе последнего примера, неиндексированная область выглядит следующим образом:
Он довольно недвусмысленно говорит, как отменить сделанные вами изменения. Давайте сделаем то, что написано:
Важно понимать, что git restore <file> — опасная команда. Любые локальные изменения, внесенные в этот файл, исчезнут — Git просто заменит файл последней зафиксированной версией. Никогда не используйте эту команду, если точно не знаете, нужны ли вам эти несохраненные локальные изменения.
Отмена действий в Git
Мы всегда готовы подчеркивать бесчисленные возможности, которые предлагает Git, и эта статья не станет исключением. Git известен своей потрясающей способностью отменять практически любые действия! Наверняка на память вам уже приходят тысячи печальных случаев, когда вы делали объединение, а потом понимали, что в ваши планы оно не входило. Даже если вам кажется, что ошибочное объединение— это величайшая неудача всей вашей жизни, сделайте глубокий вдох и дочитайте статью до конца.
Не существует какого-то одного традиционного способа отмены действий в Git. Отмена производится с помощью некоторых других команд. Мы рассмотрим “первую пятерку” сценариев, которые помогут вам исправить ошибку и двинуться дальше.
Отмена Git Add
Один из самых распространенных вопросов в сообществе Git звучит так: “Как откатить git add перед коммитом?” Вы можете отменить действия над конкретным файлом или все внесенные изменения.
Решение, которое потребуется для этого, весьма простое. Чтобы откатить один файл, просто вызовите команду git reset :
Для отмены всех изменений запустите следующее:
Необходимость в откате становится неизбежной, если вы сделали коммит слишком рано и забыли добавить еще несколько файлов. В подобных случаях используется команда amend , чтобы внести изменения, зафиксировать их и сделать коммит снова.
Как откатить Git Merge
Объединение может привести к нежелаемым результатам. Но, как уже было сказано, вы можете с легкостью исправить свою ошибку! Давайте представим сценарий, в котором вы уже отправили изменения и осознали, что вам нужно отменить сделанное объединение.
Здесь на помощь приходит еще одна команда класса “отмена”: git revert . Начнем с того, что переключимся на мастер-ветку, используя команду git checkout :
Следующий шаг — запустить команду git log , чтобы получить ID сделанного объединения:
Затем вернитесь к упомянутому коммиту, выполнив следующее:
Используя -m 1 , вы даете Git указание: вернуться к первому родительскому элементу мастер-ветки, куда был совершен коммит объединения. Например, использование -m 2 сказало бы Git вернуться к первому родительскому элементу ветки, откуда пришел запрос на объединение.
Git также предлагает возможность предварительного просмотра, если вы хотите увидеть, что произойдет при объединении веток.
Как откатить Git Reset
Предлагаем суперкороткий способ отменить команду git reset:
Следом можно запустить команду git reflog , чтобы просмотреть журнал всех обновлений (т.е. переключение веток, сброс, коммит, объединение).
Отмена последних коммитов в Git
Существует несколько методов для отмены git commit . Давайте рассмотрим их по очереди.
Команду git reset можно использовать для отмены внесенных изменений:
x введите число. Например, если вы укажете
4 , то команда повлияет на четвертый снизу коммит. Если вы не укажете никакое конкретно число, git reset — soft HEAD применится к последнему коммиту.
Когда вы используете команду git reset — soft HEAD , то просто отменяете последний коммит, при этом внесенные изменения останутся в вашем рабочем дереве и в вашем индексе. Поэтому git commit создаст в будущем коммит с теми же самыми изменениями, которые вы “обнулили” перед этим.
Другой метод — это команда git revert HEAD
x ( git reset — hard commit hash ), которая отменяет изменения, указанные последним коммитом в HEAD , и создает новый с возвращенными изменениями:
Этот метод лучше всего работает в случае с общими публичными репозиториями.
Отмена Git Rebase
Допустим, вы выполнили команду git rebase в локальной ветке git и отправили ее в удаленную ветку. Следом вы поняли, что это не отвечает вашим ожиданиям, и захотели отменить сделанное.
Самый простой способ — найти главный коммит вашей ветки, запустив команду:
Следом необходимо установить туда текущую ветку, воспользовавшись git reset .
В данном случае старым коммитом был HEAD5 .
Заключение
Вот и все о том, как вы можете отменить наиболее часто используемые команды в Git. Хоть никакой традиционной команды отмены и нет, другие команды git могут помочь вам откатить то, что вы могли сделать по ошибке.