Git: Wie kann man 2 Dateien zurücksetzen, die hartnäckig bei "Geändert, aber nicht festgeschrieben" hängen bleiben?


83

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

Wenn Sie dies tun git diff, ändert sich der gesamte Dateiinhalt, auch wenn dies nicht wahr ist (es scheint gemeinsame Zeilenbereiche zu geben, die diff nicht zu sehen scheint).

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

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

$ 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 versucht, was unter Wie verwerfe ich nicht bereitgestellte Änderungen in Git? 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 so hängen bleiben und scheinbar "Tabelle nicht wiederherstellen"?

PS In der obigen Liste mit Befehlen, die ich bereits ausprobiert hatte, habe ich fälschlicherweise geschrieben, git revertals ich meinte git checkout. Es tut mir leid und ich danke denen von Ihnen, die geantwortet haben, dass ich es versuchen sollte checkout. Ich habe die Frage bearbeitet, um sie zu korrigieren. Ich habe es definitiv schon versucht checkout.


Macht git diff --ignore-space-changeoder git diff --ignore-all-spacemacht es einen Unterschied in der Ausgabe von git diff?
jdd

@ jermiahd Ja! Bei beiden Flags sind git diffdie Dateien identisch.
Greg Hendershott

2
Mögliches Duplikat von stackoverflow.com/questions/2016404/… . Ich mag die akzeptierte Antwort dort sowieso besser, nämlich git config --global core.autocrlf false"wahr" zu setzen.
Johann

2
Die Antwort [hier] [1] hat für mich und viele andere funktioniert. [1]: stackoverflow.com/questions/2016404/…
Mike K

2
Dies geschieht auch, wenn das Repository, das zwei oder mehr Dateien in demselben Verzeichnis mit unterschiedlicher Groß- und Kleinschreibung enthält, im Dateisystem ohne Berücksichtigung der Groß- und Kleinschreibung ausgecheckt wird. Entfernen Sie eine der Dateien oder benennen Sie sie um, um das Problem zu beheben.
465544

Antworten:


33

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

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


1
Vielen Dank. Ich habe es bereits git config --global core.autocrlf trueund die andere Partei drängt auf GitHub zum Repo.
Greg Hendershott

1
Dann sollten Sie nur noch die Bits im letzten <pre>Block dieses Handbuchs ausführen müssen, um die Dateien im Repo zu reparieren.
Tekkub

5
Ich bin nicht der Meinung, dass Zeilenenden im Repo immer LF sein sollten (insbesondere wenn bereits jemand anderes CRLF festgelegt hat) und dass das Betriebssystem immer nativ sein sollte. Mein Windows-Editor und meine Umgebung (hauptsächlich für PHP, HTML, CSS usw.) kommen mit LF-Zeilenenden perfekt zurecht.
Simon East

Eine geniale Antwort, ich hatte vergessen, dass ich kürzlich Gitattribute verwendet hatte, um LF in Repo-Dateien zu erzwingen, und nicht erwartet hatte, dass Git die Datei automatisch ändert. Wir haben eine Mischung aus Windows- und Linux-Entwicklern, und es hat uns verrückt gemacht, als Redakteure auf verschiedenen Plattformen immer wieder Leitungsterminatoren austauschten, sobald die Änderung durchgesickert ist, sollte dies alles verschwinden.
Oliver Dungey

116

Ich habe stundenlang versucht, ein ähnliches Problem zu lösen - einen von mir ausgecheckten Remote-Zweig, in dem vier Dateien hartnäckig als "Geändert, aber nicht aktualisiert" angezeigt wurden, selbst wenn alle Dateien gelöscht und git checkout -ferneut ausgeführt wurden (oder andere Variationen dieses Beitrags)!

Diese vier Dateien waren notwendig, wurden aber von mir sicherlich nicht geändert. Meine endgültige Lösung - überzeugen Sie Git, dass sie nicht geändert wurden. Das Folgende funktioniert für alle ausgecheckten Dateien und zeigt den Status "Geändert" an. Stellen Sie sicher, dass Sie bereits festgeschriebene Dateien gespeichert haben.

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

Unter Mac OS X 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 als Platzhalter für mich selbst für das nächste Mal hinzugefügt, aber ich hoffe, es hilft auch jemand anderem.

-Al


