Wie normalisiere ich funktionierende Baumzeilenenden in Git?

73

Ich habe ein Repository geklont, das inkonsistente Zeilenenden hatte. Ich habe ein hinzugefügt .gitattributes, das das Textattribut für die Dateien festlegt, die ich normalisieren möchte. Wenn ich jetzt Änderungen festschreibe, erhalte ich folgende Meldung:

warning: CRLF will be replaced by LF in FILE.
The file will have its original line endings in your working directory.

Wie kann ich Git dazu bringen, meine Arbeitskopie der Datei für mich zu normalisieren? Am liebsten möchte ich, dass git den gesamten Arbeitsbaum normalisiert.

user11171
quelle
Wenn Sie 2019 zu dieser Frage kommen, beachten Sie, dass die zweite Antwort (von @philippn) jetzt besser ist als die derzeit akzeptierte
CharlieB

Antworten:

88

Mit Git Client 2.16 und höher gibt es jetzt eine viel einfachere Möglichkeit, dies zu tun. Benutz einfach:

git add --renormalize .

Hinweis: Es ist besser, dies mit einem sauberen Arbeitsbereich zu tun. Einzelheiten finden Sie unter:

philippn
quelle
1
Ich habe dies gerade auf Git Bash für Windows versucht und es hat jede Datei im Repo zum Festschreiben bereitgestellt.
William.berg
1
Ich habe eine Fehlermeldung:error: unknown option 'renormalize'
Ryan Nghiem
@ RyanNghiem Was git --versionsagt das? Ich würde vermuten, dass es einfach älter als 2.16 ist und Sie ein Upgrade durchführen müssen. HTH
Philippn
2
@cja "Clean workspace" wie in: Der Befehl git statusgibt so etwas wienothing to commit, working tree clean
philippn
Das bringt mir überhaupt nichts. : - /
Timmmm
99

Für diejenigen, die Version 2.16 oder besser verwenden, können Sie einfach Folgendes verwenden:

git add --renormalize .  # Update index with renormalized files
git status               # Show the files that will be normalized
git commit -m "Introduce end-of-line normalization"

Diese Anweisungen stammen direkt aus den Gitattributen . Für ältere Versionen bieten die Dokumente (vor Version 2.12) eine andere Antwort:

rm .git/index     # Remove the index to force git to
git reset         # re-scan the working directory
git status        # Show files that will be normalized
git add -u
git add .gitattributes
git commit -m "Introduce end-of-line normalization"

Führen Sie diese Sequenz aus, nachdem Sie sie bearbeitet haben .gitattributes.

Aktualisieren

Es scheint, dass einige Benutzer Probleme mit den obigen Anweisungen hatten. Aktualisierte Dokumente für Gitattributes (2.12 bis 2.14) zeigen eine neue Anleitung (nach dem Bearbeiten der Gitattributes-Dateien):

git read-tree --empty   # Clean index, force re-scan of working directory
git add .
git status        # Show files that will be normalized
git commit -m "Introduce end-of-line normalization"

Vielen Dank an @ vossad01 für diesen Hinweis.

Bei beiden Lösungen behalten die Dateien in Ihrer Arbeitskopie ihre alten Zeilenenden bei. Wenn Sie sie aktualisieren möchten, stellen Sie sicher, dass Ihr Arbeitsbaum sauber ist, und verwenden Sie:

git rm --cached -r .
git reset --hard

Jetzt sind die Zeilenenden in Ihrem Arbeitsbaum korrekt.

John Szakmeister
quelle
Das hat funktioniert, danke! Ich habe die Dokumentation zu gitattributes durchgesehen, aber es war so viel zu lesen, dass ich sie irgendwie beschönigte und nicht finden konnte, wonach ich suchte. Ich fühle mich jetzt dumm.
user11171
Keine Sorge, es passiert! Es ist nicht so leicht zu finden, wie es wahrscheinlich sein sollte. :-)
John Szakmeister
11
Dies funktioniert beim .gitattributeserstmaligen Hinzufügen oder Ändern der Einstellung, funktioniert jedoch nicht, wenn der Arbeitsbaum eine andere EOL hat (zumindest bei MsysGit nicht). Dafür scheint es, dass git rm --cached -r .und dann git reset --hardfunktioniert (Warnung: zerstört Ihren Arbeitsbaum). Von help.github.com/articles/dealing-with-line-endings .
Waddlesplash
1
Hat sich an Git etwas geändert, das dies kaputt gemacht hat? Ich habe dies oft verwendet, bin aber jetzt in einem Repository, in dem es nicht funktioniert (Git 2.13.0, Linux). Stattdessen musste ich git add .nach dem Entfernen des Index (unter Berücksichtigung aller zuvor nicht verfolgten Elemente im Arbeitsverzeichnis) vorgehen.
Vossad01
4
Seien Sie vorsichtig mit der git read-tree --empty; git add .Variante. Alle verfolgten Dateien, die von .gitignore ignoriert werden, werden bei Verwendung gelöscht. Die Dokumentation empfiehlt jetztgit add --renormalize .
vossad01
9

Alternativer Ansatz (unterscheidet sich nur im verwendeten Befehl)

Stellen Sie sicher, dass im Repository keine Änderungen anstehen:

$ git status
$ git stash

Ändern Sie dies .gitattributesso, dass sich die CRLF-Interpretation ändert:

