Отмена действий гит
All checks were successful
Build MkDocs / build-and-deploy (push) Successful in 3s
All checks were successful
Build MkDocs / build-and-deploy (push) Successful in 3s
This commit is contained in:
134
docs/git/undo.md
Normal file
134
docs/git/undo.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Отмена действий в Git
|
||||
|
||||
## Отмена изменений до `git add`
|
||||
|
||||
Вернуть состояние файла к последнему коммиту.
|
||||
|
||||
```sh
|
||||
git restore <path-to-dir-or-file>
|
||||
```
|
||||
|
||||
|
||||
## Отмена изменений после `git add` до `git commit`
|
||||
|
||||
Если нежелательные изменения уже проиндексированы, т. е. выполнена команда `git add`.
|
||||
|
||||
```sh
|
||||
# Отменяет git add
|
||||
git restore --staged <path-to-dir-or-file>
|
||||
# Возвращает к исходному состоянию
|
||||
git restore <path-to-dir-or-file>
|
||||
```
|
||||
|
||||
Можно и одной командой.
|
||||
|
||||
```sh
|
||||
git reset --hard <path-to-dir-or-file>
|
||||
```
|
||||
|
||||
|
||||
## Отмена коммитов до `git push`
|
||||
|
||||
### Изменение последнего коммита
|
||||
|
||||
Часто нужно что-то добавить/исправить/удалить в последнем коммите, в том числе сообщение коммита.
|
||||
|
||||
```sh
|
||||
# Добавляем/исправляем/удаляем
|
||||
# Индексируем изменения (git add)
|
||||
git commit -m "New message" --amend
|
||||
```
|
||||
|
||||
Можно без `-m` и сообщения, если не хотим его менять, тогда надо будет просто закрыть открывшийся редактор, либо добавить флаг `--no-edit`, чтобы `Git` даже и не предлагал изменять сообщение.
|
||||
|
||||
```sh
|
||||
# Добавляем/исправляем/удаляем
|
||||
# Индексируем изменения (git add)
|
||||
git commit --amend --no-edit
|
||||
```
|
||||
|
||||
!!! warning "Коммит не должен быть запушен!"
|
||||
|
||||
Команда `git commit --amend` изменяет историю репозитория, не нужно использовать её, если последний коммит уже оказался на сервере (была выполнена команда `git push`).
|
||||
|
||||
### Удаление последних коммитов
|
||||
|
||||
Можно полностью удалить коммит из истории репозитория с помощью `git reset`.
|
||||
|
||||
```sh
|
||||
# Можно добавить --hard, чтобы откатить изменения и вернуть рабочий каталог
|
||||
# к состоянию, в котором он был на предыдущем коммите
|
||||
git reset HEAD~1
|
||||
```
|
||||
|
||||
После такого удаления можно делать `git push`, не опасаясь, что кто-нибудь ещё сможет получить доступ к данным коммита, его следы могут остаться лишь в локальной копии репозитория.
|
||||
|
||||
!!! warning "Коммит не должен быть запушен!"
|
||||
|
||||
Команда `git reset` изменяет историю репозитория, не нужно использовать её, если последний коммит уже оказался на сервере (была выполнена команда `git push`).
|
||||
|
||||
??? info "Подробнее про `git reset`"
|
||||
|
||||
Команда `git reset <commit>` просто перемещает текущую ветку и `HEAD` на указанный коммит. Соответственно, вместо `HEAD~1` (указатель на предыдущий коммит) можно указать любой другой коммит в текущей ветке, например, `HEAD~3` - позволит отменить последние 3 коммита. Разумеется можно указать хэш коммита, к которому нужно откатиться.
|
||||
|
||||
Параметр `--hard` говорит о том, что нужно сбросить и индекс и рабочий каталог до состояния указанного коммита. Есть и другие варианты: `--soft` - оставить изменения в индексе и рабочем каталоге, `--mixed` (значение по умолчанию) - сбросить индекс, но не трогать рабочий каталог.
|
||||
|
||||
??? info "Как восстановить коммиты, удалённые с помощью `git reset`"
|
||||
|
||||
`Git` ведёт локальный журнал всех операций, так что хэш коммита ещё можно восстановить.
|
||||
|
||||
```sh
|
||||
git reflog
|
||||
```
|
||||
|
||||
Зная хэш коммита, можно вернуть состояние ветки к нему с помощью того же `git reset`.
|
||||
|
||||
```sh
|
||||
git reset <commit-hash>
|
||||
```
|
||||
|
||||
Или, например, вынести его в отдельную ветку.
|
||||
|
||||
```sh
|
||||
git checkout <commit-hash>
|
||||
git checkout -b branch-with-restored-commit
|
||||
```
|
||||
|
||||
|
||||
## Отмена коммитов после `git push`
|
||||
|
||||
### Отмена изменений последнего коммита
|
||||
|
||||
Если коммит уже оказался в удалённом репозитории, то самый простой вариант - просто сделать новый коммит, который будет отменять изменения предыдущего.
|
||||
|
||||
```sh
|
||||
git revert HEAD
|
||||
```
|
||||
|
||||
Можно указать диапазон коммитов, которые нужно отменить, или перечислить их хэши.
|
||||
|
||||
```sh
|
||||
# Создаст коммит с отменой изменений последних трёх коммитов
|
||||
git revert HEAD~3..HEAD
|
||||
```
|
||||
|
||||
После `git revert` можно спокойно делать `git push`, не опасаясь, что возникнут какие-либо конфликты с удалённым репозиторием.
|
||||
|
||||
!!! warning "Изменения сохраняются в репозитории"
|
||||
|
||||
Никакие данные ни из локального, ни из удалённого репозитория не удаляются, все коммиты остаются в истории той же самой ветки. `git revert` не подходит, если нужно полностью удалить нежелательные изменения (например, конфиденциальные данные) из локального и удалённого репозитория.
|
||||
|
||||
### Удаление последних коммитов из удалённого репозитория
|
||||
|
||||
Переписывать историю удалённого репозитория можно если над репозиторием работает один человек, либо, если на сервер была отправлена конфиденциальная информация, которую непременно нужно удалить, в других случаях лучше использовать `git revert`.
|
||||
|
||||
Для отмены коммитов можно использовать методы, описанные в предыдущем разделе, а затем перезаписать историю удалённого репозитория.
|
||||
|
||||
```sh
|
||||
git push --force
|
||||
```
|
||||
|
||||
## Полезные ссылки
|
||||
- GitHowTo [12](https://githowto.com/ru/undoing_local_changes), [13](https://githowto.com/ru/undoing_staged_changes), [14](https://githowto.com/ru/undoing_committed_changes), [15](https://githowto.com/ru/removing_commits_from_a_branch).
|
||||
- [Отмена нескольких коммитов](https://stackoverflow.com/questions/1463340/how-can-i-revert-multiple-git-commits#answer-1470452).
|
||||
- [Удаление запушенного коммита](https://stackoverflow.com/questions/3293531/how-to-permanently-remove-few-commits-from-remote-branch#answer-41726152).
|
||||
Reference in New Issue
Block a user