git status показывает изменения, git checkout - <file> не удаляет их


222

Я хотел бы удалить все изменения в моей рабочей копии.
Бег git statusпоказывает измененные файлы.
Ничто, что я делаю, кажется, не удаляет эти модификации.
Например:

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git checkout -- Rhino.Etl.Core/Enumerables/CachingEnumerable.cs

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git checkout `git ls-files -m`

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git reset --hard HEAD
HEAD is now at 6c857e7 boo libraries updated to 2.0.9.2 and rhino.dsl.dll updated.

rbellamy@PROMETHEUS /d/Development/rhino-etl (master)
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   Rhino.Etl.Core/Enumerables/CachingEnumerable.cs
#       modified:   Rhino.Etl.Core/Pipelines/SingleThreadedPipelineExecuter.cs
#       modified:   Rhino.Etl.Tests/Rhino.Etl.Tests.csproj
#       modified:   Rhino.Etl.Tests/SingleThreadedPipelineExecuterTest.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

6
Не уверен, почему здесь git reset --hardне работает. Примечание: следует git checkout -- `git ls-files -m`отменить файлы ( --)
VonC

2
Если вы удалите файлы и используете checkout -- <file>его, должно работать. Обнаружение изменений в некоторых ситуациях немного придирчиво (среди прочих, если присутствует несоответствие CRLF)
eckes


1
@ BuZZ-dEE - это дубликат, и старше, и поэтому будет иметь приоритет. Но хотя вопрос, на который вы ссылаетесь, по сути один и тот же, ответ, который я принял ниже, гораздо более информативен, чем любой из ответов, и решил мою проблему.
rbellamy

не решение, а швейцарский нож для скучного дела: git update-index --assume-unchagedпринудительно изменяет состояние файлов (даже для измененных!)
pdem

Ответы:


126

Есть много проблем, которые могут вызвать это поведение:

Нормализация конца строки

У меня тоже были такие проблемы. Все сводится к тому, что git автоматически конвертирует crlf в lf. Обычно это вызвано смешанным окончанием строки в одном файле. Файл нормализуется в индексе, но когда git затем снова денормализует его, чтобы сравнить его с файлом в рабочем дереве, результат будет другим.

Но если вы хотите это исправить, вы должны отключить core.autocrlf , изменить все окончания строк на lf, а затем включить его снова. Или вы можете отключить его, выполнив:

git config --global core.autocrlf false

Вместо core.autocrlf вы также можете рассмотреть возможность использования .gitattributeфайлов. Таким образом, вы можете быть уверены, что все, кто использует репо, используют одни и те же правила нормализации, предотвращая попадание концов смешанных строк в репозиторий.

Также рассмотрите возможность установки core.safecrlf для предупреждения, если вы хотите, чтобы git предупреждал вас, когда будет выполнена необратимая нормализация.

Git manpages говорят это:

Преобразование CRLF имеет небольшую вероятность повреждения данных. autocrlf = true преобразует CRLF в LF во время принятия и LF в CRLF во время извлечения. Файл, содержащий смесь LF и CRLF перед фиксацией, не может быть воссоздан git. Для текстовых файлов это правильно: он исправляет окончания строк так, что в хранилище есть только LF-окончания строк. Но для двоичных файлов, которые случайно классифицированы как текст, преобразование может повредить данные.

Нечувствительные к регистру файловые системы

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

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


8
Хорошо ... так, что сделал это ... теперь состояние git не показывает изменений. Я прочитал о настройках autocrlf, и я просто не могу понять это правильно.
rbellamy

1
Хороший улов! +1. Еще один аргумент для меня, установив это в false ( stackoverflow.com/questions/1249932/… ).
VonC

Что это значит: «Файл, содержащий смесь LF и CRLF до фиксации, не может быть воссоздан git». Это потому, что git всегда нормализует окончания строк, основываясь на параметре core.autocrlf?
rbellamy

