Erzwinge LF eol in Git Repo und Arbeitskopie

170

Ich habe ein Git-Repository auf Github gehostet. Viele der Dateien wurden ursprünglich unter Windows entwickelt, und ich war nicht besonders vorsichtig mit Zeilenenden. Als ich das erste Commit durchführte, hatte ich auch keine Git-Konfiguration, um korrekte Zeilenenden zu erzwingen. Das Ergebnis ist, dass ich eine Reihe von Dateien mit CRLF-Zeilenenden in meinem Github-Repository habe.

Ich entwickle jetzt teilweise unter Linux und möchte die Zeilenenden bereinigen. Wie kann ich sicherstellen, dass die Dateien mit LF auf Github korrekt gespeichert werden und LF in meiner Arbeitskopie enthalten ist?

Ich habe eine .gitattributesDatei eingerichtet, die Folgendes enthält text eol=LF: Ist das korrekt? Kann ich mit diesem rmCommit und Push nur mein lokales Repo erstellen und von Github neu klonen, um den gewünschten Effekt zu erzielen?

Chowlett
quelle
1
Mögliches Duplikat von Git, das LF durch CRLF ersetzt
Lazy Badger
Beides ist nicht ganz das, was ich frage. Ich bin der einzige Entwickler und durchaus bereit, alle meine Maschinen gleich einzurichten. Ich habe ein bestehendes Repo mit einigen bereits festgeschriebenen CRLF-Dateien und ein paar Klone auf verschiedenen Computern. Wie kann ich das Repo und jede Arbeitskopie aktualisieren, sodass es überall LF gibt?
Chowlett
Haben Sie sich diesen Github-Leitfaden angesehen?
Andy

Antworten:

237

Ohne ein paar Informationen darüber, welche Dateien sich in Ihrem Repository befinden (reiner Quellcode, Bilder, ausführbare Dateien, ...), ist es ein bisschen schwierig, die Frage zu beantworten :)

Außerdem gehe ich davon aus, dass Sie bereit sind, standardmäßig LF als Zeilenenden in Ihrem Arbeitsverzeichnis zu verwenden, da Sie sicherstellen möchten, dass Textdateien LF-Zeilenenden in Ihrem .git-Repository haben, ob Sie unter Windows oder Linux arbeiten . In der Tat besser sicher als leid ....

Es gibt jedoch eine bessere Alternative: Profitieren Sie von LF-Zeilenenden in Ihrem Linux-Arbeitsverzeichnis, CRLF-Zeilenenden in Ihrem Windows-Arbeitsverzeichnis UND LF-Zeilenenden in Ihrem Repository.

Da Sie teilweise unter Linux und Windows arbeiten, stellen Sie sicher, dass core.eolauf nativeund eingestellt core.autocrlfist true.

Ersetzen Sie dann den Inhalt Ihrer .gitattributesDatei durch den folgenden

* text=auto

Auf diese Weise kann Git die Konvertierung der automatischen Zeilenenden für Commits und Checkout-Vorgänge für Sie übernehmen. Binärdateien werden nicht geändert. Bei Dateien, die als Textdateien erkannt werden, werden die Zeilenenden im laufenden Betrieb konvertiert.

Da Sie jedoch den Inhalt Ihres Repositorys kennen, können Sie Git helfen und ihm helfen, Textdateien aus Binärdateien zu erkennen.

Wenn Sie an einem C-basierten Bildverarbeitungsprojekt arbeiten, ersetzen Sie den Inhalt Ihrer .gitattributesDatei durch den folgenden

* text=auto
*.txt text
*.c text
*.h text
*.jpg binary

Dadurch wird sichergestellt, dass Dateien mit der Erweiterung c, h oder txt mit LF-Zeilenenden in Ihrem Repo gespeichert werden und native Zeilenenden im Arbeitsverzeichnis haben. JPEG-Dateien werden nicht berührt. Alle anderen profitieren von der gleichen automatischen Filterung wie oben.

Um ein tieferes Verständnis für die inneren Details all dessen zu bekommen, würde ich Ihnen empfehlen, in diesen sehr guten Beitrag "Mind the end of your line" von Tim Clem, einem Githubber, einzutauchen.

Als Beispiel aus der Praxis können Sie auch einen Blick auf dieses Commit werfen , in dem diese Änderungen an einer .gitattributesDatei demonstriert werden.

UPDATE zur Antwort unter Berücksichtigung des folgenden Kommentars

