TL;DR: щоб скасувати останній коміт, зберігши зміни, виконайте git reset --soft HEAD~1 (зміни залишаться застейдженими) або git reset HEAD~1 (зміни залишаться у робочому дереві). Якщо коміт уже запушено — виконуйте натомість git revert HEAD: він створює новий коміт, який скасовує старий без переписування історії. Ці три команди покривають майже кожен момент «я закомітив занадто рано». Решта гайду розбирає кожен випадок із командами для копіювання, пояснює різницю між --soft, --mixed і --hard і показує, як відновитися, якщо щось пішло не так. Кожна команда нижче працює на будь-якій свіжій інсталяції Git на Linux, macOS чи Windows.
Як скасувати останній коміт, зберігши зміни?
Найпоширеніша ситуація: ви закомітили, а тоді помітили одруківку, забутий файл або зрозуміли, що зміна належить до іншого коміта. Нічого не запушено. Скасовуйте коміт і повертайте все на місце:
# Коміт зникає з історії — зміни повертаються в область стейджингу
git reset --soft HEAD~1
# Зміни повертаються в робоче дерево (нестейджені)
git reset HEAD~1 HEAD~1 означає «один коміт до того місця, куди зараз вказує HEAD». Після будь-якої з команд файли на диску недоторкані — зсунувся лише вказівник гілки. Перевірте через git status: з --soft зміни застейджені, готові до повторного коміта з виправленнями; без прапорця вони нестейджені — можна спокійно редагувати спершу.
Безпечніша звичка, коли ви просто хочете додати файли до останнього коміта, — взагалі не скасовувати його:
git add forgotten-file.txt
git commit --amend --no-edit --amend замінює останній коміт на місці (тут — без зміни повідомлення). Зауважте: amend запушеного коміта переписує історію — про це нижче.
У чому різниця між —soft, —mixed і —hard?
Це варто запам’ятати, бо прапорець вирішує, де опиняться ваші зміни — і чи можуть вони загинути:
| Прапорець | Коміт скасовано? | Зміни на диску | Застейджені? | Типове застосування |
|---|---|---|---|---|
--soft | Так | Збережені | Так | Повторний коміт з дрібними виправленнями |
--mixed (типовий) | Так | Збережені | Ні | Перегрупувати зміни, застейджити вибірково |
--hard | Так | Видалені | — | Викинути роботу повністю |
git revert | Ні (новий коміт) | Збережені | — | Скасувати вже запушений коміт |
--hard — єдиний небезпечний: він викидає і коміт, і зміни. Перед будь-яким reset --hard заховайте роботу у stash або гілку:
git branch backup-before-reset # дешеве страхування
git reset --hard HEAD~1 # коміт і зміни зникли Якщо небезпечна версія вже виконана — не все втрачено: git reflog пам’ятає, де був HEAD:
git reflog # знайдіть хеш втраченого коміта
git reset --hard HEAD@{1} # або: git reset --hard <hash> Reflog тримає повислі коміти близько 90 днів за замовчуванням, тож «я випадково зробив hard-reset» майже завжди можна відновити, якщо встигнути до збирання смiття.
А якщо коміт уже запушено?
Якщо коміт на спільній гілці (будь-що, окрім вашої власної feature-гілки), не переписуйте історію. Використовуйте git revert: він обчислює протилежну зміну і комітить її:
git revert HEAD
git push Кожен, хто зробить pull, просто отримає новий коміт, що прибирає зміни старого. Жодного force-push, жодних зламаних колег. Якщо треба скасувати серію комітів, робіть revert діапазону: git revert --no-commit HEAD~3..HEAD && git commit.
Альтернатива — git reset --hard HEAD~1 && git push --force-with-lease — припустима лише на гілці, на якій ніхто інший не будує, а --force-with-lease (ніколи не гола --force) — єдина безпечна форма, бо відмовляє пуш, якщо хтось ушпорив у проміжку. Force-push спільних гілок — це спосіб, яким команди втрачають коміти, а лог CI загадково перестає збігатися з чиїмось чекаутом.
Як скасувати останній коміт, але залишити його про запас?
Іноді коміт — хороша робота за неправильною адресою: не та гілка або занадто рано. Замість скасування — перенесіть його:
git branch stash-commit # припаркуйте коміт на новій гілці
git reset --hard HEAD~1 # тоді приберіть його з поточної Або заберіть лише цей коміт на іншу гілку, не чіпаючи поточну:
git cherry-pick <hash> # перебуваючи на цільовій гілці Між reset --soft, cherry-pick і revert не існує коміта, який неможливо перемістити чи анулювати — трюк у тому, щоб вибрати «перемістити» чи «скасувати» ще до того, як тягнутися за прапорцем.
Яке скасування обрати? Швидкий путівник
- Не запушено, хочу виправити й перезакомітити →
git reset --soft HEAD~1 - Не запушено, хочу застейджити вибірково →
git reset HEAD~1(mixed) - Хочу, щоб зміни зникли повністю →
git reset --hard HEAD~1(reflog знає, якщо пошкодуєте) - Вже запушено на спільну гілку →
git revert HEAD - Коміт належить іншій гілці →
cherry-pick, не скасовуйте
Остання операційна порада: якщо поганий коміт таки дістався сервера — зіпсований deploy-хук, мандрівник CI, що здурів після force-push, — наступне місце пошуку це логи машини, а не Git. На будь-якій машині з systemd journalctl -u <service> -n 100 показує точно, що виконувалося і коли; у нашій шпаргалці journalctl є патерни для копіювання. А якщо ваш робочий потік включає локальні LLM-інструменти для ревʼю дифів, ми порівняли два головні варіанти у Ollama vs LM Studio.
— mrsaynothing
— mrsaynothing
Польові нотатки про ШІ, Linux і self-hosting.
Обговорити пост на dev.to dev.to ↗
Наступний гайд — на email
Один лист на пост. Полагодили — і далі.
що це таке?Шпаргалка journalctl: хвости, фільтри й живий хвіст логів
Читається добре? Таке я будую за гроші. найміть мене