1
Более разумным решением проблемы чувствительности к регистру является отсутствие нескольких папок в репо, имена которых отличаются только регистром .
Охад Шнайдер

3
Чтобы найти имена файлов, которые отличаются только регистром букв, вы можете запустить git ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d. Чтобы перечислить имена таких файлов в верхнем и нижнем регистре, запуститеgit ls-tree -r --name-only HEAD | fgrep -i -f <(git ls-tree -r --name-only HEAD | tr A-Z a-z | sort | uniq -d) | sort -i
Diomidis Spinellis

220

У меня была эта проблема в Windows, но я не был готов рассмотреть последствия использования. config --global core.autocrlf falseЯ также не был готов отказаться от других частных веток и вкусностей в своем тайнике и начать с нового клона. Мне просто нужно что-то сделать. Сейчас.

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

git rm --cached -r .
git reset --hard

(Обратите внимание, что запуск не git reset --hardбыл достаточно хорош, и не было простой rmв файлах до того, resetкак предлагается в комментариях к исходному вопросу)


8
Еще один успех здесь после изменения core.autocrlfне имел никакого эффекта.
Дэниел Бакмастер,

8
Была проблема с Windows даже с core.autocrlf false. Этот ответ сработал, когда больше ничего не будет.
Кенчилада

9
Я попробовал несколько предложений по этому и другим вопросам. Это единственное исправление, которое сработало для меня. У меня не было файла атрибутов, и я уже начал с core.autocrlf со значением false.
BrotherOdin

4
Это не сработало для меня. Итак, я сделал это более уродливо, создав новую ветку только для того, чтобы зафиксировать эти изменения, поскольку они в любом случае бесполезны для меня. [java] git checkout -b a-branch-to-commit-bad-crlf-файлы [/ java] [java] git commit -am "фиксация плохих файлов crlf" [/ java]
Мохд Фарид

3
Иногда такие проблемы заставляют меня скучать по SVN.
Майк Годин

104

Другое решение, которое может работать для людей, так как ни один из вариантов текста не работал для меня:

  1. Заменить содержимое .gitattributesс одной строки: * binary. Это говорит git обрабатывать каждый файл как двоичный файл, с которым он ничего не может сделать.
  2. Проверьте, что сообщение об оскорбительных файлах пропало; если это не так, вы можете git checkout -- <files>восстановить их до версии хранилища.
  3. git checkout -- .gitattributesвосстановить .gitattributesфайл в исходное состояние
  4. Убедитесь, что файлы по-прежнему не помечены как измененные.

1
Я застрял на том, что последние пару часов я не могу восстановить, вытащить или спрятать файлы. Это было исправление для меня! Спасибо! (Git 1.8.3.1)
NuSkooler

3
Я перепробовал много вещей, прежде чем, наконец, добился успеха с этим. Спасибо!
ghenghy

1
Как это работает? Я бы подумал, что возвращение .gitattributesк оригиналу приведет к повторному появлению той же проблемы, но, увы, моя проблема теперь решена. Ни одно из других предложений не сработало в моем случае.
jdk1.0

1
@ jdk1.0 Насколько я понимаю, у меня есть два разных метода сравнения. Ошибка возникает, когда у вас где-то заканчивается другая строка, и git иногда игнорирует ее. Когда вы спрашиваете git status, он обнаруживает, что это разные файлы. Когда вы спрашиваете git checkout, он обнаруживает, что они имеют одинаковое содержание. Это решение временно инструктирует git игнорировать любую возможную хитрость конца строки и гарантирует, что ваша локальная копия является побайтовой, идентичной копии в HEAD. После того, как это будет решено, разрешить возобновить ловкость можно, потому что это не добавит новых ошибок.
zebediah49

3
Потратил пару часов, чтобы разобраться с этим, и это решение, наконец, сработало для меня!
Марьям

71