Ich möchte CRLF eigentlich nicht in meinen Windows-Verzeichnissen haben, da meine Linux-Umgebung tatsächlich eine VirtualBox ist, die das Windows-Verzeichnis gemeinsam nutzt

Macht Sinn. Danke für die Klarstellung. In diesem speziellen Kontext reicht die .gitattributesDatei allein nicht aus.

Führen Sie die folgenden Befehle für Ihr Repository aus

$ git config core.eol lf
$ git config core.autocrlf input

Da Ihr Repository von Ihrer Linux- und Windows-Umgebung gemeinsam genutzt wird, wird die lokale Konfigurationsdatei für beide Umgebungen aktualisiert. core.eolstellt sicher, dass Textdateien an der Kasse LF-Zeilenenden tragen. core.autocrlfstellt sicher, dass potenzielle CRLF in Textdateien (die beispielsweise aus einem Kopier- / Einfügevorgang resultieren) in Ihrem Repository in LF konvertiert werden.

Optional können Sie Git unterscheiden helfen , was ist , indem Sie eine Textdatei .gitattributesDatei mit etwas ähnlich der folgenden:

# Autodetect text files
* text=auto

# ...Unless the name matches the following
# overriding patterns

# Definitively text files 
*.txt text
*.c text
*.h text

# Ensure those won't be messed up with
*.jpg binary
*.data binary

Wenn Sie eine .gitattributesDatei erstellen möchten, schreiben Sie sie fest .

Stellen Sie zum Schluss sicher git status, dass "nichts festzuschreiben ist (Arbeitsverzeichnis bereinigt)" , und führen Sie dann den folgenden Vorgang aus

$ git checkout-index --force --all

Dadurch werden Ihre Dateien in Ihrem Arbeitsverzeichnis neu erstellt, wobei Ihre Konfigurationsänderungen und die .gitattributesDatei berücksichtigt werden und möglicherweise übersehene CRLF in Ihren Textdateien ersetzt werden.

Sobald dies erledigt ist, trägt jede Textdatei in Ihrem Arbeitsverzeichnis LF-Zeilenenden und git statussollte das Arbeitsverzeichnis weiterhin als sauber betrachten.

nulltoken
quelle
34
Ich möchte CRLF eigentlich nicht in meinen Windows-Verzeichnissen haben, da meine Linux-Umgebung tatsächlich eine VirtualBox ist, die das Windows-Verzeichnis gemeinsam nutzt. und während Notepad ++ usw. unter Windows nur mit LF umgehen kann, viist CRLF weniger zufrieden. Möchte ich es nur so ändern, dass core.autocrlfes false(oder input) ist?
Chowlett
5
Hervorragende Antwort. Ein kurzer Hinweis für alle anderen Benutzer dieses Setups: Die Zeile "* text = auto" sollte die erste Zeile in Ihrer .gitattributes-Datei sein, damit nachfolgende Zeilen diese Einstellung überschreiben können.
Ari Patrick
9
@CMCDragonkai Abhängig von Ihrer Shell git checkout-index --force --allkann es besser funktionieren. Der zweite Punkt sieht in Bezug auf die ursprüngliche Frage etwas unangebracht aus. Wie wäre es mit einer speziellen Frage?
Nulltoken
8
Ich verstehe nicht, warum .gitattributes den Fall der Freigabe einer Arbeitskopie zwischen Linux und Windows nicht behandeln kann. Können wir nicht das gleiche Ergebnis wie in Ihrer Antwort über und festlegen textund eol=lferzielen ? core.eolcore.autocrlf
DanielSank
10
git checkout-index --force --alltut nichts für mich Was funktioniert, ist die Liste der Befehle in den GitHub-Anweisungen zur Behebung dieses Problems.
Roman Starkov
126

Ab Git 2.10 (veröffentlicht am 03.09.2016) ist es nicht erforderlich, jede Textdatei einzeln aufzulisten. Git 2.10 hat das Verhalten von text = auto zusammen mit eol = lf behoben . Quelle .

.gitattributes Datei im Stammverzeichnis Ihres Git-Repositorys:

* text=auto eol=lf

Fügen Sie es hinzu und legen Sie es fest.

Anschließend können Sie die folgenden Schritte ausführen, und alle Dateien werden jetzt normalisiert:

git rm --cached -r .  # Remove every file from git's index.
git reset --hard      # Rewrite git's index to pick up all the new line endings.

