Пошук уроків, статей та іншого контенту
Порівняйте режими --soft, --mixed і --hard та використовуйте git reset для переміщення HEAD і скасування commit.
git resetgit reset переміщує HEAD і, залежно від режиму, синхронізує з новим commit:
HEAD — поточна позиція Git, зазвичай останній commit поточної гілки.
Індекс — підготовлені до commit зміни, які відображаються після git add.
Робоче дерево — файли у вашій файловій системі.
Для команди:
git reset [режим] <commit>Git переміщує поточну гілку на вказаний <commit>. Режим визначає, що станеться з індексом і робочим деревом.
Найчастіше як commit використовують:
HEAD~1Це батьківський commit поточного HEAD, тобто commit на один крок раніше.
--softgit reset --soft HEAD~1Режим --soft:
переміщує HEAD і поточну гілку;
залишає індекс без змін;
залишає робоче дерево без змін.
У результаті зміни з commit, який було скасовано, залишаються підготовленими до нового commit.
Це зручно, коли потрібно:
змінити повідомлення commit;
об’єднати кілька commit;
додати або прибрати зміни перед повторним commit.
Приклад:
git reset --soft HEAD~1
git status
git commit -m "Оновлене повідомлення commit"Після reset --soft Git показуватиме зміни як staged, тобто вони вже перебувають в індексі.
--mixedgit reset --mixed HEAD~1--mixed є режимом за замовчуванням, тому ці команди еквівалентні:
git reset HEAD~1
git reset --mixed HEAD~1Режим --mixed:
переміщує HEAD і поточну гілку;
скидає індекс до стану нового HEAD;
залишає робоче дерево без змін.
Зміни зі скасованого commit залишаються у файлах, але більше не є підготовленими до commit.
Це корисно, коли потрібно скасувати commit, але зберегти його зміни для подальшого редагування:
git reset HEAD~1
git statusПісля цього за потреби можна вибірково підготувати файли:
git add src/app.js
git commit -m "Залишити потрібні зміни"--hardgit reset --hard HEAD~1Режим --hard:
переміщує HEAD і поточну гілку;
скидає індекс;
змінює робоче дерево відповідно до нового HEAD.
Зміни, яких немає у вибраному commit, з робочих файлів видаляються.
Це зручно, коли потрібно повністю повернути локальну гілку до попереднього стану:
git reset --hard HEAD~1Але команду потрібно використовувати обережно: незбережені зміни у робочому дереві можуть бути втрачені.
Нехай поточна гілка вказує на commit C3, а команда переміщує її на C2:
C1 --- C2 --- C3 (HEAD)Після виконання git reset <режим> C2:
--soft:
HEAD вказує на C2;
індекс і файли відповідають C3;
зміни між C2 і C3 є staged.
--mixed:
HEAD вказує на C2;
індекс відповідає C2;
файли відповідають C3;
зміни між C2 і C3 є unstaged.
--hard:
HEAD вказує на C2;
індекс відповідає C2;
файли відповідають C2;
зміни між C2 і C3 видалено з робочого дерева.
Наведена послідовність створює три commit і демонструє всі режими на одному репозиторії:
mkdir reset-demo
cd reset-demo
git init
git branch -M main
git config user.name "Demo User"
git config user.email "demo@example.com"
printf "version 1\n" > note.txt
git add note.txt
git commit -m "Початкова версія"
printf "version 2\n" >> note.txt
git add note.txt
git commit -m "Друга версія"
printf "version 3\n" >> note.txt
git add note.txt
git commit -m "Третя версія"
# Зберігаємо посилання на поточний commit для повторного прикладу
git tag before-reset
# Скасовуємо останній commit, але залишаємо його зміни staged
git reset --soft HEAD~1
git status --short
# Повертаємо репозиторій до стану перед демонстрацією
git reset --hard before-reset
# Скасовуємо останній commit і залишаємо його зміни unstaged
git reset --mixed HEAD~1
git status --short
# Знову повертаємо третій commit
git reset --hard before-reset
# Скасовуємо останній commit разом із його змінами у файлах
git reset --hard HEAD~1
cat note.txtПісля --soft команда git status --short покаже зміни як staged:
M note.txtПерший символ M означає зміни в індексі.
Після --mixed вивід буде таким:
M note.txtДругий символ M означає зміни лише у робочому дереві.
Після --hard файл note.txt міститиме тільки дані з попереднього commit.
git reset і скасування локальних commitЯкщо commit ще не був опублікований у віддаленому репозиторії, git reset часто є простим способом виправити локальну історію.
Наприклад, щоб прибрати останній commit, але зберегти його зміни підготовленими:
git reset --soft HEAD~1Щоб прибрати commit і залишити зміни для редагування:
git reset HEAD~1Щоб прибрати commit і повернути файли до попереднього стану:
git reset --hard HEAD~1git reset змінює історію поточної локальної гілки. Він не створює нового commit, який скасовує попередній. Натомість покажчик гілки переміщується на інший commit.
resetCommit, який залишився поза поточною гілкою, не обов’язково одразу втрачено. Git зберігає попередні позиції HEAD у журналі посилань.
Переглянути їх можна так:
git reflogУ виводі буде попередній commit, наприклад:
a1b2c3d HEAD@{0}: reset: moving to HEAD~1
f4e5d6c HEAD@{1}: commit: Третя версіяЯкщо потрібно повернутися до commit f4e5d6c, можна виконати:
git reset --hard f4e5d6cПеред використанням --hard переконайтеся, що у робочому дереві немає потрібних незбережених змін.
--soft і --mixed--soft залишає зміни staged, а --mixed прибирає їх з індексу. Обидва режими залишають файли у робочому дереві, але стан індексу відрізняється.
--hard без перевірки статусуПеред небезпечним reset варто перевірити:
git statusЯкщо у робочому дереві є незбережені зміни, --hard може їх видалити.
reset для вже опублікованої гілкиЯкщо гілку вже отримали інші розробники, переміщення її історії створює розбіжності між локальними та віддаленими копіями.
Для спільної історії зазвичай безпечніше створити новий commit, який скасовує попередні зміни, використовуючи git revert. git reset переважно застосовують для локальної або ще не опублікованої історії.
Після git reset commit зникає з поточної гілки, але може залишатися доступним через git reflog. Не слід одразу створювати багато нових операцій, якщо потрібно відновити попередній стан: спочатку знайдіть потрібний commit у журналі.
git reset переміщує HEAD і покажчик поточної гілки до іншого commit.
--soft залишає зміни staged.
--mixed залишає зміни у файлах, але прибирає їх з індексу. Це режим за замовчуванням.
--hard синхронізує HEAD, індекс і робоче дерево, видаляючи незбережені зміни.
Для локального виправлення історії використовуйте reset, але обережно застосовуйте його до опублікованих гілок.
Якщо reset виконано помилково, попередній стан часто можна знайти через git reflog.