Для будущих людей, имеющих эту проблему: Изменения в файловом режиме также могут иметь те же симптомы. git config core.filemode falseэто исправлю.


3
После этого вам может потребоваться сделатьgit checkout .
Марти Нил

2
Работал для меня без необходимости повторного
заказа

3
Для дальнейшего использования: чтобы узнать, нужно ли вам это исправление (а не другие исправления в других ответах), используйте, git diffи он покажет файлы с изменениями режима, подобными этим old mode 100755 / new mode 100644.
пгр

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

Спасибо, ты спас мне много слез!
Лукаш

33

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

Источник проблемы: моя первоначальная установка git была без автоматического преобразования строки в Windows. Это привело к тому, что мой первоначальный коммит в GLFW не имел правильного окончания строки.

Примечание: это только локальное решение. Следующий парень, клонирующий репо, все равно останется с этой проблемой. Постоянное решение можно найти здесь: https://help.github.com/articles/dealing-with-line-endings/#re-normalizing-a-repository .

Установка: Xubuntu 12.04 Git-репо с проектом glfw

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

Решено:

edit .gitattributes

Comment out the line:    # text=auto

Save the file

restore .gitattributes:   git checkout .gitattributes

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

К сожалению, большинство проектов не имеют этого необязательного файла
.gitattribute

Спасибо. Я просто не понимаю, зачем это нужно
diogovk

Зачем? По сути, это временное исправление конца строки. Используйте постоянное решение, перейдя по ссылке в примечании.
Ричард Лалансетт

11

У меня был файл .bat с той же проблемой (не удалось избавиться от него в неотслеживаемых файлах). git checkout - не сработало, ни одно из предложений на этой странице. Единственное, что сработало для меня, это сделать:

git stash save --keep-index

А затем удалить тайник:

git stash drop

Это сработало для меня. Обратите внимание, что --keep-indexэто важно.
user991710

Почему важен --keep-index?
Чойлтон Б. Хиггинботтом

8

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

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

git rm --cached -r .
git reset --hard

Теперь я получил почти все файлы в моем хранилище изменены.

При разметке файла он говорит, что я удалил все строки, а затем добавил их снова.

Вид беспокойства. Теперь я не буду прятаться в будущем.

Единственное решение - клонировать новый репозиторий и начать заново. (Сделал это в прошлый раз)


6

Попробуйте сделать

git checkout -f

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


Ницца! Это сработало для меня. Хотя для одного упрямого случае я должен был сначала git checkout -f <another recent branch>затем вернуться к моей ветви сgit checkout -f <branch I'm working on>
Перевернутое инженер

4

Я смог исправить это только путем временного удаления файла .gitattributes моего репо (который определил * text=autoи *.c text).

Я побежал git statusпосле удаления, и изменения исчезли. Они не вернулись даже после того, как .gitattributes был возвращен на место.


Это работает даже с более сложными gitattributes, например, фильтрами
Самиздис

2

Наличие последовательных окончаний строк - это хорошо. Например, это не вызовет ненужных слияний, хотя и тривиальных. Я видел, как Visual Studio создавал файлы со смешанными окончаниями строк.

Кроме того, некоторые программы, такие как bash (в linux), требуют, чтобы файлы .sh заканчивались LF.

Чтобы убедиться в этом, вы можете использовать gitattributes. Он работает на уровне хранилища независимо от значения autcrlf.

Например, вы можете иметь .gitattributes как это: * text = auto

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

Затем autocrlf может конвертировать окончания строк для программ Windows локально.

На смешанном проекте C # / C ++ / Java / Ruby / R, Windows / Linux это работает хорошо. Пока никаких проблем.


2

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

Я не смог:

git checkout app.js //did nothing
git rm app.js //did nothing
rm -rf app.js //did nothing

