Как восстановить файл

Обновлено: 02.07.2024

Команды git reset , git checkout и git revert — одни из самых полезных инструментов в вашем наборе инструментов Git. Все они позволяют отменить какое-либо изменение в вашем репозитории, а первые две команды можно использовать для управления либо коммитами, либо отдельными файлами.

Поскольку они очень похожи, очень легко перепутать, какую команду следует использовать в том или ином сценарии разработки. В этой статье мы сравним наиболее распространенные конфигурации git reset, git checkout и git revert. Надеюсь, вы будете уверенно перемещаться по репозиторию с помощью любой из этих команд.

Каждую команду полезно рассматривать с точки зрения ее влияния на три механизма управления состоянием репозитория Git: рабочий каталог, промежуточный снимок и историю коммитов. Эти компоненты иногда называют «тремя деревьями» Git. Мы подробно изучаем три дерева на странице сброса git. Помните об этих механизмах, когда будете читать эту статью.

Извлечение — это операция, которая перемещает указатель HEAD ref на указанную фиксацию. Чтобы продемонстрировать это, рассмотрим следующий пример.

Переместить указатель HEAD ref на указанную фиксацию

В этом примере показана последовательность коммитов в основной ветке. Ссылка HEAD и ссылка основной ветки в настоящее время указывают на коммит d. Теперь давайте выполним git checkout b

Это обновление дерева "История фиксаций". Команду git checkout можно использовать в области фиксации или на уровне файла. Проверка на уровне файла изменит содержимое файла на содержимое конкретной фиксации.

Откат — это операция, которая берет указанную фиксацию и создает новую фиксацию, которая инвертирует указанную фиксацию. git revert может выполняться только на уровне фиксации и не имеет функций на уровне файлов.

Сброс — это операция, которая берет указанную фиксацию и сбрасывает «три дерева» в соответствии с состоянием репозитория на момент указанной фиксации. Сброс можно вызвать в трех разных режимах, соответствующих трем деревьям.

Checkout и reset обычно используются для локальной или частной отмены действий. Они изменяют историю репозитория, что может вызвать конфликты при отправке в удаленные общие репозитории. Откат считается безопасной операцией для «общедоступных отмен», поскольку она создает новую историю, которой можно поделиться удаленно, и не перезаписывает историю, от которой могут зависеть удаленные члены команды.

Справочник Git Reset, Revert и Checkout

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

< td>Уровень файла
Команда Область Общие варианты использования
git reset Уровень фиксации Отменить коммиты в приватной ветке или удалить незафиксированные изменения
git reset Удалить файл
git checkout Уровень фиксации Переключение между ветки или проверять старые снимки
git checkout На уровне файлов Отменить изменения в рабочем каталоге
git revert Commit-level Отменить коммит в общедоступной ветке
git revert< /td> Уровень файла (Н/Д)

Операции на уровне фиксации

Параметры, которые вы передаете в git reset и git checkout, определяют их область действия. Когда вы не включаете путь к файлу в качестве параметра, они работают со всеми коммитами. Это то, что мы будем исследовать в этом разделе. Обратите внимание, что git revert не имеет аналога на уровне файлов.

Сбросить конкретную фиксацию

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

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

Сброс ветки исправлений до HEAD-2

Это использование git reset — простой способ отменить изменения, которые никому не были переданы. Это ваша команда, когда вы начинаете работать над функцией и ловите себя на мысли: «Вот дерьмо, что я делаю? Я должен просто начать сначала».

Помимо перемещения текущей ветки, вы также можете настроить git reset для изменения промежуточного снимка и/или рабочего каталога, передав ему один из следующих флагов:

  • --soft — промежуточный снимок и рабочий каталог никак не изменяются.
  • --mixed — промежуточный снимок обновляется в соответствии с указанной фиксацией, но рабочий каталог не затрагивается. Это параметр по умолчанию.
  • --hard — промежуточный снимок и рабочий каталог обновляются в соответствии с указанной фиксацией.

Эти режимы проще рассматривать как определяющие область действия операции сброса git. Для получения более подробной информации посетите страницу git reset.

Проверить старые коммиты

Команда git checkout используется для обновления состояния репозитория до определенного момента в истории проектов. При передаче с именем ветки он позволяет переключаться между ветвями.

Внутри все, что делает вышеприведенная команда, — это перемещает HEAD в другую ветку и обновляет рабочий каталог, чтобы он соответствовал. Поскольку это может перезаписать локальные изменения, Git заставляет вас зафиксировать или спрятать любые изменения в рабочем каталоге, которые будут потеряны во время операции извлечения. В отличие от git reset , git checkout не перемещает ветки.

Перенос HEAD с основного на исправление

Вы также можете проверить произвольные коммиты, передав ссылку коммита вместо ветки. Это делает то же самое, что и проверка ветки: она перемещает ссылку HEAD на указанный коммит. Например, следующая команда извлечет прародителя текущего коммита:

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

