Назад до блога

Git revert чи git reset: хто рятує вашу історію?

15 вересня 2026 р.

TL;DR: git revert додає новий коміт, що скасовує старий — історія збережена, безпечно на гілках, які хтось уже пуллив. git reset відсуває вказівник гілки назад — історія переписується, безпечно лише на комітах, яких не пушив. На спільних гілках — revert, на локальному прибиранні — reset. А reset --hard ще й видаляє незакомічені зміни робочого дерева; саме він з’їдає справжню роботу.

У чому різниця між git revert і git reset?

Обидва змушують проєкт виглядати так, ніби минулого коміта не було. Розходяться в тому, як:

  • git revert <sha> обчислює обернений патч коміта і комітить його. Історія росте на один коміт «скасуй той». Поганий коміт лишається в логу, за ним — його скасування. SHA всього іншого недоторкані.
  • git reset <sha> зсуває вказівник поточної гілки на <sha>. Коміти після нього відв’язуються — досі в базі об’єктів до збирання сміття, але більше не досяжні з жодної гілки чи git log.

Один нічого не переписує, інший прикидається, що нічого не було. Саме та властивість вирішує, кого вимагає кожна ситуація:

# Демонстрація: одноразовий runnable-репозиторій
git init /tmp/revert-vs-reset && cd /tmp/revert-vs-reset
echo one > file.txt && git add . && git commit -m "one"
echo two > file.txt && git add . && git commit -m "two"

# Revert: історія тримає обидва коміти, плюс третій, що скасовує "two"
git revert --no-edit HEAD
git log --oneline        # 3 коміти: revert, two, one

# Reset: вказівник гілки відсунувся, "two" зникає з логу
git reset --hard HEAD~1
git log --oneline        # 1 коміт: one

Запустіть обидва й огляньте git log — асиметрія і є вся відповідь.

Що насправді роблять reset —soft, —mixed і —hard?

Три режими керують тим, де виживають ваші зміни після руху вказівника:

РежимВказівник гілкиСтейджингРобоче деревоВаші правки
--softназадлишилися застейджениминедоторканізбережені повністю
--mixed (дефолт)назаднестейдженінедоторканізбережені, нестейджені
--hardназадскинутоскинутовидалені

Конкретні прочитання таблиці:

  • git reset --soft HEAD~1 — «я закомітив зарано». Усе повертається застейдженим, готовим до повторного коміту, можливо разом з іншою роботою.
  • git reset HEAD~1 (mixed) — «я застейджив не ті файли». Правки живуть у робочому дереві, стейдж порожній. Спарте з видаленням невідстежуваних файлів, коли хочете прибрати й блукаючі файли.
  • git reset --hard HEAD~1 — «цей коміт і мої незакомічені правки — сміття». Git не спитає двічі; для частини з робочим деревом скасування немає, якщо не застешували і не комітили заздалегідь.

У revert режимів немає, бо він ніколи нічого не нищить — лише додає компенсувальний коміт.

Коли брати git revert замість git reset?

Одне питання: чи хтось ще пуллив цей коміт? Якщо так — reset за бортом.

Скидання гілки, на якій хтось будував роботу, переписує спільну історію. Їхній наступний pull зустрічає розбіжні гілки, а «виправлення» — це зазвичай force-push, що перетворює вашу помилку на проблему всіх. Revert додає звичайний коміт, тож звичайний git pull мержиться чисто для всіх — тому revert є типовою відповіддю на main і в GitHub pull request’ах, де кнопка «Revert» існує саме тому, що переписати історію змерженого PR — не варіант.

Reset — для вікна до поширення: коміт, зроблений тридцять секунд тому, помилка стейджингу, локальна експериментальна гілка. Якщо єдина копія роботи — на вашій машині, ви вільні переставляти історію — у цьому весь сенс передпушного вікна.

Проміжний випадок: ви запушили у власну feature-гілку, і ніхто на ній не будує. Force-push після reset там соціально прийнятний, але revert досі коштує менше координації. Залишіть force-push-и для гілок, якими володієте самі.

Чи revert безпечніший за reset для спільних гілок?

Так, структурно — не лише за конвенцією:

  • Revert породжує звичайний коміт: CI на ньому біжить, диф придатний до рев’ю, а git log пояснює майбутньому-вам, чому зміна зникла.
  • Reset мовчки викидає проміжний стан. Ніхто, хто ревʼюватиме пізніше, не побачить, що скасували і коли, бо лог показує пряму лінію, яка ніколи його не містила.

Два практичні гострі краї:

  • Скасування merge-коміта вимагає git revert -m 1 <sha> (лишити лінію першого батька). Без -m git відмовляється і лишає вам читати помилку.
  • Revert — не машина часу: він скасовує диф одного коміта. Якщо пізніші коміти чіпали ті самі рядки, можливо, доведеться розв’язувати конфлікти — це git каже, що скасування переплелося, корисна інформація, а не несправність.

Про скасування саме вашого останнього коміта — зі збереженням чи викиданням змін — варіанти розкладені в git undo last commit: зі збереженням змін.

А git restore — де його місце?

git restoregit switch, його пара) приїхали в git 2.23, щоб забрати роботи, які reset робив погано через перевантаження іменами:

ЗадачаСтара дорогаЗрозуміла дорога
Відкинути правки робочого дерева у файліgit checkout -- file / git reset --hardgit restore file
Зняти файл зі стейджингуgit reset HEAD filegit restore --staged file
Перемістити гілку на інший комітgit reset <sha>git reset <sha> (заміни немає — це лишається)

Отже сучасний поділ: restore лагодить файли, reset рухає гілки, revert скасовує опубліковані коміти. Автодоповнення показує, що люди шукають «git revert vs reset vs restore» разом недаремно — це одна ментальна модель, розлита на три команди. Старі форми git checkout досі працюють всюди; нові просто не дають вам відправити цілу гілку в шредер, коли ви мали на увазі зняти один файл зі стейджингу.

Якщо ж ваша ціль — скопіювати хороший коміт уперед, а не стерти поганий, то це робота cherry-pick — дивіться git cherry-pick: кілька комітів, гілок і конфліктів.

Швидкий підсумок рішень

  1. Коміт публічний (запушено, інші пуллили) → git revert <sha>.
  2. Коміт лише локальний, хочете переробити → git reset --soft чи --mixed і перекомітіть.
  3. Лише локальний, хочете, щоб зник разом із незакоміченим безладдям → git reset --hard, після одного чесного погляду, що ще тримає робоче дерево.
  4. Поламали один файл → git restore <file> і лишіть гілку в спокої.

Єдиний справді небезпечний пункт у тому списку — --hard; усе інше можна відбити назад через git reflog. Постійні втрати в git вузькі й здебільшого вимагають, щоб ви ввели їх явно; звичка, варта вироблення, — застигнути на пів секунди перед --hard, а не уникати гострих інструментів git узагалі.

— mrsaynothing

— mrsaynothing

Польові нотатки про ШІ, Linux і self-hosting.

Обговорити пост на dev.to dev.to ↗

Наступний гайд — на email

Один лист на пост. Полагодили — і далі.

self-hosted · без третіх сторін · відписка в один клік

що це таке?

Systemd-сервіс не стартує? Як це виправити

Читається добре? Таке я будую за гроші. найміть мене