Временно переключите рабочую копию на определенный коммит Git

249

Как переключиться на конкретный коммит Git без потери всех коммитов, сделанных после него ?

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

Я хочу изменить состояние файлов на конкретную фиксацию, запустить проект и, когда закончите, восстановить файлы до последней фиксации.

Как это сделать без архивирования всей папки проекта?

Павел
источник

Ответы:

344

Если вы находитесь на определенной ветке mybranch, просто продолжайте git checkout commit_hash. Затем вы можете вернуться в свою ветку по git checkout mybranch. У меня была та же самая игра, которая делит пополам ошибку сегодня :) Также вы должны знать о git bisect .

Александр Павлов
источник
6
Обратите внимание, что вы можете просто сделать это, git checkout commit_hashесли вы находитесь в чистом хранилище и не нуждаетесь в ветвлении. Может быть проще для некоторых случаев использования (как у меня).
enderland
@enderland: твоя ГОЛОВА всегда указывает на какую-то ветку, обычно :)
Александр Павлов
У меня была проблема, когда мне приходилось использовать весь хеш коммита, потому что частичный не был принят.
Mightyiam
6
Upvote для git bisectсправки; какой чрезвычайно полезный инструмент!
Ниек
55

Во-первых, используйте git logдля просмотра журнала, выберите нужный коммит, запишите хэш sha1, который используется для идентификации коммита. Далее беги git checkout hash. После того, как вы закончите git checkout original_branch. Преимущество в том, что вы не перемещаете ГОЛОВКУ, а просто переключаете рабочую копию на конкретный коммит.

Femaref
источник
4
Я думаю, что вы имеете в виду git checkout <original_branch>. git checkout HEADфактически NOOP
Abe Voelker
3
git reset --hard <hash>изменяет заголовок текущей ветви, в то время как git checkout <hash>вы получаете отдельную проверку, которая не меняет никакой ветви, и вы можете легко вернуться, не зная исходного хеш-кода вашей ветви, как показано в этом ответе.
Джофель
@Femaref Вопрос новичка: учитывая контекст этого вопроса (временно переключиться на более ранний коммит), почему было бы преимуществом или недостатком перемещать или не перемещать ГОЛОВУ?
Сумасшедший о Natty
@nuttyaboutnatty Предполагая, что мое редактирование одобрено, оно должно ответить на ваш вопрос. ГОЛОВУ фактически перемещают в любом случае; но в извлечении ссылка на ветку, на которую указывает HEAD, сама не перемещена.
Эхристоферсон
15

В дополнение к другим ответам, приведенным здесь, показывающим, как git checkout <the-hash-you-want>стоит знать, вы можете вернуться туда, где вы использовали:

git checkout @{-1}

Это часто более удобно, чем:

git checkout what-was-that-original-branch-called-again-question-mark

Как и следовало ожидать, git checkout @{-2}вы вернетесь в ту ветвь, в которой вы были два года git checkoutназад, и аналогично для других номеров. Если вы можете вспомнить, где вы были для больших чисел, вы должны получить какую-то медаль за это.


К сожалению, для производительности, git checkout @{1}не приведет вас к отрасли, в которой вы будете в будущем, что является позором.

Benjohn
источник
1
Обратите внимание, что git checkout -это сокращенный псевдоним дляgit checkout @{-1}
Натанаэль
@ Натанаэль OMGOD , ни за что ... это меняет все! Приятно спасибо! … Я собирался включить это в ответ, но я думаю, что также полезно знать об общем @{n}синтаксисе, так как он работает со многими командами git. Мне было трудно добавить вашу стенограмму, не делая ответ довольно запутанным. Вместо этого я проголосовал за ваш комментарий - надеюсь, люди это увидят. Еще раз спасибо.
Бенджон
1
Нет проблем. В любом случае, эта дискуссия касается реального вопроса. Больше бонуса! Я часто использую один и тот же синтаксис для объединения функций в выпуске. например, git merge -чтобы объединить ветку, которую вы последний раз проверяли, с веткой, которая была извлечена в данный момент. Это как cd -в Bash.
Натанаэль