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
).
Когда мы позже захотим рассматривать тот же файл как текст (-text
→ text
), его нужно будет зафиксировать снова.
Конечно, вы можете временно отменить его (как правильно ответил Абу Ассар). В нашем случае:
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 у вас может быть только один. И у тебя проблемы.
Чтобы проверить, так ли это, просто посмотрите, имеет ли удаленный репозиторий двойную структуру.
Чтобы это исправить, сделайте резервную копию родительского каталога за пределами репозитория, затем удалите родительский каталог и нажмите его. Сделайте нажатие (здесь, когда второй, помеченный как удаленный должен появиться в статусе) и нажмите еще раз. После этого воссоздайте всю структуру из резервной копии и снова внесите изменения.