Хард ресет одного файла

1006

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

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

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

Эмилиано
источник
3
git checkoutниже ответ. В git «возврат» - это то, что вы делаете с коммитом. «Revert» воспроизводит обратную запись исторического коммита в ваш рабочий каталог, так что вы можете сделать новый коммит, который «отменяет» аннулированный коммит. Я нахожу, что это частая путаница для людей, которые приходят в Git из SVN.
Дэн Рэй
Если вас интересует, почему вы не можете сделать полный сброс с путями, посмотрите мой ответ там .
пользователь
Этот вопрос предполагает, что каждый знает, что такое Hard reset.

Ответы:

1811

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

git checkout HEAD -- my-file.txt

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

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

Марк Лонгэйр
источник
58
Более полный ответ. +1;) Относительно '-' см. Также stackoverflow.com/questions/6561142/… (и, в более общем смысле, stackoverflow.com/questions/1192180/… )
VonC
8
Кроме того, не забудьте, что вы можете ссылаться на предыдущий коммит, HEAD~1чтобы указать предпоследний коммит.
Ryanmt
14
Вы можете выйти, HEADесли вы возглавляете текущую ветку - см. Norbauer.com/rails-consulting/notes/…
cxw
4
Любое понимание, почему resetкоманда (как она говорит) «не может сделать полный сброс с путями», а затем, почему checkoutкоманда не используется (не может быть?) Для жесткого сброса всего набора? (Я имею в виду, почему это было разработано так.)
Sz.
1
@cxw К сожалению, это не совсем так. Со страницы руководства git checkout: «Перезаписать пути в рабочем дереве, заменив их содержимым в индексе или в <tree-ish>». Т.е. если <tree-ish>он опущен, то любой контент в индексе будет использоваться для обновления рабочего дерева. Это может или не может отличаться от HEAD.
tuntap
137

Сброс к голове:

Для полной перезагрузки одного файла в HEAD:

git checkout @ -- myfile.ext

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

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

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

git checkout -- myfile.ext

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

Акаменус
источник
1
Что случилось с "-" перед myfile.ext?
Лэнс Кинд
3
@LanceKind Как я понимаю, это используется для разграничения списка имен файлов, который следует за ним. Без этого бывают случаи, когда git неправильно интерпретирует аргументы.
Acumenus
2
Не только имена файлов. Широко используемое соглашение отделяет опции от позиционных аргументов во многих утилитах. Смотрите man bashстраницу. Также упоминается в этом ответе: unix.stackexchange.com/a/187548/142855
boweeb
1
Условно, --используется, чтобы сказать программе I've finished specifying "options", and from here on, everything will be a positional argument.. Условно «опции» - это токены, --recursiveкоторые могут появляться в любом порядке или даже объединяться в краткой форме, например, с rm -rf. Напротив, «позиционные аргументы» гораздо больше похожи на аргументы, передаваемые функции в языке программирования: их позиция в списке токенов определяет, что именно программа собирается с ними делать (это часто имена файлов). --устраняет двусмысленность относительно того, что есть что.
ионосферные
42

Чтобы вернуться в upstream / master, сделайте:

git checkout upstream/master -- myfile.txt
Энн Райхо
источник
19

Начиная с Git 2.23 (август 2019) вы можете использовать restore( больше информации ):

git restore pathTo/MyFile

Выше будет восстановить MyFileнаHEAD (последней фиксации) на текущей ветке.

Если вы хотите получить изменения от другого коммита, вы можете вернуться назад в историю коммитов. Команда ниже получит MyFileдва коммита, предшествующие последнему. Теперь вам нужна опция -s( --source), так как теперь вы используете, master~2а не master(по умолчанию) при восстановлении источника:

git restore -s master~2 pathTo/MyFile

Вы также можете получить файл из другой ветки!

git restore -s my-feature-branch pathTo/MyFile
AxeEffect
источник
1
Самый простой способ до сих пор. К сожалению, этот ответ не получает достаточного внимания.
сингрий
5

Ссылка на ГОЛОВУ не обязательна.

git checkout -- file.js достаточно

Эмануэль Фридрих
источник
4

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

git checkout HEAD -- path_to_file/file_name

Список всех измененных файлов, чтобы получить path_to_file/filenameс помощью команды ниже

git status
HariKishore
источник
1

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

git reset -- my-file.txt

который обновит обе рабочие копии my-file.txtпри добавлении.

ADDYQU
источник
Не изменяет содержимое измененного файла, как требуется.
Рафаэль
Когда вы добавляете в тайник Вы редактировали файл?
ADDYQU,
1
Не в этом суть @ADDQU. Вопрос в том, как «жестко перезагрузить» файл, чтобы не удалять его из поэтапного списка.
Рафаэль
@Rafael Вы правы, но я хочу, чтобы вы знали, что есть способ.
ADDYQU
0

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

git checkout filename

Если у вас есть ветка с тем же именем файла, вы должны использовать эту команду:

git checkout -- filename
Милад Рахими
источник
1
Это не приведет к «жесткому сбросу» файла - оно только копирует состояние индекса в рабочее дерево. «Жесткий сброс» сначала сбрасывает индекс.
AH
-21

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

  1. Просмотр журнала вашего файла

    git log myFile.js

    commit 1023057173029091u23f01w276931f7f42595f84f Автор: kmiklas Дата: вторник, 7 августа 09:29:34 2018 -0400

    JIRA-12345 - Рефакторинг с новой архитектурой.

  2. Примечание хеш файла:

    1023057173029091u23f01w276931f7f42595f84f

  3. Показать файл, используя хэш. Убедитесь, что это то, что вы хотите:

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js

  4. Перенаправить файл в локальную копию

    git show 1023057173029091u23f01w276931f7f42595f84f: ./ myFile.js> myFile.07aug2018.js

  5. Сделайте резервную копию вашего текущего файла.

    cp myFile.js myFile.bak.js

  6. Откройте оба файла в вашем любимом текстовом редакторе.

    vim myFile.js
    vim myFile.07aug2018.js

  7. Скопируйте и вставьте код из myFile.07aug2018.js в myFile.js и сохраните.

  8. Подтвердите и нажмите myFile.js

  9. Снова просмотрите журнал и убедитесь, что ваш файл правильно на месте.

  10. Скажите своим клиентам, чтобы они брали последнюю версию, с удовольствием наблюдаем, как она работает со старой версией на месте.

Не самое сексуальное или наиболее мерзкое решение, и определенно «ручной» сброс / возврат, но это работает. Это требует минимального знания git и не нарушает историю коммитов.

kmiklas
источник
2
Этот ответ гораздо более сложен и подвержен ошибкам, чем любое из решений, которые предшествуют ему годами.
Artif3x
2
Зачем кому-то использовать это решение? истинный ответ - только простая команда.
Милад Рахими
1
Это оптимальное решение для определенных обстоятельств. Это имеет смысл для тех, кто в безвыходном положении, где git работает со сбоями, и для тех, кто нуждается в обходном пути.
kmiklas