Пошук уроків, статей та іншого контенту
Створюйте новий commit, який скасовує попередні зміни, не переписуючи спільну історію.
git revertgit revert скасовує зміни, внесені певним commit, але не видаляє його з історії. Замість цього Git створює новий commit із протилежними змінами.
Наприклад, якщо commit додав рядок у файл, commit-відкат видалить цей рядок.
A --- B --- C
\
D ← commit, створений git revert CCommit C залишається в історії, а D скасовує його зміни.
Це відрізняє git revert від команд, які переписують історію, наприклад git reset. Тому git revert безпечний для гілок, якими користуються кілька розробників.
Спочатку перегляньте історію та знайдіть commit, який потрібно скасувати:
git log --onelineПриклад результату:
f8a31c2 Update validation
c42e9d1 Add login form
a17b5e0 Initial project setupЩоб скасувати commit f8a31c2, виконайте:
git revert f8a31c2Git створить новий commit. Якщо для commit не задано параметр --no-edit, Git відкриє редактор повідомлення commit за замовчуванням.
Типове повідомлення матиме вигляд:
Revert "Update validation"Після збереження повідомлення новий commit буде створено автоматично.
Перевірити результат можна так:
git log --onelineІсторія матиме приблизно такий вигляд:
91bd7a4 Revert "Update validation"
f8a31c2 Update validation
c42e9d1 Add login form
a17b5e0 Initial project setupДля скасування останнього commit можна використати спеціальне посилання HEAD:
git revert HEADHEAD вказує на поточний commit, тобто на вершину активної гілки.
Після виконання команди:
попередній commit залишиться в історії;
буде створено новий commit;
зміни попереднього commit буде скасовано;
робоче дерево зазвичай залишиться чистим.
Приклад повного сценарію:
# Створюємо новий файл
printf "temporary feature\n" > feature.txt
# Додаємо файл до індексу
git add feature.txt
# Створюємо commit
git commit -m "Add temporary feature"
# Скасовуємо останній commit новим commit
git revert HEAD
# Перевіряємо історію
git log --oneline -3Після git revert HEAD файл feature.txt буде видалено з робочого дерева, але commit Add temporary feature залишиться в історії.
За замовчуванням Git пропонує повідомлення на кшталт:
Revert "Add temporary feature"Щоб одразу використати стандартне повідомлення без відкриття редактора:
git revert --no-edit HEADЯкщо потрібно встановити власне повідомлення:
git revert --no-edit -m "Revert temporary feature" HEADУ цій команді параметр -m має інше значення, ніж під час скасування merge commit. Для власного повідомлення використовуйте параметр -m лише разом із форматом, який підтримує ваша версія Git; найнадійніший спосіб — дозволити Git відкрити редактор або змінити повідомлення після створення commit.
Практично зазвичай достатньо:
git revert HEADта відредагувати запропоноване повідомлення в редакторі.
Скасувати кілька останніх commit можна окремими командами:
git revert HEAD
git revert HEAD~1
git revert HEAD~2Однак після кожної команди змінюється HEAD, тому посилання потрібно обирати уважно.
Для діапазону commit використовується синтаксис:
git revert OLDEST^..NEWESTНаприклад:
git revert a17b5e0^..f8a31c2Ця команда вказує Git скасувати commit від a17b5e0 до f8a31c2 включно. Символ ^ перед першим commit потрібен, щоб включити сам a17b5e0 до діапазону.
Перед скасуванням діапазону варто перевірити, які commit до нього входять:
git log --oneline a17b5e0^..f8a31c2Якщо в діапазоні є взаємозалежні зміни, Git може зупинитися через конфлікт. У такому разі часто безпечніше скасовувати commit по одному, перевіряючи стан проєкту після кожного кроку.
git revert і незбережені зміниПеред скасуванням commit бажано перевірити стан робочого дерева:
git statusЯкщо є незбережені зміни, Git може відмовитися виконувати revert, щоб не перезаписати вашу роботу.
Можливі варіанти:
Зберегти зміни в окремому commit.
Тимчасово сховати їх за допомогою git stash.
Відмовитися від непотрібних локальних змін.
Не варто запускати git revert, не перевіривши, які файли вже змінені локально.
За замовчуванням git revert сам створює commit. Щоб застосувати зворотні зміни, але не створювати commit одразу, використовуйте:
git revert --no-commit HEADАбо короткий запис:
git revert -n HEADПісля цього можна перевірити зміни:
git diff
git statusЯкщо результат правильний, створіть commit самостійно:
git add .
git commit -m "Revert validation changes"Це корисно, коли потрібно скасувати кілька commit і об’єднати результат в один зрозумілий commit.
Приклад:
# Застосовуємо скасування без створення commit
git revert --no-commit HEAD~2..HEAD
# Перевіряємо підсумкові зміни
git diff --cached
# Створюємо один commit для всього скасування
git commit -m "Revert recent changes"Під час git revert --no-commit зміни потрапляють до індексу, тому для перевірки часто використовують саме git diff --cached.
Конфлікт виникає, коли Git не може автоматично застосувати зворотні зміни. Наприклад, наступний commit уже змінив ті самі рядки, які намагається скасувати git revert.
Після конфлікту Git покаже повідомлення та зупинить операцію. Перевірте стан:
git statusФайли з конфліктами міститимуть спеціальні маркери:
<<<<<<< HEAD
Поточний варіант
=======
Варіант зі скасування
>>>>>>> parent of f8a31c2Потрібно:
Відкрити файли з конфліктами.
Вручну залишити правильний варіант.
Видалити маркери <<<<<<<, ======= і >>>>>>>.
Додати виправлені файли до індексу.
Завершити операцію.
git add path/to/file.js
git revert --continueЯкщо Git відкриє редактор повідомлення commit, збережіть повідомлення та закрийте редактор.
Якщо ви вирішили скасувати всю операцію:
git revert --abortПісля цього Git спробує повернути стан робочого дерева до стану перед початком revert.
Merge commit має двох або більше батьків. Тому Git не може автоматично визначити, відносно якої батьківської гілки потрібно скасувати merge.
Для такого commit потрібно вказати основну батьківську гілку:
git revert -m 1 <merge-commit>Наприклад:
git revert -m 1 7ac91deНомер 1 зазвичай відповідає гілці, у яку виконували merge, а номер 2 — гілці, яку приєднали. Перед виконанням команди потрібно переконатися, який parent є основним:
git show --summary 7ac91deСкасування merge commit може створити складні конфлікти. Крім того, Git запам’ятовує, що цей merge вже було скасовано. Якщо пізніше спробувати повторно злити ті самі зміни, Git може не застосувати їх автоматично.
Для звичайного скасування merge краще виконувати команду на актуальній гілці та після цього перевіряти тести й робочий стан проєкту.
Після створення commit-відкату його можна опублікувати звичайним способом:
git push origin mainІнші учасники отримають:
початковий commit;
новий commit, який скасовує його;
повну послідовну історію без переписування вже опублікованих commit.
Саме тому git revert часто використовують у main, master або інших спільних гілках.
git revert і git resetЦі команди мають різне призначення.
git revertстворює новий commit;
зберігає попередню історію;
підходить для вже опублікованих commit;
безпечний для спільних гілок.
git resetпереміщує покажчик гілки;
може прибрати commit із видимої історії;
часто змінює стан індексу або робочого дерева;
небезпечний для commit, які вже отримали інші розробники.
Якщо commit уже було передано до віддаленого репозиторію, для скасування змін зазвичай обирають git revert.
git revert не видаляє початковий commit. Це очікувана поведінка:
git revert HEADУ результаті історія міститиме і початковий commit, і commit-відкат.
Перед скасуванням перевірте повну інформацію про commit:
git show <commit>Переконайтеся, що це саме той commit і що він містить потрібні зміни.
Після конфлікту не потрібно повторно запускати git revert. Спочатку перегляньте стан:
git statusПотім виправте файли, виконайте git add і продовжіть:
git revert --continueПеред командою перевірте активну гілку:
git branch --show-currentСкасування commit в іншій гілці не змінить гілку, яку ви насправді хотіли виправити.
git revert технічно може завершитися успішно, але скасування може вплинути на інші частини програми. Після операції перевірте:
git status
git diff HEAD^ HEADТакож запустіть тести проєкту, якщо вони налаштовані.
git revert <commit> створює новий commit, який скасовує зміни вказаного commit.
Початковий commit залишається в історії.
git revert HEAD скасовує останній commit.
git revert --no-commit застосовує скасування без негайного створення commit.
Конфлікт вирішують через git add і git revert --continue.
Щоб повністю відмовитися від операції, використовують git revert --abort.
Для merge commit потрібно вказати основного батька через -m.
Для вже опублікованих commit у спільній гілці git revert безпечніший за переписування історії.