Отменить общедоступную фиксацию с помощью Revert

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

Это можно представить следующим образом:

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

Вы также можете рассматривать git revert как инструмент для отмены зафиксированных изменений, тогда как git reset HEAD предназначен для отмены незафиксированных изменений.

Как и git checkout , git revert может перезаписать файлы в рабочем каталоге, поэтому вам будет предложено зафиксировать или спрятать изменения, которые будут потеряны во время операции возврата.

Операции на уровне файлов

Команды git reset и git checkout также принимают в качестве параметра необязательный путь к файлу. Это резко меняет их поведение. Вместо того, чтобы работать со снимками целиком, это вынуждает их ограничивать свои операции одним файлом.

Git сбросить определенный файл

При вызове с указанием пути к файлу git reset обновляет поэтапный снимок, чтобы он соответствовал версии указанной фиксации. Например, эта команда извлечет версию foo.py из предпоследнего коммита и подготовит ее для следующего коммита:

Как и в случае с версией git reset на уровне фиксации, она чаще используется с HEAD, а не с произвольной фиксацией. Запуск git reset HEAD foo.py отключит foo.py . Содержащиеся в нем изменения будут по-прежнему присутствовать в рабочем каталоге.

Флаги --soft , --mixed и --hard не влияют на версию git reset на уровне файлов, поскольку промежуточный снимок всегда обновляется, а рабочий каталог никогда не обновляется.

Файл проверки Git

Извлечение файла похоже на использование git reset с путем к файлу, за исключением того, что он обновляет рабочий каталог, а не рабочую область. В отличие от версии этой команды на уровне фиксации, она не перемещает ссылку HEAD, что означает, что вы не будете переключать ветки.

Например, следующая команда заставляет foo.py в рабочем каталоге соответствовать файлу из предпоследней фиксации:

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

Если вы подготовите и зафиксируете извлеченный файл, это приведет к «возврату» к старой версии этого файла. Обратите внимание, что это удаляет все последующие изменения в файле, тогда как команда git revert отменяет только изменения, внесенные указанной фиксацией.

Как и git reset , это обычно используется с HEAD в качестве ссылки на фиксацию. Например, git checkout HEAD foo.py отбрасывает неустановленные изменения в foo.py. Это похоже на git reset HEAD --hard , но работает только с указанным файлом.

Обзор

Теперь у вас должны быть все необходимые инструменты для отмены изменений в репозитории Git. Команды git reset , git checkout и git revert могут сбивать с толку, но когда вы думаете об их влиянии на рабочий каталог, промежуточный снимок и историю коммитов, должно быть легче определить, какая команда подходит для текущей задачи разработки.< /p>

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

Возврат и сброс файла до определенной версии

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

Чтобы сбросить файл до состояния конкретной фиксации, выполните команду git reset:

Вы также можете эффективно использовать команду git checkout:

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

Сброс, откат и получение в Git

Git reset, git revert и git checkout относятся к наиболее эффективным инструментам Git. Самый важный вариант, который они предлагают, — это отмена изменений в репозитории git. Поскольку приведенные выше команды похожи, можно легко запутаться. Давайте посмотрим, как их использовать без путаницы.

Сброс Git

Команда git reset используется для:

  • Возврат всего рабочего дерева в предыдущее зафиксированное состояние. Он отменит фиксации или очистит незафиксированные изменения.
  • Изменение фиксации ветки, на которую указывает HEAD. Он может изменить уже существующую историю коммитов.
  • Для отмены хранения файла.

Вернуться к Git

Эта команда помогает:

  • Отменить зафиксированные изменения;
  • Создайте новую фиксацию, инвертировав определенную фиксацию. Таким образом, он может добавить совершенно новую историю коммитов, но не может изменить уже существующую.
  • Перезаписать файлы, включенные в рабочий каталог.

Оформить заказ через Git

Эта команда используется для:

  • Перемещение указателя HEAD на определенную фиксацию или переключение между разными ветвями;
  • Откат любых изменений содержимого до тех, которые были внесены в конкретную фиксацию;
  • Не вносить изменения в историю коммитов;
  • Перезапись файлов в рабочем каталоге.

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

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

Как программное обеспечение для контроля версий, Git позволяет предсказуемо легко откатывать изменения. Но даже концепция отмены изменений сложнее, чем вы можете подумать. Репозиторий Git — это не совсем то же самое, что набор файлов, над которыми вы работаете локально. Чтобы отменить изменения, нужно подумать, где именно вы хотите их отменить.

git checkout, git reset и git restore — это команды, которые могут помочь вам вернуться к предыдущей версии не только кодовой базы, но и отдельных файлов. Узнайте подробности об этих командах, и вы сразу же будете прыгать по истории файлов, как эксперт.

Что вообще означает сброс файла?

Важно отметить, что сброс файла может означать разные вещи для разных людей в разных обстоятельствах. Кроме того, команда git reset может не соответствовать вашим ожиданиям относительно того, что означает сброс.

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

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