$ echo "*.txt  text" >>.gitattributes
$ git commit -m "Made .txt files a subject to CRLF normalization." -- .gitattributes

Daten aus dem Index entfernen und Arbeitsverzeichnis aktualisieren:

$ git rm --cached -r .
$ git reset --hard

Überprüfen Sie die von Git vorgeschlagenen CRLF-Korrekturen:

$ git ls-files --eol
$ git status
$ git diff

Stimmen Sie der Git-Entscheidung zu:

$ git add -u
$ git commit -m "Normalized CRLF for .txt files"

Laden Sie die Änderungen neu, als ob ein sauberer Klon durchgeführt worden wäre:

$ git rm --cached -r .
$ git reset --hard
Gavenkoa
quelle
1
Hinweis: Die --eolOption to git ls-filesist neu in Git 2.8 (nicht mehr so ​​neu, aber einige Leute leiden immer noch unter Git 1.7, sogar Ende 2018!).
Torek
4

Die .gitattributesEinstellungen wirken sich nur auf neue Commits aus. Wenn in diesem Repository kein Verlauf veröffentlicht wurde (keine anderen hängen davon ab), möchten Sie möglicherweise den gesamten Verlauf durchgehen. Unter Unix / Linux können Sie dos2unix(1)alle Dateien in Kombination mit reparieren find(1)und mithilfe des Umschreibens des Verlaufs filter-branch(siehe Diskussion im Git-Buch) sogar den gesamten Verlauf des Projekts bereinigen.

Mit größter Sorgfalt auf einem frischen Klon anwenden. Nehmen Sie Kontakt mit allen Personen auf, die möglicherweise einen Klon haben, und teilen Sie ihnen mit, was Sie tun möchten.

vonbrand
quelle
3
Ich würde generell von dieser Lösung abraten, es sei denn, eine perfekte Geschichte ist wichtig. Es gibt so viele Möglichkeiten, sich in den Fuß zu schießen, indem man die Geschichte neu schreibt. Normalisieren Sie die Dateien im Repo in einem einzigen Commit und lassen Sie .gitattributes die Arbeit von da an erledigen.
Angularsen
@angularsen, wenn es wichtig ist, einen sauberen, brauchbaren Verlauf zu veröffentlichen ... deshalb empfehle ich, an einem sauberen, neuen Klon zu arbeiten und diesen (erneut) zu veröffentlichen, sobald er als vernünftig markiert ist.
vonbrand
1

Die Option * text = auto in .gitattributes versetzt das Git-Repository in einen "unzulässigen Zustand", wenn es Dateien mit CRLF-Zeilenenden (Windows) enthält, die jetzt als Text markiert sind (siehe https://marc.info/?l=git&m) = 154484903528621 & w = 2 ). Die Standardoption zum Renormieren funktioniert mit den LFS-Filtern nicht richtig, daher funktionieren die Anweisungen in den anderen Antworten oder beispielsweise unter https://help.github.com/de/articles/dealing-with-line-endings nicht richtig . Stattdessen haben diese Schritte für uns funktioniert:

Lage:

  • Unter Windows
  • Das Git-Repository enthielt Dateien mit CR- und CRLF-Zeilenenden
  • * Text = auto zu .gitattributes hinzugefügt (also nicht abhängig davon, ob der Benutzer core.crlf = auto unter Windows festgelegt hat)
  • Außerdem wurde -crlf für LFS-verfolgte Dateien in -text geändert, da nicht sicher ist, ob dies erforderlich ist.

    1. Erstellen Sie einen neuen Zweig aus dem Zweig mit dem Zeilenendeproblem (vorausgesetzt, es werden dort keine nicht festgeschriebenen Änderungen vorgenommen): git checkout -b feature / done-stuff-fix-eol
    2. Entfernen Sie die LFS-Filter aus .gitattributes (ersetzen Sie alle 'filter = lfs diff = lfs merge = lfs' durch nichts)
    3. Commit und Push: git commit -a -m "LFS-Filter für EOL-Fix deaktivieren"
    4. Wechseln Sie in einen Nicht-Git-Ordner
    5. LFS global deinstallieren: git lfs deinstallieren
    6. Erstellen Sie einen neuen Repository-Klon: Git-Klon -b Feature / Doing-Stuff-Fix-Eol [Remote-Repository-URL] Fix-Eol
    7. Normalisieren Sie die Zeilenenden: git add --renormalize. (Beachten Sie den Punkt, um alle Dateien neu zu normalisieren.)
    8. Überprüfen Sie nur die richtigen normalisierten Dateien. Es sollte keine Dateien enthalten, die normalerweise von LFS verarbeitet werden!
    9. Commit und Push (speichern Sie den Hash): git commit -m "Fix line endings"
    10. Wechseln Sie in einen Nicht-Git-Ordner
    11. LFS global installieren: git lfs install
    12. Gehen Sie zum ursprünglichen Repository-Klon und ziehen Sie
    13. Checke deinen ursprünglichen Zweig aus: Git Checkout-Funktion / Doing-Stuff
    14. Cherry Pick das EOL Fix Commit und Push: Git Cherry-Pick [Hash]
    15. Löschen Sie den Äol-Zweig und drücken Sie
    16. Löschen Sie den EOL-Repository-Klon (oder bleiben Sie dabei, wenn Sie weitere Zweige reparieren müssen).
Walter Laan
quelle
0

Die merge.renormalizeKonfigurationseinstellung kann hilfreich sein.

Solomon Ucko
quelle