даже на git rm --cached app.jsнем отмечены как удаленные, так и в неотслеживаемых файлах я видел app.js. Но когда я попытался снова rm -rf app.jsвыполнить команду peform, git statusон все еще показывает мне файл «без отслеживания».

После пары попыток с коллегой мы узнали, что это было вызвано Grunt!

Так как Gruntон был включен, и поскольку app.js был сгенерирован из пары других js-файлов, мы обнаружили, что после каждой операции с js-файлами (также это app.js) grunt снова воссоздает app.js.


2

Эта проблема также может возникать, когда участник репо работает на компьютере с Linux или когда меняются окна с Cygwin и разрешениями для файлов. Git знает только о 755 и 644.

Пример этой проблемы и как проверить это:

git diff styleguide/filename

diff --git a/filename b/filename
old mode 100644
new mode 100755

Чтобы избежать этого, вы должны убедиться, что вы правильно настроили git, используя

git config --global core.filemode false

2

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

Наша проблема заключалась в том, что у нас не было принудительного применения конечных линий, а в хранилище было сочетание DOS / Unix. Хуже всего было то, что это было на самом деле репо с открытым исходным кодом в этой позиции, и мы его раздвоили. Те, кто имел первичное владение хранилищем ОС, приняли решение изменить все конечные строки на Unix, и было принято обязательство, включающее .gitattributesдля принудительного завершения концов строк .

К сожалению, это, похоже, вызывало проблемы, подобные описанным здесь, когда после слияния кода до DOS-2-Unix файлы навсегда помечались как измененные и не могли быть возвращены.

Во время моих исследований я наткнулся на - https://help.github.com/articles/dealing-with-line-endings/ - Если я столкнусь с этой проблемой снова, я сначала начну с ее опробования.


