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

Содержание:

Как откатить Git Merge

Объединение может привести к нежелаемым результатам. Но, как уже было сказано, вы можете с легкостью исправить свою ошибку! Давайте представим сценарий, в котором вы уже отправили изменения и осознали, что вам нужно отменить сделанное объединение.

Здесь на помощь приходит еще одна команда класса “отмена”: . Начнем с того, что переключимся на мастер-ветку, используя команду :

Следующий шаг — запустить команду , чтобы получить ID сделанного объединения:

Затем вернитесь к упомянутому коммиту, выполнив следующее:

Используя  , вы даете Git указание: вернуться к первому родительскому элементу мастер-ветки, куда был совершен коммит объединения. Например, использование сказало бы Git вернуться к первому родительскому элементу ветки, откуда пришел запрос на объединение.

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

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

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

1 $ git status

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

1 $ git checkout — second.php

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

git revert

В предыдущих примерах было выполнено несколько важных операций отмены с перемещением во времени с помощью команд и . Git содержит еще одну утилиту отмены, которая часто считается более безопасной, чем команда reset. Команда revert создает новые коммиты, которые содержат обратные изменения для указанных коммитов. Такие обратные коммиты можно безопасно отправлять в удаленные репозитории, чтобы делиться ими с другими разработчиками.

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

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

Это запустит рабочий процесс . Git создаст новый коммит, содержимое которого будет сброшено до состояния коммита, указанного в команде revert. Затем Git откроет настроенный текстовый редактор, чтобы запросить комментарий к новому коммиту. Команда revert считается более безопасным способом выполнения отмены изменений, поскольку она соответствует рабочему процессу на основе коммитов. При создании обратных коммитов с помощью команды revert история коммитов наглядно показывает, когда выполнялась операция отмены.

Поиск утерянного: просмотр старых коммитов

В основе любой системы управления версиями лежит идея хранения «безопасных» копий проекта, чтобы у разработчиков не возникало опасений безвозвратно испортить базу кода. Когда в проекте сохранена история коммитов, можно повторно оценивать и анализировать любые ранее выполненные коммиты. Один из лучших инструментов для просмотра истории репозитория Git — это команда . В примере ниже мы используем команду , чтобы получить список последних коммитов для популярной графической библиотеки с открытым исходным кодом.

Каждый коммит имеет уникальный идентифицирующий хеш SHA-1. Эти идентификаторы используются для перемещения по временной шкале коммитов и возвращения к коммитам. По умолчанию показывает только коммиты текущей выбранной ветки. Но не исключено, что искомый коммит находится в другой ветке. Для просмотра всех коммитов во всех ветках используется команда . Команда  используется для просмотра и посещения других веток. Так, команда возвращает список имен всех известных веток. Просмотреть весь журнал коммитов одной из этих веток можно с помощью команды .

После того как вы нашли ссылку на нужный коммит в истории, для перехода к нему можно использовать команду . Команда  — это простой способ «загрузить» любой из этих сохраненных снимков на машину разработчика. При нормальном процессе разработки указатель обычно указывает на главную ветку или другую локальную ветку. Но при загрузке предыдущего коммита указатель указывает уже не на ветку, а непосредственно на сам коммит. Такая ситуация называется состоянием «открепленного указателя », и ее можно представить следующим рисунком:

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

Отмена в Git — Сброс, Извлечение и Откат

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

Исправление незакоммиченных ошибок

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

Это отбросит все сделанные изменения которые вы возможно добавили в индекс git, а также все другие изменения в вашей рабочем дереве. Другими словами, результат этого — вывод команд «git diff» и «git diff —cached» будет пустым.

Если вы просто хотите восстановить только один единственный файл, предположим hello.rb, то выполните git checkout вместо

Первая команда восстановит hello.rb до версии хранящейся в индексе, и команда «git diff hello.rb» не покажет отличий. Вторая команда восстановит hello.rb до версии в ревизии HEAD, таким образом обе команды «git diff hello.rb» и «git diff —cached hello.rb» не покажут отличий.

