Как сделать откат в git

Добавил пользователь Алексей Ф.
Обновлено: 04.10.2024

В Git мы можем корректно вернуть все изменения к определенному коммиту без использования потенциально опасной команды git reset .

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

Дельный Совет: Откат файла к предыдущему коммиту! Читать далее →

Git — Откат Изменений к Определенному Коммиту

Найдите конкретный коммит, к которому вы хотите вернуть все изменения:

Откатите все изменения к старому коммиту:

Обратите Внимание: Точка ( . ) после имени ветки является обязательной.

Добавьте изменения в staging и сделайте коммит:

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

Дельный Совет: Очистка истории коммитов в Git! Читать далее →

Если я чему-то научился за 15 с лишним лет программирования, так это то, что ошибки встречаются часто, и я их много делаю. Это в равной степени относится и к инструментам контроля версий. Независимо от того, случайно ли вы зафиксировали изменения или просто поняли, что ваш предыдущий зафиксированный код — это не то, что вам нужно, часто вам потребуется отменить предыдущий коммит в Git.

В этой статье я покажу несколько способов отменить ваши коммиты, в зависимости от вашего варианта использования. Это сложная тема (которая относится ко многим темам Git в целом), поэтому убедитесь, что вы следуете инструкциям, которые лучше всего соответствуют вашим потребностям.

Удалить неопубликованные коммиты

Если вы еще не опубликовали свои коммиты в удаленном репозитории, таком как GitHub, вы можете по существу удалить предыдущие коммиты с помощью команды reset.

Команда reset имеет три различных параметра, два из которых мы опишем здесь:

Используя опцию —hard, все возвращается обратно к указанному коммиту. Это включает в себя ссылки на историю коммитов, промежуточный индекс и ваш рабочий каталог.

Это означает, что с помощью этой команды вы не только вернетесь к предыдущей фиксации, но и потеряете все рабочие изменения в процессе. Чтобы не потерять какие-либо рабочие изменения, вы можете использовать команды stash и stash pop:

Команда stash сохраняет ваши рабочие изменения (без каких-либо комитов или изменений в дереве), а затем stash pop возвращает их обратно.

Другим вариантом, который вы можете рассмотреть, является параметр —soft. Эта опция работает так же, как git reset —hard , но влияет только на историю коммитов, а не на ваш рабочий каталог или промежуточный индекс.

Удаление опубликованных коммитов

Допустим, вы зафиксировали свой код, а затем отправили его в удаленный репозиторий. На этом этапе настоятельно рекомендуется не использовать что-то вроде git reset, поскольку вы переписываете историю.

Вместо этого рекомендуется использовать команду revert. Эта команда работает, отменяя изменения, которые были внесены в указанный коммит, создавая новый коммит и фактически не удаляя предыдущие коммиты. Это идеально для опубликованных изменений, потому что тогда реальная история репозитория сохраняется. Вот пример:

Допустим, в вашем репозитории есть текстовый файл со следующим содержанием

И вы изменяете его на:

Ваша история коммитов может выглядеть примерно так:

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

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

Или, если вы хотите отменить много непостоянных коммитов, вы указываете их индивидуально:

Временно оформить предыдущий коммит

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

Если в рабочей директории были внесены нежелательные изменения восстановить состояние можно выполнив

Это полезно если требуется в git откатить изменения в файле и или в нескольких файлах, которые еще не были добавлены в индекс и замоммичены.

Команда подтянет изменения из последнего сделанного коммита — содержимого HEAD. Локальные файлы будут замещены.

При этом те, изменения, которые уже были добавлены в индекс с git add в нем останутся.

Если коммиты не нужны — самый простой способ привести состояние локальной системы в соответствие состоянию удаленной:

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

Самая частая практика при откате изменений git

Можно не трогать индекс и локальные файлы просто удаляя коммиты.

reflog выведет все список всех действий

reset возвращает состояние по индексу, взятому из списка

Таким же образом можно отменить последний коммит

После знака тильды можно указать любое другое число;

1 означает, что отменяется последний коммит,

3, что последние три и т.д. Список всех коммитов и комментариев можно увидеть выполнив git log

Другой способ сделать то же

Ключ —soft означает, что данные удалены не будут, только коммит, если заменить его на —hard удалятся и данные

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

Конфликты при внесении изменений в git репозитории неизбежны — если какое-то действие не возможно система не даст его выполнить и будет выводить предупреждения. Они обычно весьма информативны и конфиликты в версиях разрешаются редактированием файлов вручную.

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

Откат в предыдущее состояние можно осуществить двумя способами:

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

2. Сбрасывает всю историю вместе с состоянием рабочей директории до указанного коммита.

Практический пример

Перейдём в существующий репозиторий и выведем всю историю коммитов в текущей ветке при помощи команды git log.

Есть два коммита: первый (Create README.md) и второй (Edit README.md)