9
Ich hatte ein paar hartnäckige Dateien und führte diesen Befehl aus. Der Git-Status enthält jetzt keine Änderungen mehr. Wenn ich jedoch versuche, den Zweig zu ändern, sagt mir Git immer noch, dass ich den Zweig nicht ändern kann, da diese beiden Dateien lokale Änderungen aufweisen. Sie sind sich nicht sicher, was ich falsch gemacht habe, aber es schien, als hätte es das Problem nur vertuscht, anstatt es zu beheben? Ich konnte die Dateien auch nicht festschreiben, nachdem ich diesen Befehl ausgeführt hatte. Die Lösung für mich bestand darin, sie zu löschen, Zweige festzuschreiben und auszutauschen.
RodH257

5
Vielen Dank! Ich habe ALLE Tricks ausprobiert, die in jeder anderen Antwort erwähnt wurden - keine hat funktioniert. Auf einem Mac konnte die Zeile nicht so verwendet werden, wie sie ist. Sie haben lediglich den git update-index --assume-unverändert <Dateiname> für jede Datei ausgeführt, wodurch das Problem behoben wurde.
Yonatan Karni

2
Soll die Option "--assume-unverändert" nicht verwendet werden, wenn lokale Änderungen an dieser Datei NIEMALS festgeschrieben werden sollen? Zum Beispiel, wenn Sie eine Konfigurationsdatei für eine Vorlagenwebsite auschecken und mit vertraulichen Informationen aktualisieren, die nicht im Repository gespeichert werden sollten?
Maxime Rossini

6
Dies ist genau das, was ich brauchte, obwohl xargs auf dem Mac etwas anders zu funktionieren scheint (ich verwende 10.10 Yosemite). Dies funktionierte schließlich für mich:git ls-files -m | xargs -I {} git update-index --assume-unchanged {}
Daniel

3
Um die Wirkung des Befehls git ls-files -v|grep '^h' | cut -c3- | xargs -i git update-index --no-assume-unchanged "{}"
Marinos An

20

So habe ich das gleiche Problem in meinem Fall 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


1
Das Entfernen der text=autoEinstellung in .gitattributes hat bei mir funktioniert, und nachdem ich git reset --harddiese Einstellung zurückgesetzt habe, wurden die Dateien nicht mehr als geändert angezeigt !
ErikE

1
Mit dieser text=autoEinstellung stimmt offensichtlich etwas nicht . Ich arbeite in Repos mit Commits von mehreren Betriebssystemen und habe immer noch nicht herausgefunden, was mir mehr Probleme bereitet: es zu behalten oder es fallen zu lassen.
Marinos An

1
@MarinosAn ja, mit git können Sie die vorhandenen Textdateien mit den falschen Zeilenenden belassen, wenn Sie diese Einstellung zum ersten Mal hinzufügen. Das ist einfach falsch und wenn Sie nicht daran denken, dies selbst zu tun, werden Sie irgendwann auf eine dieser nicht rückgängig zu machenden Änderungen stoßen.
Roman Starkov

12

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

git diff dir1 / foo.aspx

Und es zeigt Ihnen Änderungen im Dateimodus. Sie können sie jedoch immer noch nicht zurücksetzen. 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 dies aus der Antwort auf Wie mache ich Änderungen am Git-Ignoriermodus (chmod)? )


1
Wenn Sie unter Windows arbeiten, sollte
AlcubierreDrive

Achten Sie besonders darauf, niemals Cygwin Git von cmd.exe zu verwenden. Wenn Sie git in cmd.exe möchten, installieren Sie msysgit.
AlcubierreDrive

Nur um zu bestätigen, dass dies tatsächlich das Problem unter Windows war.
Dejan Marjanović

Für mich unter Windows war dies nicht das Problem ( core.filemodewurde bereits auf false gesetzt). In meinem Fall war der Fix / Workaround der in Alan Forsyths Antwort .
Venryx

3

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

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

Ich hatte "zurück" im Gehirn und wollte schreiben checkout. Ich habe es schon versucht checkout. Trotzdem vielen Dank für Ihre Antwort. Es war eine gute Antwort auf meine ursprüngliche Frage, also werde ich abstimmen.
Greg Hendershott

3

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

Das Ausführen dieses Befehls funktioniert manchmal :
(Deaktiviert die "intelligenten", aber oft nicht hilfreichen Konvertierungen am Zeilenende von git)

git config --local core.autocrlf false

In einem anderen Fall stellte ich jedoch fest, dass es sich um eine .gitattributesDatei im Stammverzeichnis handelte, in der einige Einstellungen für das Zeilenende vorhanden waren, die versuchte, autocrlfbestimmte Dateien auch dann anzuwenden , wenn sie deaktiviert war. Das war eigentlich nicht hilfreich, also habe ich gelöscht .gitattributes, festgeschrieben und die Datei wurde nicht mehr als geändert angezeigt.


