Git: Как восстановить 2 файлов, которые упорно застряли на «Измененный, но не совершал»? - PullRequest
78 голосов
/ 13 июня 2011

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

Так что я застрял с этим:

$ 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 не видит).

Интересно, что я не помню, чтобы эти файлы менялись локально. Это репо используется с одним удаленным репо (частным, на 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? плюс еще. Но 2 файла остаются «измененными, но не зафиксированными».

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

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

Ответы [ 10 ]

106 голосов
/ 03 января 2013

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

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

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

В Mac OSX, однако, xargs работает немного иначе (спасибо Дэниелу за комментарий):

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

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

-Аль

30 голосов
/ 14 июня 2011

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

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

20 голосов
/ 08 марта 2016

Вот как я исправил ту же проблему в моем случае: откройте .gitattributes change:

* text=auto

на:

#* text=auto

сохраните и закройте, затем верните или сбросьте, спасибона @ Симон Восток за подсказку

10 голосов
/ 13 июня 2012

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

git diff dir1 / foo.aspx

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

git config core.filemode false

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

[ядро]

filemode = false

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

git reset HEAD dir1 / foo.aspx

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

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

3 голосов
/ 12 февраля 2016

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

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

git config --local core.autocrlf false

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

3 голосов
/ 13 июня 2011

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

git checkout -- dir1/foo.aspx
git checkout -- dir2/foo.aspx
2 голосов
/ 13 июня 2011
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx
1 голос
/ 22 августа 2018

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

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

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

1 голос
/ 01 ноября 2017

Для меня проблема была не в конце строки.Речь шла об изменении регистра в имени папки (Reset_password -> Reset_Password).Это решение помогло мне: https://stackoverflow.com/a/34919019/1328513

1 голос
/ 11 июля 2017

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

$ 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's revert now

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

# Oooops, it didn't revert!!


# hm let's 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's 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's try to revert for once more:
$ git checkout -- 1.txt
$ git status
 modified:   1.txt

# Nothing. Let's 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 и затем зафиксировать.

...