Вы можете рассматривать сброс файла как отмену изменений.Но состояние вашего файла будет определять, какие изменения вы на самом деле отменяете. Очевидный случай: вы вносите какие-то изменения, фиксируете их, а потом решаете, что они вам больше не нужны.

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

Как откатить ранее зафиксированный файл?

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

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

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

Здесь мы передаем определенный путь (путь/к/файлу), который идентифицирует только один файл. Мы также указываем идентификатор коммита, чтобы получить файл в том виде, в котором он существовал в этот конкретный коммит. Эта команда обновит файл только в нашем рабочем дереве.

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

Как изменить то, что я показываю?

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

Вы можете использовать команду git reset, чтобы отменить промежуточный файл:

Можно ли быстро отменить локальные изменения?

Да, вы можете отменить изменения в локальном файле до его подготовки. Используйте следующую команду:

Обратите внимание, что это аналогично откату изменения репозитория, только идентификатор фиксации не указывается. Как только вы выполните эту команду, Git отменит любые изменения в вашей рабочей копии.

А как насчет git restore?

В более поздних версиях Git есть более новая команда: restore. Для простых случаев, которые мы здесь обсуждали, вы можете использовать следующие эквиваленты. Чтобы отменить изменение репозитория:

Чтобы отключить файл, используйте:

Чтобы отменить изменения в рабочей копии:

Освоение возможностей Git по управлению версиями бесценно

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


Бобби — энтузиаст технологий, проработавший разработчиком программного обеспечения почти два десятилетия. В MUO он младший редактор отдела программирования. Он увлечен играми, работает главным редактором журнала Switch Player Magazine и занимается всеми аспектами онлайн-публикаций и веб-разработки.

Подпишитесь на нашу рассылку

Подпишитесь на нашу рассылку, чтобы получать технические советы, обзоры, бесплатные электронные книги и эксклюзивные предложения!

В настоящее время в моем рабочем каталоге есть три измененных файла. Однако я хочу, чтобы один из них был сброшен в статус HEAD.

В SVN я бы использовал svn revert (с последующим обновлением svn, если необходимо), но в Git я должен использовать git reset --hard . Однако эта команда не может работать с одним файлом.

Есть ли в Git способ отменить изменения в одном файле и перезаписать его новой копией HEAD?

git checkout ниже — ответ. В git «возврат» — это то, что вы делаете для коммита. «Revert» воспроизводит обратную историческую фиксацию в вашем рабочем каталоге, поэтому вы можете сделать новую фиксацию, которая «отменяет» отмененную фиксацию. Я считаю, что это частая путаница для людей, переходящих на git из svn.

9 ответов 9

Вы можете использовать следующую команду:

<р>. который обновит как рабочую копию my-file.txt, так и ее состояние в индексе с помощью HEAD.

-- в основном означает: обрабатывать каждый аргумент после этой точки как имя файла. Подробнее в этом ответе. Спасибо VonC за указание на это.

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

Есть понимание, почему команда сброса (как говорится) «не может выполнить полный сброс с путями», а затем почему команда проверки не используется (не может быть?) для жесткого сброса всего набора? (Я имею в виду, почему он был разработан именно так.)

@cxw К сожалению, это не совсем так. На справочной странице git checkout: «Перезаписать пути в рабочем дереве, заменив их содержимым в индексе или в ». т.е. если опущен, любое содержимое индекса будет использоваться для обновления рабочего дерева.Это может отличаться от HEAD, а может и не отличаться.

Сбросить в заголовок:

Чтобы полностью сбросить один файл до HEAD:

Обратите внимание, что @ — это сокращение от HEAD. Старая версия git может не поддерживать краткую форму.

Сбросить до индекса:

Чтобы полностью сбросить один файл до индекса, предполагая, что индекс не пуст, в противном случае до HEAD:

Дело в том, что в целях безопасности вы не должны опускать @ или HEAD в команде, если вы специально не хотите сбросить только индекс.

@LanceKind Насколько я понимаю, это используется для разграничения списка имен файлов, которые следуют за ним. Без него бывают случаи, когда git неправильно интерпретирует аргументы.

Обычно -- используется, чтобы сообщить программе, что я закончил указывать "опции", и с этого момента все будет позиционным аргументом. . Традиционно «опции» — это токены, такие как --recursive, которые могут появляться в любом порядке или даже объединяться вместе в их краткой форме, например, с rm -rf . Напротив, «позиционные аргументы» гораздо больше похожи на аргументы, передаваемые функции в языке программирования: их позиция в списке токенов определяет, что именно программа собирается с ними делать (это часто имена файлов). -- устраняет двусмысленность в отношении того, что есть что.

Это не «жесткий» сброс чего-либо, он просто применяет изменения из некоторой фиксации и требует дополнительной фиксации. Однако при жестком сбросе на уровне ветки ваши изменения просто возвращаются к фиксации, к которой вы хотели сбросить, без какой-либо дополнительной фиксации

Читайте также: