Як відкотити комміти до Git: докладний посібник
Для відкату комміту Git можна використовувати команду git reset. Залежно від того, який тип відкату потрібен, використовуються різні опції цієї команди. Розглянемо найпоширеніші варіанти.
1. Відкат останнього комміту
Якщо потрібно відкотити останній коміт, можна використовувати команду:
HEAD позначає поточну позицію у гілці, а символ вказує на попередній коміт. Таким чином, команда reset HEAD ^ скасовує останній коміт і повертає файли в стан перед ним.
2. Відкат на певний коміт
Якщо потрібно скасувати коміт, який було зроблено не останнім, необхідно провести відкат на конкретний комит. Для цього потрібно знати хеш-код, який можна отримати за допомогою команди git log. Наприклад, якщо потрібно відкотити на передостанній коміт, потрібно виконати наступну команду:
3. Відкат комміту зі збереженням змін
Іноді корисно зберегти внесені зміни, але скасувати тільки конкретний коміт. Для цього можна використовувати опцію -soft. Наприклад, якщо потрібно скасувати останній коміт, але зберегти його зміни, потрібно виконати наступну команду:
git reset --soft HEAD^
4. Відкот комміту з видаленням змін
Якщо потрібно скасувати коміт і видалити всі зміни, які він вніс, можна використовувати опцію --hard. Наприклад, якщо потрібно повернутися на три коміти назад і видалити всі зміни, потрібно виконати наступну команду:
git reset --hard HEAD~3
Ця команда відкочує на три коміти назад і видаляє всі зміни, які було зроблено після цього комміту.
$ git log --oneline a3c3f2c 4 commit cc2691d 3 commit 5bfe648 Second commit 10586b2 1 commit $ git reset HEAD ^ commit 10586b2 First commit
У цьому прикладі ми зробили чотири комміти, а потім відкотили останній за допомогою команди git reset. Після цього ми бачимо, що у гілці залишилися лише три коміти, а зміни, які були в останньому коміті, повернулися до робочої директорії. В даному випадку ми використовували опцію HEAD для відкату на один коміт назад.
Як повернутися (відкотитися) до більш раннього коміту?
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).
(wt) (i) A - B - C - D? ↑ ↑ master stash (HEAD)
Відновлення незбережених змін: легко та просто.
Якщо 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 - x - x ↑ 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 Зберегти зміни у робочій області, але не індексі.
Ця команда просто переміщає вказівник гілки, але не відображає зміни в індексі (він буде порожнім).
(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 - x - x ↑ 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-коміт виявився помилковим, використовуйте цю відповідь