web-dev-qa-db-de.com

Git: Wie können 2 Dateien wiederhergestellt werden, die hartnäckig bei "Geändert, aber nicht festgelegt" hängen geblieben sind?

Ich habe ein Repo mit zwei Dateien, die ich angeblich lokal geändert habe.

Also bleibe ich dabei:

$ 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")

Doing git diff sagt aus, dass sich der gesamte Dateiinhalt geändert hat, auch wenn das Betrachten der Daten unwahrscheinlich erscheint (es scheint übliche Linienbereiche zu geben, die diff nicht zu sehen scheint).

Interessanterweise erinnere ich mich nicht daran, diese Dateien lokal geändert zu haben. Dieses Repo wird mit einem Remote-Repo (privat, bei GitHub.com, FWIW) verwendet.

Egal was ich versucht habe, ich kann diese lokalen Änderungen nicht verwerfen. Ich habe alles ausprobiert:

$ 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

Mit anderen Worten, ich habe alles ausprobiert, was in beschrieben ist. und mehr. Die 2 Dateien bleiben jedoch als "geändert, aber nicht festgeschrieben" hängen.

Was zum Teufel würde dazu führen, dass zwei Dateien wie diese und scheinbar "un-revert-table" hängen bleiben?

P.S. In der obigen Liste mit Befehlen, die ich bereits ausprobiert hatte, schrieb ich irrtümlicherweise git revert, als ich git checkout meinte. Es tut mir leid und ich danke Ihnen allen, die geantwortet haben, dass ich checkout versuchen soll. Ich habe die Frage bearbeitet, um sie zu korrigieren. Ich habe definitiv schon checkout ausprobiert.

76

Was sind die Zeilenenden in den Dateien? Ich wette, sie sind CRLF. Wenn dies der Fall ist, lesen Sie dieses Handbuch: http://help.github.com/line-endings/

Kurz gesagt, Sie müssen sicherstellen, dass git so eingestellt ist, dass die Zeilenenden beim Commit in LF konvertiert werden und diese Dateien dann festgeschrieben werden. Dateien im Repo sollten immer LF sein, ausgecheckte Dateien sollten nativ sein, vorausgesetzt, Sie setzen git richtig.

31
Tekkub

Ich habe stundenlang versucht, ein ähnliches Problem zu lösen - einen entfernten Zweig, den ich ausgecheckt hatte, der vier Dateien hartnäckig als "Geändert, aber nicht aktualisiert" angezeigt hat, selbst wenn alle Dateien gelöscht wurden und git checkout -f erneut ausgeführt wurde (oder andere Variationen aus diesem Beitrag)!

Diese vier Dateien waren notwendig, waren aber sicherlich nicht von mir modifiziert worden. Meine endgültige Lösung - überzeugen Sie Git, dass sie nicht geändert wurden. Das Folgende funktioniert für alle ausgecheckten Dateien, die den Status 'modifiziert' anzeigen - stellen Sie sicher, dass Sie bereits alle Dateien festgelegt/gespeichert haben, die wirklich geändert wurden !:

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

Unter Mac OSX funktioniert xargs jedoch etwas anders (danke Daniel für den Kommentar):

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

Ich habe dies für das nächste Mal als Platzhalter für mich hinzugefügt, aber ich hoffe, es hilft auch jemand anderem.

-Al

102
Alan Forsyth

so habe ich in meinem Fall dasselbe Problem behoben: open .gitattributes change:

* text=auto

zu:

#* text=auto

speichern und schließen, dann zurücksetzen oder zurücksetzen, Danke an @Simon East für den Hinweis

21
Abu Assar

Eine andere Möglichkeit ist, dass der Unterschied (der verhindert, dass Sie diese Dateien mit einem Checkout-Befehl zurücksetzen) der Dateimodus ist. Das ist mir passiert. Auf meiner Version von git können Sie dies mithilfe von entdecken

git diff dir1/foo.aspx

Daraufhin werden Änderungen im Dateimodus angezeigt. Es wird Sie immer noch nicht zulassen, dass Sie sie umkehren. Verwenden Sie dazu entweder

git config core.filemode false

oder ändern Sie Ihre git .config in Ihrem Texteditor durch Hinzufügen

[Ader]

filemode = false

Nachdem Sie dies getan haben, können Sie verwenden

git reset HEAD dir1/foo.aspx

