Unstage удаленный файл в Git

504

Обычно, чтобы отменить изменения в файле, вы должны сделать:

git checkout -- <file>

Что если изменение, которое я хочу отменить, удаляет файл? Приведенная выше строка выдаст ошибку:

error: pathspec '<file>' did not match any file(s) known to git.

Какая команда восстановит этот файл без отмены других изменений?

Бонус: также, что если изменение, которое я хочу отменить, добавит файл? Я хотел бы также узнать, как это изменить.

lurscher
источник
1
Отказ от изменений и unstaging - это две разные вещи, которые вы пытаетесь сделать?
Эндрю Маршалл
1
Это два разных вопроса и проблемы в одном посте. Это делает ответы слишком много и излишне запутанным.
Давид Сопко

Ответы:

779

Предполагая, что вы хотите отменить эффекты git rm <file>или rm <file>последующие git add -Aили что-то подобное:

# this restores the file status in the index
git reset -- <file>
# then check out a copy from the index
git checkout -- <file>

Для отмены git add <file>достаточно первой строки выше, если вы еще не подтвердили.

twalberg
источник
70
Это --ключ. git reset <file>не работает, что и привело меня сюда.
2
Почему end-of-options-markerтребуется только в случае удаленного файла?
haridsv
5
@handsv Это строго не требуется (вы можете сделать это по-другому git reset HEAD <file>, что эквивалентно), но git resetобрабатывает свой первый аргумент перед end-of-options-markerименем ref, а не именем файла. Может ли это быть написано более гибко? Вероятно. Почему не так? Наверное, только разработчики знают наверняка.
Твальберг
2
@twalberg git reset filenameотлично работает для не удаленных файлов.
Брайан Гордон
1
@AaronMahan - не могли бы вы объяснить разницу между git reset <file>и git reset -- <file>. Мне трудно найти ответ на этот вопрос в Google.
Neeraj B.
56

На оба вопроса дан ответ git status.

Чтобы отключить добавление нового файла, используйте git rm --cached filename.ext

# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   test

Чтобы удалить удаление файла, используйте git reset HEAD filename.ext

# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    test

С другой стороны, git checkout --никогда не бывает нестабильным, он просто отбрасывает не поэтапные изменения.

seppo0010
источник
5
Я не вижу подсказки для удаленного файла в git 1.7.2.5 на Debian.
Трипли
Приятно видеть git statusцитируемое; показывает пользователям способ самопомощи сейчас и в следующий раз, а также в случае добавления или обновления информации в будущих версиях git.
Уилл Каин
Это не верно. «Изменения быть привержен» является то , что вы видите передgit reset тем . Послеgit reset , вы видите «изменился , но не обновляется» , что означает «Изменения не поставлена» на родном языке авторов GIT, по- видимому. Что еще более важно, вся догма о «git status говорит вам все, что вы знаете» - ложь. (Менеджеры, которые говорят, что тратят время людей и должны быть уволены.)
personal_cloud
11

Ответы на два ваших вопроса связаны между собой. Начну со второго:

После того, как вы подготовили файл (часто с помощью git add, хотя некоторые другие команды также неявно вносят изменения, например git rm), вы можете отменить это изменение с помощью git reset -- <file>.

В вашем случае вы должны были использовать git rmдля удаления файла, что эквивалентно простому удалению его с rmпоследующим внесением этого изменения. Если вы сначала отключили его, git reset -- <file>вы можете восстановить его с помощью git checkout -- <file>.

Бен Джексон
источник
7

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

git reset COMMIT_HASH file_path
git checkout COMMIT_HASH file_path
git add file_path

Это будет работать для удаления, которое произошло несколькими коммитами предыдущего.

michaeldever
источник
1
Это более эффективноgit revert COMMIT_HASH
Flair
2

Начиная с git v2.23 , у вас есть другая опция:

git restore --staged -- <file>

Kreempuff
источник