В нашем случае мы произведем откат к коммиту (Create README.md).

Вывод на экран всех коммитов в текущей ветке

Первый способ отката позволяет сбросить историю до указанного коммита, но оставляет внесённые изменения в файлах.

Откат коммита в существующем Git-репозитории

Второй способ отката выполняет сброс всей истории и возвращает файлы к исходному состоянию.

Откат коммита в существующем Git-репозитории

Метки: Git.

Комментарии к записи

Добрый день. Может ли git откатить все изменения в некотором определённом каталоге?
Т.е. вернуть в исходное состояние всё файлы некоторого определённого каталога?

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

Система контроля версий git позволяет очень быстро вернуть состояние файла или состояние всего проекта к моменту в котором они были зафиксированы в последнем коммите. Операция эта очень проста, быстра и удобна.

Как сбросить файл к исходному состоянию в коммите?

Для примера рассмотрим локальный репозиторий, который находится под версионным контролем git. В нашем тестовом проекте имеются изменения в содержимом файла second.php, при этом эти изменения еще не подготовлены к добавлению в следующий коммит, а значит файл находится в состоянии not staged. В этом можно убедиться, воспользовавшись командой:

[cce lang=’bash’]
$ git status
[/cce]


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

[cce lang=’bash’]
$ git checkout — second.php
[/cce]


Как сбросить файл к состоянию в коммите, если изменения уже подготовлены командой git add?

В случае, если в файл были внесены изменения и эти изменения уже подготовлены для фиксации в коммит с помощью команды git add, то в этом случае для сброса файла в исходное состояние нужно:

  • Убрать файл из подготовленного состояния к фиксации в коммите, т.е. перевести файл из состояния staged.
  • Сбросить файл к исходному состоянию.

Для примера рассмотрим ситуацию, когда в нашем локальном репозитории есть файл second.php , в который были внесены изменения и более того эти изменения были подготовлены к фиксации в коммит при помощи команды [cci]$ git add *.php[/cci] .


В репозитории есть модифицированный файл со статусом staged, подготовленный для фиксации изменений в следующий коммит.

Для того, чтобы такой модифицированный файл сбросить к первоначальному состоянию, вначале следует перевести его в состояние not staged. Делается это при помощи команды:

[cce lang=’bash’]
$ git reset HEAD second.php
[/cce]


На иллюстрации выше к файлу применена команда [cci]$ git reset HEAD [имя файла][/cci], а после этого команда [cci]$ git satus[/cci] в результате вывода информации которой видно, что файл second.php теперь просто является модифицированным. Кстати, обратите внимание, что система контроля версий git сама в выводе команды status подсказывает, что файл можно сбросить к исходному состоянию командой [cci]$ git checkout — [имя файла][/cci] или подготовить изменения к фиксации в коммит при помощи [cci]$ git add [имя файла][/cci] .

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

[cce lang=’bash’]
$ git checkout — second.php
[/cce]


Файл сброшен к исходному состоянию при помощи команды git checkout

Вывод: Для сброса команды к состоянию сохраненному в последнем коммите применяется команда [cci]$ git checkout — [имя файла][/cci]. Если изменения в файле уже подготовлены для фиксации в следующем коммите, то перед сбросом следует воспользоваться также командой [cci]git reset HEAD [имя файла][/cci].

Как я могу откатить свой первый (самый старый), но оставить второй?

Мне просто нужно сделать:

Этот вопрос кажется не по теме, потому что речь идет об инструменте программирования. Это относится к переполнению стека.

Самый безопасный и, вероятно, самый чистый путь - это интерактивная перебазировка.

Оттуда вы можете сдавить коммиты, которые помещают один или несколько коммитов в предыдущий коммит. Чтобы полностью удалить коммит из истории, удалите строку из списка.

Если два коммита, с которыми вы здесь работаете, влияют на один и тот же файл (-ы), вы можете увидеть конфликт слияния.

Сброс хранилища с помощью git reset --hard должен быть сделан с осторожностью, так как это не может быть отменено.

Переписывать историю следует с осторожностью.

Как я могу удалить коммит во время 'git rebase'? Есть только 3 команды: выбрать, редактировать, сквош. Там нет удалить AFAIK.

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

Я бы предложил использовать rebase как можно меньше. Если вы работаете с другими, то просто зарабатывайте revert .

Нет. git-reset --hard вернет вас в историю. То, что вы ищете, это git revert, который отменит любой коммит.

Ну, это работает, но это также загрязняет журнал коммитов. Если эти коммиты не были уже сдвинуты / вытянуты, лучше очистить их с помощью интерактивной перебазировки. Возможность изменять историю - одно из главных преимуществ git перед другими системами контроля версий.

Я только что сделал это:

Я облажался, так что я сделал

Затем сделал это снова. Тогда я должен был толкать так:

И это уничтожило коммиты, более новые, чем коммит, на который я откатился. Работал отлично.

Читайте также: