Есть ли способ "мягкого возврата" старого коммита?

Есть ли способ вернуть старый коммит без изменения файлов в рабочем каталоге? Я сделал коммит некоторое время назад, но код, который я зафиксировал, не был готов, и я хочу, чтобы эти изменения оставались в моем рабочем каталоге как незафиксированные изменения, чтобы я мог продолжить работу над ними сейчас. Я посмотрел в команду возврата, но это меняет рабочий каталог. Я думал о проверке старой ревизии, обнулении головы 1 и сохранении изменений, но у меня уже есть изменения. Я просто хочу, чтобы это было так, как будто я никогда не делал этот коммит еще тогда, но я хочу, чтобы изменения в файлах остались.

6 ответов

Решение

Короткий ответ - нет".

Чем дольше ответ: git revert- как и все операции слияния, в том числе git cherry-pick, git rebaseи конечно git merge само по себе - изменяет изменяемое рабочее дерево, используя индекс. Вы можете зафиксировать или спрятать вашу текущую работу, или получить второе дерево работы (с другим клоном, или используя git worktree если у вас Git версии 2.5 или выше).

Ты можешь использовать git revert -n, что позволяет рабочему дереву быть грязным, но я бы не советовал это здесь.

То, как я справлюсь с этим, это сделать коммит сейчас:

$ git add ...
$ git commit -m 'temporary commit, do not push'

Затем сделайте желаемый возврат как обычный коммит:

$ git revert <hash>

Тогда используйте git rebase -i поменять местами порядок нового возврата и временного принятия:

$ git rebase -i HEAD~2  # and edit the two "pick" lines

затем используйте git reset --soft HEAD^ (или же HEAD~1тоже самое) или git reset --mixed HEAD^ снять временную фиксацию В этот момент вы находитесь в том же состоянии (в основном), в котором находились до того, как сделали временный коммит.

(В основном) имеет отношение к состоянию индекса: если вы используете git reset --soft, всех тех git addсейчас действуют. Если вы используете git reset --mixedни один из тех git addсейчас действуют.

Только для экспертов

Если до того, как вы начнете что-либо из этого, у вас уже есть какое-то тщательно подготовленное состояние, например git add -p- что вы хотите сохранить, это требует выполнения двух коммитов, и git stash до возврата, с git stash apply --index потом проще. Это потому что git stash фактически делает два коммита, и git stash apply --index извлекает и применяет эти два коммита отдельно к индексу и рабочему дереву. (Затем git stash drop тайник, если все прошло хорошо.)

В зависимости от того, насколько вам удобно git stashВы можете даже заменить всю последовательность выше на git stash && git revert <hash> && git stash pop сделать это как однострочник. добавлять --index восстановить отдельное состояние индекса. (Обратите внимание, что если вы опечатка --index и ваша версия Git недостаточно современна, чтобы обнаружить ошибку, это объединит два отдельных коммита и сбросит тайник. Вот почему я люблю использовать git stash apply вместо git stash pop Вот.)

Если во время этого процесса что-то пойдет не так, вам необходимо точно знать, что произошло, и что с этим делать, поэтому заголовок "только для экспертов" над этой частью.

Вы можете сделать что-то вроде

git revert hash_of_your_commit
git reset HEAD^

После этого вы пришли с неустановленными изменениями вашего отмененного коммита.

У меня обычно работает эта команда: git revert --no-commit <commit>

Отличный вариант, использоватьgit apply, что является безопасной операцией и не редактирует локальную историю git.

Это мягко вернет конкретную фиксацию

      git show COMMIT_HASH | git apply -R

Как это работает

Используяgit show, мы получаем diff из определенного коммита. Затемgit apply -Rотменяет эти изменения и применяет их к текущему репо (без фиксации)

git revert <commit-hash>

git cherry-pick -n <commit-hash>

Другой способ сделать это - установить плохой $EDITOR, например:

EDITOR=nope git revert <hash>

он выйдет при попытке отредактировать сообщение о коммите, но уже внес изменения

Другие вопросы по тегам