und die Datei sollte verschwinden.

(Ich habe all das aus der Antwort auf Wie mache ich git ignore Modusänderungen (chmod)? )

10
Eyal

Versuchen Sie, lokale Änderungen rückgängig zu machen :

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

Ich hatte einige phantomveränderte Dateien, die zwar als geändert angezeigt wurden, aber tatsächlich identisch waren.

Ausführen dieses Befehls manchmal funktioniert:
(Deaktiviert gits "smarte", aber häufig nicht hilfreiche Konvertierungen für Zeilenende)

git config --local core.autocrlf false

In einem anderen Fall fand ich jedoch, dass es sich um eine .gitattributes-Datei im Stammverzeichnis handelte, in der einige Einstellungen für die Zeilenenden vorhanden waren. Diese versuchte, autocrlf für bestimmte Dateien anzuwenden, selbst wenn sie deaktiviert war. Das war nicht wirklich hilfreich, also löschte ich .gitattributes, bestätigte und die Datei wurde nicht mehr als geändert angezeigt.

3
Simon East
git checkout dir1/foo.aspx
git checkout dir2/foo.aspx
2
Steve Prentice

Ich denke, es wäre hilfreich, einen Hinweis auf das Problem zu reproduzieren zu geben, um das Problem besser zu verstehen:

$ 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. Weg zur Reproduktion: Ersetzen Sie im obigen Skript diese Zeile:
echo "*.txt -text" > .gitattributes
mit
git config core.autocrlf=false
und halten Sie die restlichen Zeilen so wie sie sind


Was sagen die oben genannten? Eine Textdatei can (unter bestimmten Umständen) mit CRLF festgelegt (z. B. -text in .gitattributes/oder core.autocrlf=false). 

Wenn wir später dieselbe Datei als Text behandeln möchten (-text -> text), muss sie erneut festgeschrieben werden.
Natürlich können Sie es vorübergehend aufheben (wie von Abu Assar richtig beantwortet). In unserem Fall: 

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

Die Antwort ist: Möchten Sie das wirklich tun, weil es jedes Mal dasselbe Problem verursacht, wenn Sie die Datei ändern.


Für den Datensatz:

Um zu prüfen, welche Dateien dieses Problem in Ihrem Repo verursachen können, führen Sie den folgenden Befehl aus (git sollte mit --with-libpcre kompiliert werden): 

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

Wenn Sie die Datei (en) festlegen (vorausgesetzt, Sie möchten sie als Text behandeln), ist es das Gleiche wie das, was in diesem Link vorgeschlagen wird. http://help.github.com/line-endings/ zur Behebung solcher Probleme. Anstatt .git/index zu entfernen und reset auszuführen, können Sie einfach die Datei (en) ändern, dann git checkout -- xyz zyf ausführen und dann die Festschreibung ausführen.

1
Marinos An

Bei mir ging es nicht um Zeilenenden. Es ging darum, die Groß-/Kleinschreibung im Ordnernamen zu ändern (Reset_password -> Reset_Password). Diese Lösung hat mir geholfen: https://stackoverflow.com/a/34919019/1328513

1
Ievgen

Möglicherweise hatten Sie auch ein Problem im Zusammenhang mit Verzeichnissen, in denen die Buchstaben mit Buchstaben benannt wurden. Einige Ihrer Kollegen hätten den Namen des Verzeichnisses geändert. myHandler an MyHandler . Wenn Sie später einige Dateien des ursprünglichen Verzeichnisses verschoben und abgerufen haben, hätten Sie 2 separate Verzeichnisse im Remote-Repository UND nur eine auf Ihrem lokalen Rechner da Sie unter Windows nur einen haben. Und du bist in Schwierigkeiten.

Um zu überprüfen, ob dies der Fall ist, prüfen Sie einfach, ob das entfernte Repository eine doppelte Struktur hat.

Um dies zu beheben, erstellen Sie eine Sicherungskopie des übergeordneten Verzeichnisses außerhalb des Repos und löschen Sie das übergeordnete Verzeichnis. Drücken Sie es. Machen Sie einen Pull (hier ist, wenn der als gelöscht markierte zweite Status angezeigt werden soll) und Push erneut . Erstellen Sie anschließend die gesamte Struktur aus Ihrer Sicherung neu und drücken Sie die Änderungen erneut.

0
smexy