Quelle: Antwort von Kenorb .

koppor
quelle
7
Git 2.10 hat am 3. September 2016. veröffentlicht
stil
Ich habe dies ausgeführt und es hat alle meine Nicht-Text-Dateien gemauert
Anthony
Sie können den Binärmodus für bestimmte Dateien explizit festlegen. - Ich frage mich, warum die automatische Erkennung bei einigen Dateien (immer noch?!)
Fehlerhaft ist
Dies sollte die akzeptierte Antwort sein.
CletusW
25

Um LF-Zeilenenden für alle Textdateien zu erzwingen, können Sie eine .gitattributesDatei in der obersten Ebene Ihres Repositorys mit den folgenden Zeilen erstellen (nach Bedarf ändern):

# Ensure all C and PHP files use LF.
*.c         eol=lf
*.php       eol=lf

Dadurch wird sichergestellt, dass alle Dateien, die Git als Textdateien betrachtet, normalisierte ( LF) Zeilenenden im Repository haben (normalerweise core.eolsteuert die Konfiguration, welche Sie standardmäßig haben).

Basierend auf den neuen Attributeinstellungen sollten alle Textdateien, die CRLFs enthalten, von Git normalisiert werden. Wenn dies nicht automatisch geschieht, können Sie ein Repository nach dem Ändern der Zeilenenden manuell aktualisieren, sodass Sie das Arbeitsverzeichnis mithilfe der folgenden Schritte erneut scannen und festschreiben können (vorausgesetzt, das Arbeitsverzeichnis ist sauber):

$ echo "* text=auto" >> .gitattributes
$ 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"

oder gemäß GitHub-Dokumentation :

git add . -u
git commit -m "Saving files before refreshing line endings"
git rm --cached -r . # Remove every file from Git's index.
git reset --hard # Rewrite the Git index to pick up all the new line endings.
git add . # Add all your changed files back, and prepare them for a commit.
git commit -m "Normalize all the line endings" # Commit the changes to your repository.

Siehe auch: @ Charles Bailey Post .

Wenn Sie außerdem ausschließen möchten, dass Dateien nicht als Text behandelt werden, deaktivieren Sie deren Textattribut, z

manual.pdf      -text

Oder markieren Sie es explizit als binär:

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

Eine erweiterte Git-Normalisierungsdatei finden Sie .gitattributesunter Drupal-Kern :

# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048

# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.

# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
#   - Exposed by default in `git diff --color` on the CLI.
#   - Validate with `git diff --check`.
#   - Deny applying with `git apply --whitespace=error-all`.
#   - Fix automatically with `git apply --whitespace=fix`.

*.config  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.html    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.js      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.php     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.po      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.script  text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh      text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.sql     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme   text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php
*.twig    text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml     text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2

# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.eot     -text diff
*.exe     -text diff
*.gif     -text diff
*.gz      -text diff
*.ico     -text diff
*.jpeg    -text diff
*.jpg     -text diff
*.otf     -text diff
*.phar    -text diff
*.png     -text diff
*.svgz    -text diff
*.ttf     -text diff
*.woff    -text diff
*.woff2   -text diff

Siehe auch:

Kenorb
quelle
2
1. text=autoist irreführend. Sie können nicht text=autound eolzusammen verwenden. Durch die Einstellung wird eoldie automatische Erkennung von Textdateien deaktiviert. Aus diesem Grund müssen Sie alle diese Dateitypen angeben. Wenn autoaktiviert wäre, würden Sie das alles nicht brauchen. 2. Du brauchst textund nicht eol=lf. eol=lfeffektiv setzt text.
Ben
2
2. Was @Ben gesagt hat, diese Konfiguration ist derzeit falsch und gefährlich, wenn Sie nicht alle Binärdateien explizit markieren.
Michael R
1
Ich habe gelesen, dass * text=auto eol=lfder erste von text=autoüberschrieben wird eol=lf. Wo haben Sie diese Funktion gefunden? Hier ist meine Quelle: stackoverflow.com/questions/29435156/…
CMCDragonkai
Aus * text=auto eol=lfdem Beispiel entfernt, da es auch aus Drupal entfernt wurde . Entfernen Sie auch Kommentare.
Kenorb
4
Es ist wichtig zu beachten, dass das, was @Ben gesagt hat, nicht mehr wahr ist und es immer ein Fehler war - kein beabsichtigtes Verhalten.
Semmel