Git: Как восстановить 2 файлов, которые упорно застряли на "Измененный, но не совершал"?

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

Итак, я застрял в этом:

$ 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:   dir1/foo.aspx
#       modified:   dir2/foo.aspx
#
no changes added to commit (use "git add" and/or "git commit -a")

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

Интересно, что я не помню, как менялись эти файлы локально. Это репо используется с одним удаленным репо (private, на GitHub.com, FWIW).

Независимо от того, что я пробовал, я не могу отказаться от этих локальных изменений. Я пробовал все:

$ git checkout -- .
$ git checkout -f
$ git checkout -- dir1/checkout_receipt.aspx
$ git reset --hard HEAD
$ git stash save --keep-index && git stash drop
$ git checkout-index -a -f

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

Какая черта приведет к тому, что два файла будут застревать как это и, казалось бы, "un-revert-table"??

P.S. В приведенном выше списке показаны команды, которые я уже пробовал, я ошибочно написал git revert, когда имел в виду git checkout. Простите, спасибо вам, кто ответил, что я должен попробовать checkout. Я отредактировал вопрос, чтобы исправить это. Я определенно уже попробовал checkout.

Ответ 1

Каковы окончания строк в файлах? Я уверен, что они CRLF. Если да, ознакомьтесь с этим руководством: http://help.github.com/line-endings/

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

Ответ 2

Я потратил часы, пытаясь решить подобную проблему - удаленный филиал, что я проверил, что упорно показывал четыре файла, как "Измененные но не обновляется", даже при удалении всех файлов и запуск git checkout -f еще раз (или другие варианты из этого поста)!

Эти четыре файла были необходимы, но, конечно, меня не модифицировали. Мое окончательное решение - убедить Git в том, что они не были изменены. Следующие работы для всех проверенных файлов, показывающих статус "измененный", убедитесь, что вы уже зафиксировали/заблокировали все, которые действительно были изменены!:

git ls-files -m | xargs -i git update-index --assume-unchanged "{}"

В Mac OSX, однако, xargs работает немного иначе (спасибо Daniel для комментария):

git ls-files -m | xargs -I {} git update-index --assume-unchanged {}

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

-Al

Ответ 3

вот как я исправил ту же проблему в моем случае: открыть .gitattributes изменить:

* text=auto

в

#* text=auto

сохранить и закрыть, затем вернуться или reset, спасибо @Simon East за подсказку

Ответ 4

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

git diff dir1/foo.aspx

И он покажет вам изменения в режиме файла. Тем не менее, это все равно не позволит вам вернуть их. Для этого используйте либо

git config core.filemode false

или измените свой git.config в текстовом редакторе, добавив

[ядро]

filemode = false

После этого вы можете использовать

git reset HEAD dir1/foo.aspx

и файл должен исчезнуть.

(я получил все это от ответа на Как мне сделать изменения режима игнорирования w2 > (chmod)?)

Ответ 5

Попробуйте вернуть локальные изменения:

git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx

Ответ 6

У меня были некоторые измененные файлы phantom, которые показывались как измененные, но были фактически идентичными.

Выполнение этой команды иногда работает:
(Отключает git "умные", но часто бесполезные конверсии с завершением строки)

git config --local core.autocrlf false

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

Ответ 7

git checkout dir1/foo.aspx
git checkout dir2/foo.aspx

Ответ 8

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

$ git init
$ echo "*.txt -text" > .gitattributes
$ echo -e "hello\r\nworld" > 1.txt
$ git add 1.txt 
$ git commit -m "committed as binary"
$ echo "*.txt text" > .gitattributes
$ echo "change.." >> 1.txt

# Ok let revert now

$ git checkout -- 1.txt
$ git status
 modified:   1.txt

# Oooops, it didn't revert!!


# hm let diff:

$ git diff
 warning: CRLF will be replaced by LF in 1.txt.
 The file will have its original line endings in your working 
 directory.
 diff --git a/1.txt b/1.txt
 index c78c505..94954ab 100644
 --- a/1.txt
 +++ b/1.txt
 @@ -1,2 +1,2 @@
 -hello
 +hello
  world

# No actual changes. Ahh, let change the line endings...

$ file 1.txt 
 1.txt: ASCII text, with CRLF line terminators
$ dos2unix 1.txt
 dos2unix: converting file 1.txt to Unix format ...
$ git diff
 git diff 1.txt
 diff --git a/1.txt b/1.txt
 index c78c505..94954ab 100644
 --- a/1.txt
 +++ b/1.txt
 @@ -1,2 +1,2 @@
 -hello
 +hello
  world

# No, it didn't work, file is still considered modified.

# Let try to revert for once more:
$ git checkout -- 1.txt
$ git status
 modified:   1.txt

# Nothing. Let use a magic command that prints wrongly committed files.

$ git grep -I --files-with-matches --perl-regexp '\r' HEAD

HEAD:1.txt

2-й способ воспроизведения: в приведенном выше сценарии замените эту строку:
echo "*.txt -text" >.gitattributes
с
git config core.autocrlf=false
и сохранить остальные строки как есть


Что все вышесказанное говорит? Текстовый файл может (при некоторых обстоятельствах) быть зафиксирован с CRLF (например, -text в .gitattributes/или core.autocrlf=false).

Когда мы позже захотим рассматривать тот же файл как текст (-texttext), его нужно будет зафиксировать снова.
Конечно, вы можете временно отменить его (как правильно ответил Абу Ассар). В нашем случае:

echo "*.txt -text" > .gitattributes
git checkout -- 1.txt
echo "*.txt text" > .gitattributes

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


Для записи:

Чтобы проверить, какие файлы могут вызвать эту проблему в вашем репозитории, выполните следующую команду (git должен быть скомпилирован с --with-libpcre):

git grep -I --files-with-matches --perl-regexp '\r' HEAD

Передавая файл (предположим, что вы хотите рассматривать их как текст), это то же самое, что делать то, что предлагается в этой ссылке http://help.github.com/line-endings/ для решения таких проблем., Но вместо того, чтобы удалить .git/index и выполнить reset, вы можете просто изменить файл (ы), затем выполнить git checkout -- xyz zyf и затем выполнить коммит.

Ответ 9

Для меня вопрос не касался окончаний строки. Речь шла об изменении случая в имени папки (Reset_password → Reset_Password). Это решение помогло мне: fooobar.com/questions/87353/...

Ответ 10

У вас также может быть проблема, связанная с именами каталогов. Некоторые из ваших коллег могли изменить название каталога, например, с myHandler на MyHandler. Если вы позже нажмете и извлечете некоторые файлы исходного каталога, у вас будет 2 отдельных каталога в удаленном хранилище и только один на локальном компьютере, поскольку в Windows у вас может быть только один. И у тебя проблемы.

Чтобы проверить, так ли это, просто посмотрите, имеет ли удаленный репозиторий двойную структуру.

Чтобы это исправить, сделайте резервную копию родительского каталога за пределами репозитория, затем удалите родительский каталог и нажмите его. Сделайте нажатие (здесь, когда второй, помеченный как удаленный должен появиться в статусе) и нажмите еще раз. После этого воссоздайте всю структуру из резервной копии и снова внесите изменения.