Das Entfernen der text=autoEinstellung in .gitattributes hat bei mir funktioniert, und nachdem ich git reset --harddiese Einstellung zurückgesetzt habe, wurden die Dateien nicht mehr als geändert angezeigt !
ErikE

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

Ich hatte das Gehirn "zurückgesetzt" und wollte schreiben checkout. Ich habe es schon versucht checkout. Trotzdem vielen Dank für Ihre Antwort. Es war eine gute Antwort auf meine ursprüngliche Frage, also werde ich abstimmen.
Greg Hendershott

2

Möglicherweise hatten Sie auch ein Problem mit Verzeichnissen, in denen Buchstabenfälle benannt wurden. Einige Ihrer Kollegen haben möglicherweise den Namen des Verzeichnisses von z . B. myHandler in MyHandler geändert . Wenn Sie später einige der Dateien des ursprünglichen Verzeichnisses verschoben und abgerufen hätten, hätten Sie zwei separate Verzeichnisse im Remote-Repository UND nur eines auf Ihrem lokalen Computer, da Sie unter Windows nur eines haben können. Und du bist in Schwierigkeiten.

Um zu überprüfen, ob dies der Fall ist, überprüfen Sie einfach, ob das Remote-Repository eine doppelte Struktur aufweist.

Um dies zu beheben, erstellen Sie eine Sicherungskopie des übergeordneten Verzeichnisses außerhalb des Repos, löschen Sie das übergeordnete Verzeichnis und drücken Sie es. Ziehen Sie (hier sollte der zweite, der als gelöscht markiert ist, im Status angezeigt werden) und drücken Sie erneut. Erstellen Sie danach die gesamte Struktur aus Ihrem Backup neu und übertragen Sie die Änderungen erneut.


2

Ich denke, es wäre hilfreich, einen Hinweis zu geben, wie das Problem reproduziert werden kann, 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. Art der Reproduktion: Ersetzen Sie im obigen Skript diese Zeile:
echo "*.txt -text" > .gitattributes
durch
git config core.autocrlf=false
und behalten Sie den Rest der Zeilen bei


Was sagen alle oben genannten? Eine Textdatei kann (unter bestimmten Umständen) mit CRLF festgeschrieben werden (z. B. -textin .gitattributes/ oder core.autocrlf=false).

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

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

Die Antwort lautet : Wollen Sie das wirklich tun, weil es jedes Mal, wenn Sie die Datei ändern, dasselbe Problem verursacht?


Für die Aufzeichnung:

Um zu überprü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) festschreiben (vorausgesetzt, Sie möchten sie als Text behandeln), ist dies dasselbe wie das, was in diesem Link http://help.github.com/line-endings/ vorgeschlagen wird, um solche Probleme zu beheben . Anstatt Sie zu entfernen .git/indexund resetauszuführen, können Sie einfach die Datei (en) ändern, dann ausführen git checkout -- xyz zyfund dann festschreiben.



1

Ich hatte das gleiche Problem mit dem interessanten Zusatz, dass die Dateien unter Windows geändert wurden, aber nicht, wenn ich sie von der WSL aus betrachtete. Kein Durcheinander mit Zeilenenden, Zurücksetzen usw. konnte dies ändern.

Schließlich fand ich in dieser Antwort eine Lösung . Es folgt der Text zur Bequemlichkeit:


Ich habe dieses Problem mit den folgenden Schritten behoben

1) Entfernen Sie jede Datei aus dem Git-Index.

git rm --cached -r .

2) Schreiben Sie den Git-Index neu, um alle neuen Zeilenenden aufzunehmen.

git reset --hard

Die Lösung war Teil der auf der Git-Website https://help.github.com/articles/dealing-with-line-endings/ beschriebenen Schritte.


1

Dieses Problem kann auch daran liegen, dass git Großschreibungsunterschiede als unterschiedliche Dateien behandelt, Windows sie jedoch als dieselbe Datei behandelt. Wenn nur die Groß- und Kleinschreibung eines Dateinamens geändert wurde, wird jeder Windows-Benutzer dieses Repos in dieser Situation enden.

Die Lösung besteht darin, zu bestätigen, dass der Inhalt der Dateien korrekt ist, und ihn dann erneut zu aktivieren. Wir mussten die beiden Dateiinhalte zusammenführen, da sie unterschiedlich waren. Ziehen Sie dann und es kommt zu einem Zusammenführungskonflikt, den Sie durch Löschen der doppelten Datei lösen können. Setzen Sie die Zusammenführungsauflösung erneut fest und Sie befinden sich wieder in einem stabilen Zustand.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.