Вот что я сделал:

  1. Сначала я сделал слияние, прежде чем понял, что у меня есть эта проблема, и мне пришлось ее прервать - git reset --hard HEAD( я столкнулся с конфликтом слияния. Как я могу отменить слияние? )

  2. Я открыл эти файлы в VIM и изменил Unix ( :set ff=unix). Инструмент, как dos2unixможно было бы использовать вместо, конечно,

  3. привержен

  4. слил masterв (мастер имеет изменения DOS-2-Unix)

    git checkout old-code-branch; git merge master

  5. Устранены конфликты, и файлы снова оказались в DOS, как и :set ff=unixв VIM. (Обратите внимание, что я установил https://github.com/itchyny/lightline.vim, что позволило мне увидеть формат файла в строке состояния VIM)

  6. совершено. Все отсортировано!

2

Проблема, с которой я столкнулся, заключается в том, что windows не заботится о заглавных буквах имен файлов, а git. Так что git хранит версию файла в нижнем и верхнем регистре, но может извлечь только одну.


2

Я зафиксировал все изменения, а затем сделал и отменил коммит. Это сработало для меня

мерзавец добавить.

git commit -m "Случайный коммит"

git reset --hard HEAD ~ 1


2

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

$ git clean --force -d
$ git checkout -- .

Может быть, лучше иногда просто выполнить «git stash push» с дополнительным сообщением, например так:

$ git stash push -m "not sure if i will need this later"

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

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

$ git reset --hard

Если все вышеперечисленное не работает для вас , прочитайте ниже, что работало для меня некоторое время назад:

Я столкнулся с этой проблемой несколько раз раньше. В настоящее время я работаю на компьютере под управлением Windows 10, предоставленном моим работодателем. Сегодня это специфическое поведение git было вызвано тем, что я создал новую ветку из моей ветки "разработка". По какой-то причине после того, как я снова переключился на ветку «разработка», некоторые, казалось бы, случайные файлы сохранились и показывались как «измененные» в «состоянии git».

Кроме того, в тот момент я не мог оформить заказ на другую ветку, поэтому застрял в своей ветке "разработка".

Вот что я сделал:

$ git log

Я заметил, что новая ветвь, созданная мной из "Develop" ранее сегодня, отображалась в первом сообщении "commit", на которое ссылались в конце "HEAD -> Develop, origin / development, origin / HEAD, The-branch-i-создал Раньше сегодня ".

Поскольку мне это не нужно, я удалил это:

$ git branch -d The-branch-i-created-earlier-today

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

$ git stash

Это решило мою проблему:

$ git status
On branch develop
Your branch is up to date with 'origin/develop'.

nothing to commit, working tree clean

Конечно $ git stash list, покажет спрятанные изменения, и, так как у меня было немного, и я не нуждался в своих тайниках, я сделал, $ git stash clearчтобы УДАЛИТЬ ВСЕ ХРАНИЛИЩИ.

ПРИМЕЧАНИЕ : я не пытался делать то, что кто-то предлагал здесь до меня:

$ git rm --cached -r .
$ git reset --hard

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


1

Если вы клонируете хранилище и сразу видите ожидающие изменения, тогда хранилище находится в несогласованном состоянии. Пожалуйста , не закомментировать * text=autoиз .gitattributesфайла. Это было сделано специально потому, что владелец хранилища хочет, чтобы все файлы хранились в соответствии с окончаниями строк LF.

Как заявляет HankCa, следуя инструкциям на https://help.github.com/articles/dealing-with-line-endings/, вы сможете решить проблему. Простая кнопка:

git clone git@host:repo-name
git checkout -b normalize-line-endings
git add .
git commit -m "Normalize line endings"
git push
git push -u origin normalize-line-endings

Затем объедините (или вытяните запрос) ветку с владельцем репо.


1

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

git add -A
git reset --hard

1

Для меня проблема заключалась в том, что Visual Studio был открыт при выполнении команды

git checkout <file>

После закрытия Visual Studio команда сработала, и я наконец смог применить свою работу из стека. Поэтому проверьте все приложения, которые могут вносить изменения в ваш код, например SourceTree, SmartGit, NotePad, NotePad ++ и другие редакторы.


0

Мы столкнулись с похожей ситуацией в нашей компании. Ни один из предложенных способов нам не помог. В результате исследования была выявлена ​​проблема. Дело в том, что в Git было два файла, названия которых отличались только регистром символов. Unix-системы рассматривали их как два разных файла, но Windows сходила с ума. Чтобы решить проблему, мы удалили один из файлов на сервере. После этого в локальных репозиториях на Windows помогли следующие несколько команд (в разных последовательностях):

git reset --hard
git pull origin
git merge

0

Я решил это, отредактировав .git / config, добавив:

[branch "name_branch"]
    remote = origin
    merge = refs/heads/name_branch

Затем я пошел в .git / refs /heads / name_branch и поместил идентификатор последнего коммитаenter code here


0

Я решил это так:

  1. Скопируйте содержимое правильного кода, который вы хотите
  2. Удалите файл, который вызывает проблему (тот, который вы не можете восстановить) с вашего диска. Теперь вы должны найти обе версии одного и того же файла, помеченные как удаленные.
  3. Зафиксируйте удаление файлов.
  4. Снова создайте файл с тем же именем и вставьте правильный код, который вы скопировали на шаге 1
  5. зафиксируйте создание нового файла.

Вот что сработало для меня.


0

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

% ls -l StoreLogo.png
lrwxrwxrwx 1 janus janus 8 Feb 21 10:37 StoreLogo.png -> ''$'\211''PNG'$'\r\n\032\n'

% git status    
Changes not staged for commit:
    modified:   StoreLogo.png

% git rm --cached -r StoreLogo.png
rm 'src/GWallet.Frontend.XF.UWP/Assets/StoreLogo.png'

% git reset StoreLogo.png         
Unstaged changes after reset:
M   src/GWallet.Frontend.XF.UWP/Assets/StoreLogo.png

% git status                      
Changes not staged for commit:
    modified:   StoreLogo.png
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.