Отменить рабочую копию изменений одного файла в Git?
После последнего коммита я изменил кучу файлов в моей рабочей копии, но я хочу отменить изменения одного из этих файлов, как при сбросе его в то же состояние, что и у самого последнего коммита.
Однако я хочу только отменить изменения рабочей копии только одного этого файла, и ничего больше с ним.
Как я могу это сделать?
15 ответов
Ты можешь использовать
git checkout -- file
Вы можете сделать это без --
(как предполагает nimrodm), но если имя файла выглядит как ветка или тег (или другой идентификатор ревизии), оно может запутаться, поэтому использование --
лучший.
Вы также можете проверить конкретную версию файла:
git checkout v1.2.3 -- file # tag v1.2.3
git checkout stable -- file # stable branch
git checkout origin/master -- file # upstream master
git checkout HEAD -- file # the version from the most recent commit
git checkout HEAD^ -- file # the version before the most recent commit
Просто используйте
git checkout filename
Это заменит имя файла последней версией из текущей ветви.
ВНИМАНИЕ: ваши изменения будут отменены - резервная копия не сохраняется.
git checkout <commit> <filename>
Я использовал это сегодня, потому что я понял, что мой favicon был перезаписан несколько коммитов назад, когда я обновился до drupal 6.10, поэтому мне пришлось вернуть его. Вот что я сделал:
git checkout 088ecd favicon.ico
Если ваш файл уже подготовлен (происходит, когда вы делаете git add и т. Д. После того, как файл отредактирован), чтобы отменить изменения.
использование
git reset HEAD <file>
затем
git checkout <file>
Если еще не постановили, просто используйте
git checkout <file>
Я сделал через git bash:
(use "git checkout -- <file>..." to discard changes in working directory)
- Git статус. [Итак, мы видели один файл, модифицированный.]
- git checkout - index.html [я изменился в файле index.html:
- git status [теперь эти изменения были удалены]
Git 2.23 представил, чтобы сделать именно это, я думаю, в попытке дать простой ответ на подобные вопросы.
git restore [--] <pathspec>...
Как всегда,
--
может понадобиться, но когда имя файла начинается с тире. (Путаница с названием ветки здесь невозможна, так как периметр не включает ветки, в отличие от do-all
checkout
)
Чтобы быть полным,
restore
также может восстанавливать поэтапные файлы с
--staged
, и восстановить из фиксации, отличной от
HEAD
с участием
--source=<tree>
.
Если вы хотите просто отменить изменения предыдущего коммита в этом одном файле, вы можете попробовать это:
git checkout branchname^ filename
Это извлечет файл таким, каким он был до последнего коммита. Если вы хотите вернуться еще на несколько коммитов, используйте branchname~n
нотации.
Этот ответ предназначен для команды, необходимой для отмены локальных изменений, которые находятся в нескольких конкретных файлах в одной или нескольких папках (или каталогах). Этот ответ, в частности, отвечает на вопрос, где у пользователя более одного файла, но он не хочет отменять все локальные изменения:
если у вас есть один или несколько файлов, вы можете применить команду samne (
git checkout -- file
) к каждому из этих файлов, перечислив каждое их местоположение, разделенное пробелом, как в:
git checkout -- name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext
обратите внимание на расстояние между name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext
Для нескольких файлов в одной папке:
Если вам нужно отменить изменения для всех файлов в определенном каталоге, используйте git checkout следующим образом:
git checkout -- name1/name2/*
Звездочка, указанная выше, выполняет процедуру удаления всех файлов в этом месте с именем name /name2.
И, аналогично, следующее может отменить изменения во всех файлах для нескольких папок:
git checkout -- name1/name2/* nameA/subFolder/*
снова обратите внимание на пробел между name1/name2/* nameA/subFolder/* в приведенном выше.
Примечание: name1, name2, nameA, subFolder - все эти примеры имен папок указывают папку или пакет, где могут находиться рассматриваемые файлы.
Я всегда путаюсь с этим, поэтому вот контрольный пример с напоминанием; скажем, у нас есть это bash
скрипт для тестирования git
:
set -x
rm -rf test
mkdir test
cd test
git init
git config user.name test
git config user.email test@test.com
echo 1 > a.txt
echo 1 > b.txt
git add *
git commit -m "initial commit"
echo 2 >> b.txt
git add b.txt
git commit -m "second commit"
echo 3 >> b.txt
На данный момент изменение не происходит в кэше, поэтому git status
является:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
Если с этого момента, мы делаем git checkout
, результат такой:
$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean
Если вместо этого мы делаем git reset
результат:
$ git reset HEAD -- b.txt
Unstaged changes after reset:
M b.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
Итак, в этом случае - если изменения не поставлены, git reset
не имеет значения, в то время как git checkout
переписывает изменения.
Теперь предположим, что последнее изменение из приведенного выше сценария является поэтапным / кэшированным, то есть мы также сделали git add b.txt
в конце.
В этом случае, git status
на данный момент это:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: b.txt
Если с этого момента, мы делаем git checkout
, результат такой:
$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean
Если вместо этого мы делаем git reset
результат:
$ git reset HEAD -- b.txt
Unstaged changes after reset:
M b.txt
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: b.txt
no changes added to commit (use "git add" and/or "git commit -a")
Итак, в этом случае - если изменения поставлены, git reset
будет в основном делать поэтапные изменения в не поэтапные изменения - в то время как git checkout
перезапишет изменения полностью.
Я восстанавливаю свои файлы, используя идентификатор SHA, что я делаю git checkout <sha hash id> <file name>
git восстановить файл
Посмотрите этот повторяющийся ответ (обязательно прокрутите вниз до обновления 2020 года): /questions/10868112/kak-otmenit-lokalnyie-izmeneniya-v-konkretnom-fajle/10868116#10868116
Если вы еще не отправили или не поделились своим коммитом:
git diff --stat HEAD^...HEAD | \
fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ --
git commit -a --amend
Если он уже зафиксирован, вы можете отменить изменение для файла и зафиксировать снова, а затем заменить новый коммит последним.