Как я могу сбросить или вернуть файл к определенной версии?

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

Я сделал git log вместе с git diff, чтобы найти нужную мне ревизию, но просто не знаю, как вернуть файл в его прежнее состояние в прошлом.


person Hates_    schedule 18.10.2008    source источник
comment
После возврата не забудьте --cached при проверке git diff. ссылка   -  person Geoffrey Hale    schedule 02.12.2015
comment
Я нашел ваш вопрос, когда погуглил. Но после того, как я прочитал решение, я проверил свой журнал и обнаружил, что я внес эти изменения как отдельный коммит, поэтому я сделал git revert для этого коммита, а все остальное осталось, как я этого хотел. Не решение, просто еще один способ сделать это иногда.   -  person sudo97    schedule 08.08.2017
comment
Я использую это ручное решение: $ git revert ‹commit›, затем удалите требуемые изменения, затем загрузите эти требуемые изменения в новую фиксацию.   -  person Intenzion    schedule 14.07.2021


Ответы (33)


Предполагая, что хеш фиксации, который вы хотите, равен c5f567:

git checkout c5f567 -- file1/to/restore file2/to/restore

Дополнительная информация представлена ​​на странице руководства git checkout.

Если вы хотите вернуться к фиксации до c5f567, добавьте ~1 (где 1 - количество коммитов, которые вы хотите вернуться, это может быть что угодно):

git checkout c5f567~1 -- file1/to/restore file2/to/restore

Кстати, мне всегда было неудобно с этой командой, потому что она используется как для обычных вещей (переход между ветвями), так и для необычных, деструктивных вещей (отбрасывание изменений в рабочем каталоге).


Также имеется новая команда git restore, специально разработанная для восстановления файлов рабочих копий, которые были изменен. Если ваш git достаточно новый, вы можете использовать эту команду, но в документации есть предупреждение:

ЭТА КОМАНДА ЯВЛЯЕТСЯ ЭКСПЕРИМЕНТАЛЬНОЙ. ПОВЕДЕНИЕ МОЖЕТ ИЗМЕНИТЬСЯ.

