Как сделать откат в github desktop
Для отмены слияния веток в git (git merge) есть два решения:
- удаление коммита слияния (unmerge, merge undo, merge delete)
- отмена изменений слияния (revert)
Первый случай поможет, если вы еще не сделали новых коммитов, после слияния веток, и не отправили изменения в ваш центральный репозиторий (например в GitHub или Bitbucket). Для удаления коммита слияния нужно перейти на ветку, в которую вы влили другую ветку. Например так:
и выполнить операцию отката ветки:
Для отмены изменений слияния можно выполнить либо
где _some_hash_ - это хэш коммита, который вы хотите отменить (это отменяет изменения конкретного коммита). Либо
где _some_hash_ - это хэш коммита слияния (коммит созданный командой git merge), который вы хотите отменить. Этот вариант отменяет все изменения, сделанные командой git merge, и восстанавливает состояние ветки (в которую происходило вливание) до мерджа
Гит — система, в которой не нужно бояться совершать ошибки. Можно сказать, что это единственный способ научиться им пользоваться. В git практически всегда есть способ восстановить или изменить любые коммиты. На крайний случай спасет повторный git clone .
Что делать, если коммит уже сделан, но он нас по каким-то причинам не устраивает? Ситуаций может быть много, и все они возникают регулярно даже у профессиональных разработчиков:
Git revert
Самая простая ситуация — отмена изменений. Фактически она сводится к созданию ещё одного коммита, который выполняет изменения противоположные тому коммиту, который отменяется. Руками создавать подобный коммит довольно сложно, поэтому в git добавили команду, автоматизирующую откат. Эта команда называется git revert :
Команда revert может "отменять" не только последний коммит, но и любой другой коммит из истории проекта. Согласитесь, это очень круто. Без системы контроля версий о таком нельзя было и мечтать.
Git reset
Иногда удалить нужно только что сделанный по ошибке коммит. Конечно, и в этом случае подходит git revert , но так загрязняется история. Если этот коммит сделан был только сейчас и ещё не отправлялся на Github, то лучше сделать так, как будто бы этого коммита не существовало в принципе.
Git позволяет удалять коммиты. Это опасная операция, которую нужно делать только в том случае, если речь идет про новые коммиты, которых нет ни у кого, кроме вас.
Если коммит был отправлен во внешний репозиторий, например, на Github, то менять историю ни в коем случае нельзя, это сломает работу у тех, кто работает с вами над проектом.
Для удаления коммита используется команда git reset . Делается это так:
git reset — мощная команда, имеющая множество различных флагов и способов работы. С её помощью удаляются или отменяются (без удаления) коммиты, восстанавливаются файлы из истории и так далее. Работа с ней относится к продвинутому использованию git, здесь же мы затрагиваем только самую базу.
Флаг --hard означает полное удаление. Без него git reset отменит коммит, но не удалит его, а поместит все изменения этого коммита в рабочую директорию, так что с ними можно будет продолжить работать. HEAD~ означает "один коммит от последнего коммита". Если бы мы хотели удалить два последних коммита, то могли бы написать HEAD~2 .
HEAD (голова) — так обозначается последний сделанный коммит. Подробнее эту терминологию мы разберем в уроке, посвященном внутреннему устройству git.
Последнего коммита больше не существует, но изменения, сделанные в нём, не пропали. Они находятся в рабочей директории для дальнейшей доработки.
Система контроля версий 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.
Целью этой статьи является обзор популярных сценариев проблем и методов их решения. Мы узнаем о том, как можно решить проблемы связанные с человеческими ошибками при создании коммитов в Git, какой способ устранения ошибок лучше применять в конкретных ситуациях.
Возникающие проблемы
В ходе разработки каких-либо проектов в Git, мы можем столкнуться с различными ситуациями, такими как:
Безопасные изменения для локального репозитория
Изменить последний коммит
Давайте предположим, что мы работаем над каким-либо проектом локально.
Но что делать, если мы забыли добавить или изменить какие-то файлы в наш последний коммит?
Для этого импортируем нужные файлы в наш проект или изменяем уже существующие и добавляем их в индекс.
Для теста я добавлю файл forgotten file.txt в проект. После этого еще раз выполним команду:
В случае необходимости удаления ненужного файла из последнего коммита, мы можем удалить его из проекта, добавить изменения в индекс и воспользоваться все той же командой:
Удалить коммит
Для того, чтобы удалить один или несколько коммитов, мы можем воспользоваться командой git reset. Существует два типа выполнения reset:
- Soft — удаляет коммит из истории и переводит файлы из него в состояние рабочего каталога.
- Hard — удаляет коммит из истории вместе с файлами.
Сначала разберем soft reset. Возвращаемся к нашему проекту.
В один момент мы осознали, что допустили ошибку и хотели бы переделать последний коммит.
Для этого выполним команду:
Проверим историю коммитов. Мы можем убедится, что последний коммит был удален.
Файлы, которые были созданы или изменены в удаленном коммите, перешли в состояние рабочего каталога. Мы можем продолжить работу и, например, создать новый коммит на основе этих файлов.
Подобные действия мы можем выполнять для нескольких коммитов сразу. Для примера введем команду:
3 последних коммита пропали из истории.
Проверим состояние файлов, которых коснулась процедура удаления коммитов.
Мы можем полностью удалить коммиты без сохранения связанных с ними файлов. Для этого выполним процедуру hard reset:
И проверим состояние.
Массовое изменение коммитов
Для этой задачи хорошо подходит выполнение команды git rebase. Ее запуск в интерактивном режиме позволит нам последовательно сообщить Git’у как бы мы хотели выполнить оптимизацию.
Мы считаем, что 4 последних коммита можно смело объединить в один.
Для этого выполним команду:
Перед нами откроется текстовый редактор по умолчанию в котором мы будем выполнять изменения. Используем коммит с хэшем aab958a как начальный, путем указания команды pick напротив него и укажем напротив трех остальных команду squash. Как мы можем видеть ниже в описании, команда suqash объединит коммит с предыдущим в списке.
После выполнения — выходим из текстового редактора.
Снова выходим из текстового редактора.
Похоже, что наше объединение нескольких коммитов прошло успешно. Давайте проверим это командой:
Снова вводим команду:
В этот раз в качестве начального коммита будет использоваться с коммит хэшем 4c17043. Для его переименования укажем напротив команду reword. Затем объединяем с ним два последующих коммита командой squash. Последний коммит мы никак не изменяем.
После переименования выходим из текстового редактора и проверяем историю.
Похоже, что нам удалось провести историю коммитов в порядок и теперь нет причин откладывать загрузку нашего проекта на удаленный репозиторий. 🙂
Безопасные изменения для удаленных репозиториев
До этого мы рассматривали случаи локальной разработки. По большому счету, пока мы не публикуем изменения, наши действия — не могут повлиять на деятельность наших коллег по проекту. Применение вышеописанных способов до публикации изменений на удаленном репозитории — вполне оправдано.
Однако, что делать, если мы совместно работаем над проектом и только спустя какое-то время понимаем, что один из коммитов — лишний? Если мы воспользуемся вышеописанными методами, это может спровоцировать ряд проблем в работе над проектом у наших коллег.
В подобных случаях имеет смысл откатывать коммит. Подобная процедура создает еще один коммит, который отменит изменения ненужного. Таким образом мы не порушим историю проекта и избавим наших коллег от лишних проблем.
Снова вовзращаемся к исходному состоянию проекта.
Предположим, что изменения в коммите с хэшем и 5140d80 — лишние. Выполним команду:
Git сообщит нам об изменениях, после отката.
К сожалению, в реальности могут возникнуть проблемы при откате коммитов, требующие дополнительных мер для их решения. В этой статье мы рассмотрели достаточно простые ситуации, чтобы наглядно увидеть что и как делает каждая команда.
Итоги
В этой статье мы узнали о четырех способах изменять коммиты:
- git commit —amend — позволяет изменять последний коммит.
- git reset — позволяет удалять коммиты.
- git rebase — позволяет производить массовое изменение коммитов, приводить в порядок историю.
- git revert — позволяет откатывать изменения коммитов.
Первые три команды — подойдут для использования в условиях локальной разработки.
Последняя команда — лучший способ, не создавать лишних проблем коллегам при совместной разработке.
Читайте также: