Как откатить коммиты на github.com
Ситуация когда у вас уже есть клон репозитория с которым вы работаете, делаете pull и смотрите что там какая то фигня накоммитчена от разработчиков.
Выбираем нужный бранч(ветку), у меня она master
git checkout master
делаем откат изменений в репозитории для примера на два коммита назад
git reset —hard HEAD~2
Можно сделать до какого то определенного коммита по хешу
git reset —hard HEAD hash
Хеш можно взять в вебинтерфейсе гитхаба.
Далее делаем принудительный коммит в основной репо на гитхабе
git push -f origin master
без -f будет ругаться что у вас версия младше чем в гитхабе и вам надо сделать pull
Отмена коммитов — Введение в Git
Git — система, в которой не нужно бояться совершать ошибки. Можно сказать, что ошибки — это единственный способ научиться им пользоваться. В Git практически всегда есть способ восстановить или изменить любые коммиты. На крайний случай спасет повторный git clone .
Что делать, если коммит уже сделан, но он нас по каким-то причинам не устраивает? Ситуаций может быть много, и все они возникают регулярно даже у профессиональных разработчиков:
- Забыли добавить в коммит нужные файлы
- Изменения нужно «откатить», чтобы доработать
- Изменения больше не актуальны, и их нужно удалить
- Изменения были сделаны по ошибке, и их нужно отменить
По большей части Git движется «только вперед». Правильный подход при работе с ним — это создавать новое, а не изменять старое.
Все ситуации, описанные выше, можно решить новым коммитом, изменяющим код в нужном направлении. Это не только удобно, но и безопасно. Изменение истории коммитов — опасная операция, которая чревата проблемами при синхронизации с удаленными репозиториями. Об этом мы поговорим позже.
Несмотря на сказанное выше, внутри Git существуют специальные команды, позволяющие упростить отмену, либо изменение коммита. С их помощью можно сделать историю коммитов понятной, а сам процесс отката — быстрым. Эти команды мы изучим в этом уроке.
Git revert
Самая простая ситуация — отмена изменений. Фактически она сводится к созданию еще одного коммита, который выполняет изменения, противоположные тому коммиту, который отменяется:
Руками создавать подобный коммит довольно сложно, поэтому в Git добавили команду, автоматизирующую откат. Эта команда называется git revert :
# Этой команде нужен идентификатор коммита # Это коммит, которым мы удалили файл PEOPLE.md git revert aa600a43cb164408e4ad87d216bc679d097f1a6c # После этой команды откроется редактор, ожидающий ввода описания коммита # Обычно сообщение revert не меняют, поэтому достаточно просто закрыть редактор [main 65a8ef7] Revert "remove PEOPLE.md" 1 file changed, 1 insertion(+) create mode 100644 PEOPLE.md # В проект вернулся файл PEOPLE.md git log -p commit 65a8ef7fd56c7356dcee35c2d05b4400f4467ca8 Author: tirion Date: Sat Sep 26 15:32:46 2020 -0400 Revert "remove PEOPLE.md" This reverts commit aa600a43cb164408e4ad87d216bc679d097f1a6c. diff --git a/PEOPLE.md b/PEOPLE.md new file mode 100644 index 0000000..4b34ba8 --- /dev/null +++ b/PEOPLE.md @@ -0,0 +1 @@ +Haskell Curry
Команда revert может отменять не только последний коммит, но и любой другой коммит из истории проекта. Согласитесь, это очень круто. Без системы контроля версий о таком нельзя было и мечтать.
Команда git reset
Представьте, что вам нужно удалить только что сделанный по ошибке коммит. Конечно, и в этом случае подходит git revert , но так история становится менее читаемой. Если этот коммит сделан был только сейчас и еще не отправлялся на GitHub, то лучше сделать так, как будто бы этого коммита не существовало в принципе.
Git позволяет удалять коммиты. Это опасная операция, которую нужно делать только в том случае, если речь идет про новые коммиты, которых нет ни у кого, кроме вас.
Если коммит был отправлен во внешний репозиторий, например, на GitHub, то менять историю ни в коем случае нельзя. Это сломает работу у тех, кто работает с вами над проектом.
Для удаления коммита используется команда git reset :
# Добавляем новый коммит, который мы сразу же удалим echo 'test' >> INFO.md git add INFO.md git commit -m 'update INFO.md' [main 17a77cb] update INFO.md 1 file changed, 1 insertion(+) # Важно, что мы не делаем git push git reset --hard HEAD~ HEAD is now at 65a8ef7 Revert "remove PEOPLE.md" # Если посмотреть `git log`, то последнего коммита там больше нет
У команды git reset есть множество различных флагов и способов работы. С ее помощью можно удалять коммиты, отменять их без удаления, восстанавливать файлы из истории и так далее. Работа с ней относится к продвинутому использованию Git, но здесь мы затрагиваем только самую базу.
Флаг —hard означает полное удаление. Без него git reset отменит коммит, но не удалит его, а поместит все изменения этого коммита в рабочую директорию, так что с ними можно будет продолжить работать.
Флаг HEAD~ означает «один коммит от последнего коммита». Если бы мы хотели удалить два последних коммита, то могли бы написать HEAD~2 :
HEAD (переводится как «голова») — так обозначается последний сделанный коммит. Подробнее эту терминологию мы разберем в уроке, посвященном внутреннему устройству Git.
Если не указывать флаг —hard , то по умолчанию подразумевается флаг —mixed . В таком варианте git reset отправляет изменения последнего коммита в рабочую директорию. Затем их можно исправить или отменить и выполнить новый коммит:
echo 'no code no pain' > README.md git add README.md git commit -m 'update README.md' [main f85e3a6] update README.md 1 file changed, 1 insertion(+) # Теперь откатываем последний коммит git reset HEAD~ Unstaged changes after reset: M README.md git status On branch main Your branch is up to date with 'origin/main'. Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: README.md
Последнего коммита больше не существует. При этом сделанные в нем изменения не пропали. Они находятся в рабочей директории для дальнейшей доработки.
Самостоятельная работа
- Выполните все шаги из урока
- Измените добавленный текст на No code No pain
- Закоммитьте изменения с сообщением update README.md
- Залейте изменения на GitHub
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
#3 — Отмена действий. Возвращение к старым версиям
Git позволяет просматривать хронологию изменений в вашем проекте. В ходе урока вы познакомитесь с отменой действий (коммитов) в Git, а также научитесь удалять коммиты и возвращать проект «назад во времени».
Видеоурок
В Git есть замечательная возможность «возвращения во времени»:
- вы можете просмотреть как выглядел ваш проект на стадии определенного коммита;
- вы можете отменить определенный коммит;
- вы можете выполнить удаление коммита и возвращение к проекту на стадии определенного коммита.
Просмотр проекта
Чтобы просмотреть проект на стадии какого-либо коммита вам необходимо прописать команду git checkout id , где id это идентификатор коммита, который хотите просмотреть.
Чтобы узнать id изначально пропишите команду git log —oneline . Тогда вы получите список всех коммитов что были сделаны в вашем проекте, а также их идентификаторы.
Чтобы просмотреть какой-либо коммит выполните комманду: git checkout 102e2f1 . Здесь вы просмотрите проект на стадии первого коммита.
Отмена коммита
Для отмены коммита используйте команду git revert id , где id это идентификатор коммита, который хотите просмотреть. После выполнения команды вы отмените определенный коммит.
Удаление коммита
Для удаления коммита используйте команду git reset id —hard , где id это идентификатор коммита, который хотите просмотреть. После выполнения команды вы удалите определенный коммит и все данные будут возвращены к проекту что был на стадии коммита.
Задание к уроку
Необходимо оформить подписку на проект, чтобы получить доступ ко всем домашним заданиям
Большое задание по курсу
Вам необходимо оформить подписку на сайте, чтобы иметь доступ ко всем большим заданиям. В задание входит методика решения, а также готовый проект с ответом к заданию.
PS: подобные задания доступны при подписке от 1 месяца
Как вернуться (откатиться) к более раннему коммиту?
A , B , C , D — коммиты в ветке master .
(HEAD) — местоположение указателя HEAD.
(i) — состояние индекса Git. Если совпадает c (HEAD) — пуст. Если нет — содержит изменения, подготовленные к следующему коммиту.
(wt) — состояние рабочей области проекта (working tree). Если совпадает с (i) — нет неиндексированных изменений, если не совпадает — есть изменения.
↑ обозначает коммит, на который указывает определенная ветка или указатель.
Вот решения, в зависимости от задачи:
1. Временно переключиться на другой коммит
Если вам нужно просто переключиться на другой коммит, чтобы, например, посмотреть на его содержимое, достаточно команды git checkout :
git checkout aaaaaa (wt) (i) A - B - C - D ↑ ↑ (HEAD) master
Сейчас репозиторий находится в состоянии «detached HEAD». Чтобы переключиться обратно, используйте имя ветки (например, master ):
git checkout master
2. Переключиться на коммит и продолжить работу с него
Если вы хотите продолжить работу с другого коммита, вам понадобится новая ветка. Можно переключиться и создать ее одной командой:
git checkout -b имя-новой-ветки aaaaaa (wt) (i) A - B - C - D ↑ ↑ new master (HEAD)
3. Удалить изменения в рабочей области и вернуть ее к состоянию как при последнем коммите.
(i) (wt) A - B - C - D - ? - ? ↑ master (HEAD)
3.1 Безопасно — с помощью кармана (stash)
3.1.1 Только неиндексированные
Можно удалить прикарманить только те изменения, которые еще не были индексированы (командой add ):
git stash save --keep-index
(wt) (i) A - B - C - D - ? ? ↑ ↑ master stash (HEAD)
3.1.2 Индексированные и нет
Эта команда отменяет все индексированные и неиндексированные изменения в рабочей области, сохраняя их в карман (stash).
git stash save
(wt) (i) A - B - C - D ? ↑ ↑ master stash (HEAD)
Восстановление несохраненных изменений: легко и просто.
git stash apply
Если stash совсем не нужен, его можно удалить.
# удалить последнюю запись кармана git stash drop
После этого восстановить изменения всё ещё можно, но сложнее: How to recover a dropped stash in Git?
3.2 Опасный способ
Осторожно! Эта команда безвозвратно удаляет несохраненные текущие изменения из рабочей области и из индекса Если они вам все-таки нужны, воспользуйтесь git stash .
Восстановление несохраненных изменений: неиндексированные потеряны полностью, но вы можете восстановить то, что было проиндексировано.
Здесь мы будем использовать git reset —hard
git reset --hard HEAD
(wt) (i) A - B - C - D - х - х ↑ master (HEAD)
4. Перейти к более раннему коммиту в текущей ветке и удалить из нее все последующие (неопубликованные)
Осторожно! Эта команда переписывает историю Git-репозитория. Если вы уже опубликовали ( git push ) свои изменения, то этот способ использовать нельзя (см. почему). Используйте вариант из пункта 5 ( git revert ).
4.1 При этом сохранить изменения в индекс репозитория:
git reset --soft bbbbbb
После этого индекс репозитория будет содержать все изменения от cccccc до dddddd . Теперь вы можете сделать новый коммит (или несколько) на основе этих изменений.
(wt) (i) A - B - C - D ↑ master (HEAD)
4.2 Сохранить изменения в рабочей области, но не в индексе.
git reset bbbbbb
Эта команда просто перемещает указатель ветки, но не отражает изменения в индексе (он будет пустым).
(i) (wt) A - B - C - D ↑ master (HEAD)
4.3 Просто выбросить изменения.
Осторожно! Эта команда безвозвратно удаляет несохраненные текущие изменения. Если удаляемые коммиты не принадлежат никакой другой ветке, то они тоже будут потеряны.
Восстановление коммитов: Используйте git reflog и этот вопрос чтобы найти и восстановить коммиты; иначе сборщик мусора удалит их безвозвратно через некоторое время.
Восстановление несохраненных изменений: неиндексированные потеряны полностью, но вы можете восстановить то, что было проиндексировано.
(i) (wt) A - B - C - D - ? - ? ↑ master (HEAD)
git reset --hard bbbbbb
(wt) (i) A - B - C - D - х - х ↑ master (HEAD)
5. Отменить уже опубликованные коммиты с помощью новых коммитов
Воспользуйтесь командой git revert . Она создает новые коммиты, по одному на каждый отменяемый коммит. Таким образом, если нужно отменить все коммиты после aaaaaa :
# можно перечислить отменяемые коммиты git revert bbbbbb cccccc dddddd # можно задать диапазон от более раннего к более позднему (новому) git revert bbbbbb..dddddd # либо в относительных ссылках git revert HEAD~2..HEAD # можно отменить коммит слияния, указывая явным образом номер предка (в нашем примере таких нет): git revert -m 1 abcdef # после этого подтвердите изменения: git commit -m'детальное описание, что и почему сделано'
Восстановление: Если revert-коммит оказался ошибочным, используйте этот ответ.