person Greg Hewgill    schedule 18.10.2008
comment
@shadowhand: Есть ли способ изменить это так, чтобы это была версия сразу после? - person aliteralmind; 29.04.2014
comment
@aliteralmind: Нет, к сожалению, запись ярлыков истории Git идет только назад в истории. - person Greg Hewgill; 29.04.2014
comment
Если вы собираетесь использовать имя ветки для abcde (например, develop), вам понадобится git checkout develop -- file/to/restore (обратите внимание на двойное тире) - person Ohad Schneider; 07.10.2014
comment
@aliteralmind: На самом деле, да, есть способ сделать это: git log --reverse -1 --ancestry-path yourgitrev..master, а затем использовать соответствующие параметры, чтобы просто получить git rev. --ancestry-path проведет линию между двумя коммитами, а -1 покажет вам только одну версию, а --reverse гарантирует, что первая отправленная запись является самой старой. - person Chris Cogdon; 19.11.2014
comment
Обязательно проверьте хэш ревизии, в котором все еще есть файл, который вы ищете. Если он был удален в ревизии, перейдите к хешу хотя бы на одну раньше. - person C Fairweather; 30.03.2015
comment
Чтобы автоматизировать весь процесс поиска в истории файла и проверки соответствующего идентификатора фиксации с помощью одной команды git, используйте git prevision. - person TheCodeArtist; 01.05.2015
comment
Если вы хотите удалить изменения в этом конкретном файле, вы можете использовать git checkout path/to/file. Если вы не укажете хеш, используется HEAD. - person Flows; 27.05.2016
comment
Лично мне HEAD ^ легче набирать, чем HEAD ~ 1 :) - person juzzlin; 01.07.2016
comment
Можем ли мы передать список файлов, разделенных пробелами, сразу после идентификатора фиксации? - person Saurav Sahu; 03.02.2017
comment
@juzzlin Или используйте @^ вместо HEAD^. - person Tom Hale; 28.07.2017
comment
Я также только что понял, что вы должны находиться в ветке, на которую вы нажали, а не из. - person ArielSD; 23.08.2017
comment
Приведенная выше команда сработала для меня. Однако автозаполнение предполагало версию файла с заглавной буквы, а созданный FILE1 / TO / RESTORE не соответствовал ни одному файлу (файлам), известным git. Случаи должны соответствовать тому, что git имеет в репозитории. - person brentlightsey; 27.11.2017
comment
Как я могу проверить 2 или более файла? - person Eduard; 14.01.2018
comment
Я собирался поставить +1 вам, но очевидно, что был здесь хотя бы однажды раньше: D Очень полезный ответ, который, возможно, мне стоит запомнить! - person Darragh Enright; 10.07.2018
comment
Примечание для пользователей Windows: относительного пути было недостаточно, мне пришлось указать полный путь, например. /d/Repos/MyRepo/Folder1/Folder2/FileIWantToCheckout.json - person System.Cats.Lol; 24.08.2018
comment
Неверный ответ, это НЕ ПЕРЕВЕРТ. Это только изменяет файл, поэтому содержимое точно такое же, как и коммит, который вы ему даете, вам нужно снова выполнить фиксацию, чтобы это действительно было реализовано. - person basickarl; 04.12.2018
comment
Используйте git checkout 5364aee~1 path/to/dir/* для восстановления всего каталога файлов до их версии до 5364aee. - person joshden; 06.03.2019
comment
Кто-нибудь может объяснить примечание на полях? Почему есть разница между переключением между ветвями и отменой изменений в рабочем каталоге? Не переключение ветки не отменяет изменения, если имена файлов совпадают? - person Mark Bolster; 01.04.2019
comment
@MarkBolster: форма команды, показанная в ответе, использует git checkout -- для восстановления определенного содержимого файла. Конечно, другое совершенно другое использование git checkout - переключение ветвей. Мне непонятно, почему кто-то решил использовать одно и то же имя команды для двух совершенно разных вещей. (И нет, переключение веток никогда не отменяет изменения, если вы попытаетесь это сделать, git пожалуется и спросит вас, что вы хотите сделать с изменениями, которые будут перезаписаны.) - person Greg Hewgill; 01.04.2019
comment
это буквально ничего не делает - person Tyguy7; 28.06.2019
comment
@GregHewgill git недавно представил git restore, это более подходящая команда в будущем. Возможно, вы захотите отредактировать это в своем ответе. - person tschoppi; 07.10.2019
comment
@tschoppi: Спасибо, я сделаю это, когда команда больше не будет отмечена как экспериментальная. - person Greg Hewgill; 18.10.2019
comment
Я попытался восстановить папку с помощью git checkout HEAD~2 -- my_folder/*, но это не сработало. - person Aaron Franke; 16.05.2020
comment
Эк дум гаджаб решение! У меня это сработало. - person Takermania; 18.12.2020

Вы можете быстро просмотреть изменения, внесенные в файл, с помощью команды diff:

git diff <commit hash> <filename>

Затем, чтобы вернуть конкретный файл к этой фиксации, используйте команду сброса:

git reset <commit hash> <filename>

Возможно, вам потребуется использовать параметр --hard, если у вас есть локальные изменения.

Хороший рабочий процесс для управления путевыми точками - использовать теги, чтобы четко отмечать точки на временной шкале. Я не совсем понимаю ваше последнее предложение, но вы можете захотеть отклонить ветвь от предыдущего момента времени. Для этого воспользуйтесь удобной командой оформления заказа:

git checkout <commit hash>
git checkout -b <new branch name>

Затем вы можете переустановить это на свою основную линию, когда будете готовы объединить эти изменения:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>
person Chris Lloyd    schedule 17.12.2008
comment
Команда 'git checkout ‹commit hash›' вернула мне мою старую версию проекта именно эту, которую я искал. Спасибо, Крис. - person vidur punj; 27.01.2013
comment
'git reset ‹хеш фиксации› ‹filename› »не изменил мой конкретный файл, который я хотел изменить. Есть ли способ проверить версию файла, а не весь проект? - person Danny; 20.02.2013
comment
Восстановление файла git checkout <commit hash> <filename> у меня сработало лучше, чем git reset - person Motti Strom; 07.03.2013
comment
Мне нужна была ранняя версия одного файла, потому что я перезаписал 150 строк с помощью плохо выбранной копии / вставки. git checkout <commit hash> <filename> работал у меня. Это не должен быть общепринятым ответом, ИМХО. git reset нет. - person harperville; 28.02.2014
comment
Сброс Git без аппаратной опции не изменяет рабочую копию, поэтому не повлиял. Аппаратный сброс заставляет файл выглядеть точно так же, как в репозитории в указанной фиксации, и ОТМЕНЯЕТ ваши локальные изменения, если таковые имеются. - person SteveB; 24.11.2014
comment
нельзя использовать git reset для сброса одного файла, вы получите сообщение об ошибке fatal: Cannot do hard reset with paths - person slier; 23.12.2014
comment
Что сказал Шлиер: вы не можете git reset --hard <commit hash> <filename>. Это приведет к ошибке fatal: Cannot do hard reset with paths. Что сказал Мотти Стром: используйте git checkout <commit hash> <filename> - person Hawkeye Parker; 06.02.2015
comment
@HawkeyeParker да, мы это видим. Спасибо за подведение итогов. - person Adam Plocher; 17.07.2018
comment
@Chris, фатальный: невозможно выполнить полный сброс с помощью путей. - person Pacerier; 20.05.2020
comment
Я не понимаю этого, но все равно спасибо, Крис Ллойд, это очень аккуратно. - person drakogemini2; 06.01.2021

Вы можете использовать любую ссылку на коммит git, включая SHA-1, если это наиболее удобно. Дело в том, что команда выглядит так:

git checkout [commit-ref] -- [filename]

person foxxtrot    schedule 07.04.2009
comment
В чем разница между этим ответом, в котором есть --, и принятым ответом, в котором нет? - person 2rs2ts; 09.10.2014
comment
В git '-' перед списком файлов сообщает git, что все следующие аргументы должны интерпретироваться как имена файлов, а не как имена веток или что-то еще. Иногда это помогает избавиться от неоднозначности. - person foxxtrot; 09.10.2014
comment
'-' - это не только соглашение git, но и то, что вы можете найти в разных местах командной строки * nix. rm -- -f (удалить файл с именем -f) кажется каноническим примером. Подробнее здесь - person Hawkeye Parker; 06.02.2015
comment
Просто добавьте к тому, что сказал @HawkeyeParker, команда rm использует getopt (3) для анализа своих аргументов. getopt - это команда для анализа аргументов команды. gnu.org/software/libc/manual/html_node/Getopt.html < / а> - person Devy; 14.07.2015
comment
@HawkeyeParker, вы имеете в виду, что filename -f ?! Я предполагаю, что это очень редкий случай, верно? - person Honey; 05.04.2017
comment
@foxxtrot Вы сказали, что -- следует интерпретировать как файлы, но после того, как я увидел второй ответ Грега Хьюгилла ниже, я запутался. Он предлагает git checkout -- foo ‹- В его примере foo имя файла? или это просто что-то древовидное? Я имею в виду, что вы не можете оформить заказ на fileName! Это бессмысленно - person Honey; 05.04.2017
comment
@Honey Да, это то, что я имею в виду, и да, наверное, совсем не распространено. Я видел этот пример в разных местах, может быть, просто для того, чтобы он запомнился: rm -f, как известно, страшно / опасно. Но дело в том, что в * nix имя файла может начинаться с '-', и это запутает различные интерпретаторы командной строки, которые, когда они видят '-', ожидают, что после параметра команды будет следовать . Это может быть любой файл, начинающийся с "-"; например, -mySpecialFile. - person Hawkeye Parker; 05.04.2017

git checkout -- foo

Это сбросит foo в HEAD. Вы также можете:

git checkout HEAD^ foo

за одну ревизию назад и т. д.

person Greg Hewgill    schedule 29.08.2008
comment
Я бы предложил использовать синтаксис git checkout -- foo, чтобы избежать ошибок, если foo является чем-то особенным (например, каталог или файл с именем -f). При использовании git, если вы не уверены, всегда ставьте перед всеми файлами и каталогами специальный аргумент --. - person Mikko Rantalainen; 18.03.2013
comment
Дополнительное примечание к комментарию Микко: -- не является командой git и не является специальной для git. Это встроенный в bash, обозначающий конец параметров команды. Вы также можете использовать его со многими другими командами bash. - person matthaeus; 04.03.2016
comment
@matthaeus также не относится ни к bash, ни к функции оболочки. Это соглашение реализовано во многих различных командах (и поддерживается getopt). - person Greg Hewgill; 04.03.2016
comment
Нет, -- не встроенное специальное слово в bash. Но это обычное соглашение, поддерживаемое многими синтаксическими анализаторами командной строки и используемое многими интерфейсами командной строки, включая git. - person Emil Lundberg; 01.09.2019

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

git checkout HEAD file/to/restore
person CDR    schedule 14.01.2012
comment
в чем разница между этим (git checkout HEAD file / to / restore) и git reset --hard file / to / restore ??? - person Motti Shneor; 26.01.2016
comment
1) проще запомнить более общий способ 2) не беспокойтесь нажимать Enter перед вводом имени файла - person Roman Susi; 10.01.2017

Только что у меня была такая же проблема, и я нашел этот ответ проще всего понять (commit-ref - значение SHA изменения в журнале, к которому вы хотите вернуться):

git checkout [commit-ref] [filename]

Это поместит эту старую версию в ваш рабочий каталог, и оттуда вы сможете зафиксировать ее, если хотите.

person bbrown    schedule 27.05.2009
comment
лучший ответ на данный момент - person majurageerthan; 18.02.2021

Если вы знаете, сколько коммитов вам нужно вернуться, вы можете использовать:

git checkout master~5 image.png

Предполагается, что вы находитесь в ветке master, и вам нужна версия 5, которая возвращается.

person Ron DeVera    schedule 07.04.2009

Думаю, я нашел его .... из http://www-cs-students.stanford.edu/~blynn/gitmagic/ch02.html

Иногда вы просто хотите вернуться и забыть обо всех изменениях после определенного момента, потому что все они ошибочны.

Начнем с:

$ git log

который показывает вам список недавних коммитов и их хэши SHA1.

Затем введите:

$ git reset --hard SHA1_HASH

для восстановления состояния данного коммита и окончательного удаления всех новых коммитов из записи.

person jdee    schedule 17.12.2008
comment
Git никогда ничего не удаляет. Ваши старые коммиты все еще там, но если на них нет кончика ветки, они больше недоступны. git reflog будет показывать их, пока вы не очистите репозиторий с помощью git-gc. - person Bombe; 17.12.2008
comment
@Bombe: Спасибо за информацию. Я проверил старую версию файла. Прочитав ваш комментарий, я смог использовать gitref для поиска частичного хэша SHA1 и использовать checkout, чтобы вернуться к самой последней версии. Другие пользователи git могут найти эту информацию полезной. - person Winston C. Yang; 19.05.2010
comment
возможно, за которым следует git push --force - person bshirley; 19.04.2012
comment
Если после приведенного выше git reset --hard SHA1_HASH вы выполняете git status и видите файлы без отслеживания, и вы тоже хотите избавиться от них. Запустите git clean --force -d - person aerobiotic; 23.04.2012
comment
Если у вас есть незафиксированные изменения, вы потеряете их, если выполните git reset --hard - person Boklucius; 24.04.2012
comment
я нашел эту статью, которая помогла мне решить эту проблему: blogs.gnome.org/diegoe/2009/03/18/, похоже, он отлично работает и очень похож на этот конкретный ответ. - person hellatan; 02.05.2012
comment
Разве это не сбрасывает ВСЕ файлы? Не только конкретный файл? - person aidan; 08.01.2014
comment
@Bombe - Git ничего не удаляет. Ваши старые коммиты все еще там, но если на них не указывает ветка, они больше недоступны. - но такие коммиты удаляются через определенное время, поэтому Git никогда ничего не удаляет. Это неверно. - person Bulwersator; 29.04.2014
comment
@Bombe: git reflog will still show them until you clean your repository with git-gc - неправильно. Reflog также является ссылкой, и указанные коммиты никогда не будут удалены git-gc. Если вам нужно почистить их прямо сейчас, вы должны сделать git reflog expire --expire-unreachable=now --all - person Nick Volynkin; 26.06.2016
comment
@NickVolynkin Ваша информация неверна; git gc иногда удаляет коммиты из журнала ссылок. Как говорится на git-gc странице руководства, переменные конфигурации gc.reflogExpire и gc.reflogExpireUnreachable устанавливают возрастные пороги для удаления из журнала ссылок. Записи старше этих значений будут удалены при запуске git gc. Значения по умолчанию равны 90 дням и 30 дням для достижимых и недоступных коммитов. - person Rory O'Kane; 19.06.2017

Это сработало для меня:

git checkout <commit hash> file

Затем зафиксируйте изменение:

git commit -a
person v2k    schedule 25.08.2011

Будьте осторожны, когда говорите «откат». Если раньше у вас была одна версия файла в фиксации $ A, а затем вы внесли два изменения в две отдельные фиксации $ B и $ C (так что вы видите третью итерацию файла), и если вы скажете " Я хочу вернуться к первому ", ты правда это имеешь ввиду?

Если вы хотите избавиться от изменений как второй, так и третьей итерации, это очень просто:

$ git checkout $A file

а затем вы фиксируете результат. Команда спрашивает: «Я хочу извлечь файл из состояния, записанного фиксацией $ A».

С другой стороны, вы имели в виду избавиться от изменения, внесенного второй итерацией (то есть фиксации $ B), сохраняя при этом то, что фиксация $ C сделала с файлом, вы бы захотели вернуть $ B

$ git revert $B

Обратите внимание, что тот, кто создал коммит $ B, возможно, не был очень дисциплинирован и, возможно, совершил совершенно несвязанное изменение в том же коммите, и этот откат может коснуться файлов, отличных от file, вы видите оскорбительные изменения, поэтому вы можете захотеть после этого внимательно проверьте результат.

person Community    schedule 11.01.2009
comment
Я сделал это, но тогда в файле журнала git будет сказано, что я был в исходной фиксации, HEAD. Казалось, что git checkout не работает. Однако статус git показал, что файл действительно был изменен, а файл git diff --staged покажет фактические изменения. Кроме того, статус git показал, что файл также изменился. Так что не используйте здесь git log, чтобы отслеживать, какие файлы были изменены. - person Frederick Ollinger; 08.06.2018
comment
@FrederickOllinger - такое поведение имеет смысл, потому что git log показывает совершает, а вы не зафиксировали изменение (возврат). Если вы сделаете git commit после этого возврата, тогда git log отобразит изменение. - person ToolmakerSteve; 10.01.2021

Начиная с git v2.23.0 существует новый метод git restore, который предполагается предположить часть того, за что git checkout был ответственен (даже в принятом ответе упоминается, что git checkout довольно сбивает с толку). См. Основные изменения в блоге github.

По умолчанию эта команда восстанавливает состояние рабочего дерева с помощью содержимого, поступающего из параметра source (который в вашем случае будет хешем фиксации).

Итак, основываясь на ответе Грега Хьюгилла (при условии, что хеш фиксации равен c5f567), команда будет выглядеть так:

git restore --source=c5f567 file1/to/restore file2/to/restore

Или, если вы хотите восстановить содержимое одной фиксации до c5f567:

git restore --source=c5f567~1 file1/to/restore file2/to/restore
person mjarosie    schedule 27.08.2019
comment
Я полагаю, что это мертвая нить, но это правильный современный ответ. - person Dan; 11.04.2021

Забавно, но git checkout foo не будет работать, если рабочая копия находится в каталоге с именем foo; однако и git checkout HEAD foo, и git checkout ./foo будут:

$ pwd
/Users/aaron/Documents/work/foo
$ git checkout foo
D   foo
Already on "foo"
$ git checkout ./foo
$ git checkout HEAD foo
person Aaron Maenpaa    schedule 29.08.2008

Вот как работает rebase:

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

Предположим, у вас есть

---o----o----o----o  master
    \---A----B       <my branch>

Первые две команды ... commit git checkout git rebase master

... проверьте ветку изменений, которые вы хотите применить к ветке master. Команда rebase берет коммиты из <my branch> (которых нет в master) и повторно применяет их к заголовку master. Другими словами, родительский элемент первой фиксации в <my branch> больше не является предыдущей фиксацией в истории master, а является текущим заголовком master. Две команды такие же, как:

git rebase master <my branch>

Возможно, будет проще запомнить эту команду, поскольку обе ветви - «base» и «modify» являются явными.

. Окончательный результат истории:

---o----o----o----o   master
                   \----A'----B'  <my branch>

Последние две команды ...

git checkout master
git merge <my branch>

... выполните быстрое слияние, чтобы применить все <my branch> изменения к master. Без этого шага фиксация перебазирования не добавляется в master. Конечный результат:

---o----o----o----o----A'----B'  master, <my branch>

master и <my branch> ссылаются на B'. Кроме того, с этого момента можно безопасно удалить ссылку <my branch>.

git branch -d <my branch>
person cmcginty    schedule 24.02.2009

  1. Git вернуть файл к определенной фиксации
git checkout Last_Stable_commit_Number -- fileName

2.Git вернуть файл в определенную ветку

git checkout branchName_Which_Has_stable_Commit fileName
person ireshika piyumalie    schedule 06.02.2019

Первый сброс заголовка для целевого файла

git reset HEAD path_to_file

Вторая выписка из этого файла

git checkout -- path_to_file
person Gulshan Maurya    schedule 04.04.2017
comment
+1, хотя не уверен в намерении сбросить HEAD. Это может понадобиться, а может и не понадобиться. В моей ситуации я хотел только вернуть один конкретный файл к версии в репозитории (что позволило сохранить оставшиеся локальные изменения нетронутыми. Для меня было достаточно выполнить второй шаг выше. - person fkl; 20.01.2018
comment
Да, мне нужно запустить только вторую команду. Нравится - ›shellhacks.com/git-revert-file-to -предыдущая-фиксация - person javaPlease42; 30.05.2019

В случае, если вы хотите вернуть файл к предыдущей фиксации (и файл, который вы хотите вернуть, уже зафиксирован), вы можете использовать

git checkout HEAD^1 path/to/file

or

git checkout HEAD~1 path/to/file

Затем просто подготовьте и зафиксируйте «новую» версию.

Вооружившись знанием того, что у коммита может быть два родителя в случае слияния, вы должны знать, что HEAD ^ 1 является первым родителем, а HEAD ~ 1 - вторым родителем.

Любой из них будет работать, если в дереве только один родитель.

person ModernIncantations    schedule 11.01.2014

На помощь приходят git-aliases, awk и shell-функции!

git prevision <N> <filename>

где <N> - это количество ревизий файла, откат для файла <filename>.
Например, чтобы проверить непосредственно предыдущую ревизию отдельного файла x/y/z.c, запустите

git prevision -1 x/y/z.c

Как работает git prevision?

Добавьте следующее в свой gitconfig

[alias]
        prevision = "!f() { git checkout `git log --oneline $2 |  awk -v commit="$1" 'FNR == -commit+1 {print $1}'` $2;} ;f"

Команда в основном

  • выполняет git log в указанном файле и
  • выбирает соответствующий идентификатор фиксации в истории файла и
  • выполняет git checkout для идентификатора фиксации для указанного файла.

По сути, все, что можно было бы сделать в этой ситуации вручную,
заключено в один красивый и эффективный git-псевдоним - git-prevision

person TheCodeArtist    schedule 01.05.2015

Здесь много предложений, большинство из которых соответствует git checkout $revision -- $file. Пара малоизвестных альтернатив:

git show $revision:$file > $file

Кроме того, я часто использую это, чтобы временно увидеть определенную версию:

git show $revision:$file

or

git show $revision:$file | vim -R -

(OBS: $file должен иметь префикс ./, если это относительный путь для работы git show $revision:$file)

И что еще более странно:

git archive $revision $file | tar -x0 > $file
person Peter V. Mørch    schedule 07.01.2016
comment
Это хорошая альтернатива, если вы не уверены, какую версию фиксации хотите, и вам нужно посмотреть, не перезаписывая свой рабочий каталог. - person wisbucky; 17.02.2018

Мне нужно подключить сюда EasyGit, который является оболочкой, чтобы сделать git более доступным для новичков без сбивают с толку опытных пользователей. Одна из задач - придать _1 _ . В этом случае вы просто скажете:

eg revert foo/bar foo/baz

person Aristotle Pagaltzis    schedule 19.10.2008
comment
Это должно быть eg revert --in REVISON -- FILENAME. --in важен. Для пользователей Windows: откройте git bash. Выполнить echo %PATH. Первый путь должен быть в вашем пользовательском каталоге, заканчивающемся на bin. Создайте этот путь. Сохраните например там. Назовите его eg. Не eg.txt. - person koppor; 02.12.2016

Однако обратите внимание, что git checkout ./foo и git checkout HEAD ./foo - это не в точности одно и то же; Дело в точке:

$ echo A > foo
$ git add foo
$ git commit -m 'A' foo
Created commit a1f085f: A
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 foo
$ echo B >> foo
$ git add foo
$ echo C >> foo
$ cat foo
A
B
C
$ git checkout ./foo
$ cat foo
A
B
$ git checkout HEAD ./foo
$ cat foo
A

(Второй add помещает файл в индекс, но не фиксируется.)

Git checkout ./foo означает возврат пути ./foo из индекса; добавление HEAD указывает Git перед тем, как сделать это, вернуть этот путь в индексе к его версии HEAD.

person Damien Diederen    schedule 31.08.2008

Мне ни один ответ не казался действительно ясным, и поэтому я хотел бы добавить свой, который кажется очень простым.

У меня есть фиксация abc1, и после нее я сделал несколько (или одну модификацию) файла file.txt.

Теперь предположим, что я что-то испортил в файле file.txt и хочу вернуться к предыдущей фиксации abc1.

1.git checkout file.txt: это удалит локальные изменения, если они вам не нужны

2.git checkout abc1 file.txt: это вернет ваш файл к вашей требуемой версии.

3.git commit -m "Restored file.txt to version abc1": это зафиксирует ваш возврат.

  1. git push: это отправит все в удаленный репозиторий

Между шагами 2 и 3, конечно, вы можете сделать git status, чтобы понять, что происходит. Обычно вы должны видеть, что file.txt уже добавлен, поэтому нет необходимости в git add.

person desmond13    schedule 22.03.2017
comment
Хорошо, поэтому я предполагаю, что шаги 1 и 2 являются взаимоисключающими: если abc1 - ваша последняя фиксация, нет необходимости в 2, и если были другие фиксации после abc1, вы можете напрямую выполнить 2. - person Jean Paul; 15.11.2017

Во многих ответах здесь говорится об использовании git reset ... <file> или git checkout ... <file>, но при этом вы потеряете все изменения в <file>, совершенные после фиксации, которую хотите отменить.

Если вы хотите отменить изменения из одной фиксации только в одном файле, как это сделал бы git revert, но только для одного файла (или, скажем, подмножества файлов фиксации), я предлагаю использовать как git diff, так и git apply<sha> = хеш фиксации, которую вы хотите отменить):

git diff <sha>^ <sha> path/to/file.ext | git apply -R

По сути, он сначала сгенерирует патч, соответствующий изменениям, которые вы хотите отменить, а затем применит патч в обратном порядке, чтобы отменить эти изменения.

Конечно, это не сработает, если возвращенные строки были изменены какой-либо фиксацией между <sha1> и HEAD (конфликт).

person Vince    schedule 07.12.2016
comment
Это должен быть утвержденный ответ. Могу я предложить немного упрощенную версию: git show -p <sha> path/to/file.ext|git apply -R - person Amaury D; 19.09.2019
comment
вы можете использовать <sha>^! вместо <sha>^ <sha> - person cambunctious; 10.12.2019

Чтобы перейти к предыдущей версии файла фиксации, получите номер фиксации, скажем, eb917a1, затем

git checkout eb917a1 YourFileName

Если вам просто нужно вернуться к последней зафиксированной версии

git reset HEAD YourFileName
git checkout YourFileName

Это просто приведет вас к последнему зафиксированному состоянию файла.

person shah1988    schedule 25.02.2014

Это очень простой шаг. Извлечь файл с идентификатором фиксации, который мы хотим, здесь один идентификатор фиксации раньше, а затем просто git commit исправление, и все готово.

# git checkout <previous commit_id> <file_name>
# git commit --amend

Это очень удобно. Если мы хотим перенести какой-либо файл с любым предыдущим идентификатором фиксации в верхней части фиксации, мы можем легко это сделать.

person Abhishek Dwivedi    schedule 24.01.2019
comment
Спасибо, Абхишек. Основываясь на вашем ответе, я сделал этот Shellscipt: gist.github.com/ivanleoncz/c200338c03e3d03e4e3e05e3e03e3e05e6e05eb бесплатно улучшать :). - person ivanleoncz; 22.07.2020

git checkout ref | commitHash - путь к файлу

e.g.

git checkout HEAD~5 -- foo.bar
or 
git checkout 048ee28 -- foo.bar
person Amos Folarin    schedule 26.09.2013

Используйте git log, чтобы получить хеш-ключ для конкретной версии, а затем используйте git checkout <hashkey>

Примечание: не забудьте ввести хеш перед последним. Последний хеш указывает на вашу текущую позицию (HEAD) и ничего не меняет.

person mustafakyr    schedule 05.12.2011

Очевидно, кому-то нужно либо написать внятную книгу по git, либо git нужно лучше объяснить в документации. Столкнувшись с той же проблемой, я догадался, что

cd <working copy>
git revert master

отменит последнюю фиксацию, которая, как казалось, была сделана.

Ян

person Ian Davis    schedule 16.12.2011

Это можно сделать за 4 шага:

  1. отменить всю фиксацию с файлом, который вы хотите специально отменить - он создаст новую фиксацию в вашей ветке
  2. soft reset that commit - удаляет фиксацию и перемещает изменения в рабочую область
  3. выберите файлы для восстановления и зафиксируйте их
  4. перетащите все остальные файлы в рабочую область

Что вам нужно ввести в свой терминал:

  1. git revert <commit_hash>
  2. git reset HEAD~1
  3. git add <file_i_want_to_revert> && git commit -m 'reverting file'
  4. git checkout .

удачи

person Nir M.    schedule 08.05.2018
comment
разве это не отменяет ВСЕ изменения? - person arcee123; 29.10.2018
comment
@ arcee123 Да, но последующий сброс отменяет возврат всех изменений. Проблема в том, что git-revert работает только со всем репо, поэтому для компенсации нам приходится отменять все остальное. - person Timothy; 06.02.2019
comment
Я рекомендую использовать: 1. git revert --no-commit <commit_hash> 2. git reset HEAD Это избавляет от лишних коммитов и делает все изменения только в вашем рабочем каталоге. - person Timothy; 06.02.2019
comment
Ответ @ greg-hewgill лучше и точнее. Этот паршивый и не должен использоваться. - person Daniel Tranca; 28.02.2019
comment
Это именно то, что нужно для истинного восстановления определенных файлов. Мне нужно было отменить изменения в нескольких файлах из более ранней фиксации, которые уже были отправлены в удаленный репозиторий. Я вернул, сбросил и зафиксировал результат: git revert _oldcommit_ --no-commit git reset -- _unchanged1_ _unchanged2_ ... git commit -m "branch without changes to specific files" В новой подсказке ветки отражены все изменения, кроме возвращенных файлов. - person Suncat2000; 21.03.2019
comment
@DanielTranca Ответ Грега Хьюгилла не лучше, если вы хотите отменить изменения. Могут быть промежуточные коммиты, которые изменили другие части файлов. Ответ Нира М. касается возврата только того, что было изменено в определенных файлах за один коммит; это лучший ответ на возврат, который я подтвердил, придя к аналогичным шагам самостоятельно. - person Suncat2000; 21.03.2019

git revert <hash>

Отменит данную фиксацию. Похоже, вы думаете, что git revert влияет только на самую последнюю фиксацию.

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

person Otto    schedule 17.12.2008

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

  1. дерево с открытым исходным кодом, измените этот коммит

дерево с открытым исходным кодом

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

введите описание изображения здесь

  1. вы можете увидеть список ваших изменений в этом коммите  список файлов в дереве исходных текстов
  2. выберите его, а затем нажмите ... кнопки с правой стороны ... нажмите обратный файл
  3. затем вы можете увидеть его на вкладке состояния файла в левом нижнем углу, затем нажмите «Отключить»:

вкладка состояния файла

  1. откройте код своей визуальной студии и вернитесь назад, зафиксировав удаленные файлы
  2. после всего этого вы можете увидеть результаты своего последнего коммита в дереве исходных кодов

введите описание изображения здесь

person saber tabatabaee yazdi    schedule 23.08.2018

Вот мой путь.

а) В Android Studio откройте файл.

б) git -> Показать историю, найдите предыдущую фиксацию, к которой я хочу вернуться. Получите commit_id (т.е. хеш фиксации).

c) git checkout commit_id file_path

person Francis Bacon    schedule 13.03.2017
comment
Ваш путь в точности совпадает с принятым ответом. - person Uwe Allner; 13.03.2017

Если вы используете Git Extensions и хотите вернуться только к родительской фиксации для файла, вы можете выбрать фиксацию, содержащую изменения, которые вы хотите отменить, затем выберите вкладку «Diff» на панели сведений, щелкните правой кнопкой мыши файл, который вы хотите восстановить, затем "Сбросить файл (ы) на" ...., затем "A" (родительский)

person Chris Halcrow    schedule 26.09.2017

  • Выполните следующую команду, которая выполняет мягкий сброс, и изменения поступают на ваш локальный компьютер.
git reset --soft HEAD^1
  • Просматривайте статус ранее зафиксированных файлов, который поступает на ваш локальный компьютер, а затем вносите изменения.
 git status
  • Зафиксируйте и отправьте файл после внесения изменений.

  • Предыдущая история фиксации неверно зафиксированных файлов не будет отображаться

person Dev-lop-er    schedule 15.04.2021