Исправление закоммиченных ошибок

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

  1. Вы создаете новый коммит в котором нет тех нежелательных частей
    присутствующих в старом коммите. Это правильный способ если ваша ошибка уже была опубликована.

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

Исправление ошибки новым коммитом

Создание нового коммита который восстанавливает предыдущее состояние очень просто; нужно только передать команду git revert ссылку на ошибочный коммит; например чтобы восстановить наиболее свежий коммит:

Это создаст новый коммит который отменяет изменения в HEAD. Вам предоставится шанс отредактировать сообщение-описание нового коммита.

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

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

Исправление ошибок изменяя коммит

Если вы только что выполнили коммит но осознали что вам нужно в нем что то исправить, последнии версии git commit поддерживают флаг —amend который указывает git заменит коммит HEAD новым коммитом, основываясь на текущем содержании индекса. Это дает вам удобный случай добавить файлы которые вы забыли добавить или исправить опечатки в сообщении-описании коммита, до того как вы выполните push и сделаете свои изменения доступными всему миру.

Если вы нашли ошибку в давнем коммите, но который еще не опубликовали, используйте git rebase в интерактивном режиме, с «git rebase -i» отмечающий изменения которые требуют коррекции с edit. Это позволит вам изменить коммит во время процесса rebase.

Отмена команды git reset

До сих пор мы передавали в SHA-хеши . Теперь вывод команды не показывает сброшенные коммиты. Как их вернуть? Git никогда не удаляет коммиты окончательно, хотя все указатели на них открепляются. Кроме того, хранит отдельный журнал со всеми перемещениями ссылок — reflog, или журнал ссылок. Проверить журнал ссылок можно с помощью команды .

Вывод команды похож на то, что показано в примере выше. Вы можете просмотреть историю действий в репозитории. Самая верхняя строчка является ссылкой на команду reset, которую мы выполнили для сброса запроса pull № 6. Теперь давайте сбросим выполнение команды reset, чтобы восстановить запрос pull № 6. Во втором столбце вывода команды reflog находится указатель на действие по изменению репозитория. Здесь  — это ссылка на выполненную нами ранее команду reset. Мы не хотим отвечать на эту команду сброса, поэтому восстановим репозиторий до

Теперь давайте рассмотрим историю коммитов репозитория с помощью команды :

Здесь видно, что история коммитов репозитория была восстановлена до предыдущей версии, с которой мы экспериментировали. Коммит восстановлен, хотя был утерян при первой операции сброса. Команда является мощным инструментом для отмены изменений в репозитории. Подробнее о ее использовании см. на странице .

git status

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

Согласно выводу команды , все данные соответствуют данным в удаленной главной ветке master, а отложенных изменений и изменений, готовых к коммиту, нет. В следующем примере мы внесем небольшие изменения в репозиторий и рассмотрим его в состоянии отложенных изменений. То есть мы рассмотрим репозиторий, находящийся в локальной системе, в котором файлы изменены, но не подготовлены (или не проиндексированы) для добавления в историю проекта.

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

Согласно выводу, в репозитории есть отложенные изменения для файла . Хорошие новости! Если отменяемое изменение не было добавлено в раздел проиндексированных файлов (как в примере выше), вы можете просто отредактировать файл и продолжить работу. Git начинает отслеживать изменения только после того, как они добавлены в раздел проиндексированных файлов и выполнен коммит в историю проекта.

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

Команды Git

Логирование

Просмотреть вашу «undo»-историю

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

Команда это ваша страховочная сетка после запуска «страшных» команд, таких как . С ее помощью вы увидите не только сделанные вами коммиты, но и все действия, которые привели вас к той точке, на которой вы находитесь. Узнать больше об этой команде можно из статьи Atlassian.

Посмотреть текущее состояние и сведения о возможных конфликтах слияния

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

Навигация

Photo by Joseph Barrientos on Unsplash

Я закопался по уши, давайте-ка начнем сначала

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

Я хочу вернуться на n коммитов назад

Между , и reset есть важные отличия. Если брать в целом,

  1. : убирает изменения из коммита, но сохраняет их в стейджинге.
  2. (по умолчанию): изменения убираются из коммита и стейджинга, но остаются в рабочей директории.
  3. : изменения убираются из коммита, из стейджинга и из рабочей директории.

Хочу переписать несколько коммитов локально

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

Я думаю, что rebase это одна из самых запутанных тем при изучении Git. Дальше мы еще к ней вернемся.

Этот rebase ни к чему хорошему не приведет, давайте его прервем

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

Я хочу отменить коммит без переписывания истории

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

Уборка

Photo by Oliver Hale on Unsplash

О боже, почему у меня так много веток?

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

Эта команда слишком длинна для запоминания, но вы можете назначить для нее псевдоним (alias):

Если вы используете Oh My Zosh, все это уже сделано за вас. Подробнее — в разделе про псевдонимы.

Отправляем в мусор старые ветки и лишние коммиты

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

Псевдонимы

Команды Git могут быть очень длинными и трудными для запоминания. Поскольку никто не захочет каждый раз набирать их заново и тратить целые дни на их заучивание, я настоятельно рекомендую создать для них псевдонимы.

Можно сделать еще лучше: установить инструмент вроде Oh My Zosh для Z shell (Zsh), и вы получите набор уже готовых псевдонимов для распространенных команд Git. Я вот слишком ленив, чтобы настраивать свою оболочку в точности по своему вкусу, так что предпочитаю пользоваться инструментами, которые делают это за меня. Кстати, Oh My Zosh и выглядит красиво. Вот несколько моих любимых псевдонимов команд, которыми я пользуюсь ежедневно:

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

Или поискать по конкретному псевдониму:

Отправка результатов отмены в Bitbucket

Команда  — один из способов отмены, которые предлагает . В целом сброс с помощью команды reset считается небезопасным. Он хорошо подходит для локального применения к изолированному коду, но становится опасным при работе над общим кодом с другими участниками команды.

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

Ниже приведен пример небезопасного сценария.

  • Разработчик A работает в ветке над новой возможностью.
  • Разработчик B работает в той же ветке над другой возможностью.
  • Разработчик B решает сбросить ветку к более раннему состоянию, когда разработчики A и B еще не приступили к работе.
  • Разработчик B принудительно отправляет сброшенную ветку в удаленный репозиторий.
  • Разработчик A делает запрос pull для этой ветки, чтобы получить обновления. Во время выполнения запроса pull разработчик A получает принудительное обновление, которое сбрасывает его локальную ветку к тому моменту времени, когда он еще не начал работать над новой возможностью. Соответственно, он теряет все коммиты.

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

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

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

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

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

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

1 $ git reset HEAD second.php

На иллюстрации выше к файлу применена команда , а после этого команда в результате вывода информации которой видно, что файл second.php теперь просто является модифицированным

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

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

1 $ git checkout — second.php

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

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

Просмотр старых версий

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

Допустим, история вашего проекта выглядит примерно так:

Для просмотра коммита «Make some important changes to hello.txt» можно использовать команду в следующем виде:

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

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

Заключение

  • Преимущество — они позволяют даже начинающему пользователю GIT осуществлять работу с системой контроля версий (проверено на моём начальнике за 2 недели моего отпуска)
  • Недостаток — опытный пользователь видит некоторые более гибкие и интересные сценарии, которые сложно формализовать под набор простых правил применения. Именно поэтому я рекомендую после их успешного освоения и внедрения прочитать книгу Pro Git.

Несколько коммитов названы не по моим правилам правилам — это результат быстрой настройки Разработчиком функционала на Test/Prelive сервере при накате задачи. Я в таких случаях писал TIKET_###### Patch_## (номер Тикет и порядковый номер патча), чтобы проще опознавать к какой задаче в трекере относится та или иная правка.Часть задач реализуется непосредственно мною, а не Разработчиком. В этом случае я называю из Task, а не Tiket и указываю ID связанной задачи в другой учётной системе.

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

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