English ▾ Themen ▾ Neueste Version ▾ gitfaq zuletzt aktualisiert in 2.46.0

NAME

gitfaq - Häufig gestellte Fragen zur Verwendung von Git

SYNOPSIS

gitfaq

BESCHREIBUNG

Die Beispiele in diesem FAQ gehen von einer Standard-POSIX-Shell wie bash oder dash und einem Benutzer namens A U Thor aus, der das Konto author beim Hosting-Provider git.example.org hat.

Konfiguration

Was sollte ich in user.name eintragen?

Sie sollten Ihren persönlichen Namen eintragen, üblicherweise eine Form mit Vor- und Nachnamen. Zum Beispiel verwendet der aktuelle Maintainer von Git "Junio C Hamano". Dies ist der Namensbestandteil, der in jedem Commit, den Sie erstellen, gespeichert wird.

Diese Konfiguration hat keinerlei Einfluss auf die Authentifizierung bei entfernten Diensten; dazu siehe credential.username in git-config[1].

Was macht http.postBuffer eigentlich?

Diese Option ändert die Größe des Puffers, den Git beim Senden von Daten über HTTP oder HTTPS an ein Remote-Repository verwendet. Wenn die Daten größer als diese Größe sind, verwendet libcurl, das die HTTP-Unterstützung für Git handhabt, eine Chunked Transfer Encoding, da die Größe der gesendeten Daten im Voraus nicht bekannt ist.

Das Belassen dieses Werts bei der Standardgröße ist in Ordnung, es sei denn, Sie wissen, dass entweder der Remote-Server oder ein Proxy dazwischen HTTP/1.1 (welches die Chunked Transfer Encoding eingeführt hat) nicht unterstützt oder bekanntermaßen fehlerhaft mit gechunkten Daten ist. Dies wird oft (fälschlicherweise) als Lösung für generische Push-Probleme vorgeschlagen, aber da fast jeder Server und Proxy mindestens HTTP/1.1 unterstützt, löst das Erhöhen dieses Werts normalerweise die meisten Push-Probleme nicht. Ein Server oder Proxy, der HTTP/1.1 und Chunked Transfer Encoding nicht korrekt unterstützt, wäre heute im Internet nicht sehr nützlich, da er viel Verkehr brechen würde.

Beachten Sie, dass die Erhöhung dieses Werts den Speicherbedarf bei jedem relevanten Push, den Git über HTTP oder HTTPS durchführt, erhöht, da der gesamte Puffer zugewiesen wird, unabhängig davon, ob er vollständig verwendet wird oder nicht. Daher ist es am besten, ihn beim Standardwert zu belassen, es sei denn, Sie sind sicher, dass Sie einen anderen Wert benötigen.

Wie konfiguriere ich einen anderen Editor?

Wenn Sie keinen spezifischen Editor für Git festgelegt haben, verwendet Git standardmäßig den Editor, den Sie über die Umgebungsvariablen VISUAL oder EDITOR konfiguriert haben, oder falls keiner angegeben ist, den Systemstandard (der normalerweise vi ist). Da einige Leute vi als schwierig zu bedienen empfinden oder einen anderen Editor bevorzugen, kann es wünschenswert sein, den verwendeten Editor zu ändern.

Wenn Sie einen allgemeinen Editor für die meisten Programme konfigurieren möchten, die einen benötigen, können Sie Ihre Shell-Konfiguration (z. B. ~/.bashrc oder ~/.zshenv) bearbeiten, um eine Zeile einzufügen, die die Umgebungsvariable EDITOR oder VISUAL auf einen geeigneten Wert setzt. Wenn Sie beispielsweise nano bevorzugen, könnten Sie Folgendes schreiben:

export VISUAL=nano

Wenn Sie einen Editor speziell für Git konfigurieren möchten, können Sie entweder den Konfigurationswert core.editor oder die Umgebungsvariable GIT_EDITOR setzen. Weitere Details zur Reihenfolge, in der diese Optionen berücksichtigt werden, finden Sie in git-var[1].

Beachten Sie, dass der Editorwert in allen Fällen an die Shell übergeben wird, sodass alle Argumente mit Leerzeichen entsprechend zitiert werden sollten. Zusätzlich gilt: Wenn Ihr Editor beim Aufruf normalerweise vom Terminal entkoppelt wird, sollten Sie ihn mit einem Argument angeben, das dies verhindert, andernfalls sieht Git keine Änderungen. Ein Beispiel für eine Konfiguration, die beide Probleme unter Windows adressiert, ist die Konfiguration "C:\Program Files\Vim\gvim.exe" --nofork, die den Dateinamen mit Leerzeichen zitiert und die Option --nofork angibt, um die Hintergrundausführung des Prozesses zu vermeiden.

Anmeldedaten

Wie gebe ich meine Anmeldedaten beim Pushen über HTTP an?

Der einfachste Weg, dies zu tun, ist die Verwendung eines Credential-Helpers über die Konfiguration credential.helper. Die meisten Systeme bieten eine Standardauswahl zur Integration mit dem System-Credential-Manager. Zum Beispiel bietet Git für Windows den Credential-Manager wincred, macOS hat den Credential-Manager osxkeychain und Unix-Systeme mit einer Standard-Desktop-Umgebung können den Credential-Manager libsecret verwenden. Alle diese speichern Anmeldedaten in einem verschlüsselten Speicher, um Ihre Passwörter oder Tokens sicher aufzubewahren.

Zusätzlich können Sie den store Credential-Manager verwenden, der Anmeldedaten in einer Datei in Ihrem Home-Verzeichnis speichert, oder den cache Credential-Manager, der Ihre Anmeldedaten nicht dauerhaft speichert, aber verhindert, dass Sie für eine bestimmte Zeit danach gefragt werden.

Sie können auch einfach Ihr Passwort eingeben, wenn Sie dazu aufgefordert werden. Obwohl es möglich ist, das Passwort (das prozentkodiert sein muss) in die URL einzufügen, ist dies nicht besonders sicher und kann zur versehentlichen Offenlegung von Anmeldedaten führen, daher wird es nicht empfohlen.

Wie lese ich ein Passwort oder Token aus einer Umgebungsvariablen?

Die Konfigurationsoption credential.helper kann auch einen beliebigen Shell-Befehl annehmen, der das Credential-Protokoll auf der Standardausgabe erzeugt. Dies ist nützlich, wenn Anmeldedaten in einen Container übergeben werden, zum Beispiel.

Ein solcher Shell-Befehl kann angegeben werden, indem der Optionswert mit einem Ausrufezeichen beginnt. Wenn Ihr Passwort oder Token in GIT_TOKEN gespeichert wäre, könnten Sie den folgenden Befehl ausführen, um Ihren Credential-Helper einzurichten:

$ git config credential.helper \
	'!f() { echo username=author; echo "password=$GIT_TOKEN"; };f'
Wie ändere ich das Passwort oder Token, das ich in meinem Credential-Manager gespeichert habe?

Normalerweise löscht Git das Passwort oder Token, wenn es ungültig ist, und fragt nach einem neuen. Es gibt jedoch Fälle, in denen dies nicht immer geschieht. Um das Passwort oder Token zu ändern, können Sie die vorhandenen Anmeldedaten löschen, und Git wird dann nach neuen fragen. Zum Löschen von Anmeldedaten verwenden Sie eine Syntax wie die folgende (wobei Sie Ihren Benutzernamen und den Hostnamen ersetzen):

$ echo url=https://author@git.example.org | git credential reject
Wie verwende ich mehrere Konten beim selben Hosting-Provider über HTTP?

Normalerweise ist der einfachste Weg, zwischen diesen Konten zu unterscheiden, die Verwendung des Benutzernamens in der URL. Wenn Sie beispielsweise die Konten author und committer auf git.example.org haben, können Sie die URLs https://author@git.example.org/org1/project1.git und https://committer@git.example.org/org2/project2.git verwenden. Auf diese Weise versucht der Credential-Helper automatisch, die richtigen Anmeldedaten für Ihr Konto zu finden. Wenn Sie bereits ein Remote-Repository eingerichtet haben, können Sie die URL mit etwas wie git remote set-url origin https://author@git.example.org/org1/project1.git ändern (siehe git-remote[1] für Details).

Wie verwende ich mehrere Konten beim selben Hosting-Provider über SSH?

Bei den meisten Hosting-Providern, die SSH unterstützen, identifiziert ein einzelnes Schlüsselpaar eindeutig einen Benutzer. Um mehrere Konten zu verwenden, ist es daher notwendig, für jedes Konto ein Schlüsselpaar zu erstellen. Wenn Sie eine einigermaßen moderne OpenSSH-Version verwenden, können Sie ein neues Schlüsselpaar mit etwas wie ssh-keygen -t ed25519 -f ~/.ssh/id_committer erstellen. Sie können dann den öffentlichen Schlüssel (in diesem Fall ~/.ssh/id_committer.pub; beachten Sie die .pub-Erweiterung) beim Hosting-Provider registrieren.

Die meisten Hosting-Provider verwenden ein einziges SSH-Konto zum Pushen; das heißt, alle Benutzer pushen zum git-Konto (z. B. git@git.example.org). Wenn dies bei Ihrem Provider der Fall ist, können Sie mehrere Aliase in SSH einrichten, um klarzustellen, welches Schlüsselpaar verwendet werden soll. Zum Beispiel könnten Sie etwas wie das Folgende in ~/.ssh/config schreiben, wobei Sie die entsprechende private Schlüsseldatei ersetzen:

# This is the account for author on git.example.org.
Host example_author
	HostName git.example.org
	User git
	# This is the key pair registered for author with git.example.org.
	IdentityFile ~/.ssh/id_author
	IdentitiesOnly yes
# This is the account for committer on git.example.org.
Host example_committer
	HostName git.example.org
	User git
	# This is the key pair registered for committer with git.example.org.
	IdentityFile ~/.ssh/id_committer
	IdentitiesOnly yes

Dann können Sie Ihre Push-URL anpassen, um git@example_author oder git@example_committer anstelle von git@example.org zu verwenden (z. B. git remote set-url git@example_author:org1/project1.git).

Übertragungen

Wie synchronisiere ich einen Arbeitsbaum über Systeme hinweg?

Entscheiden Sie zunächst, ob Sie dies überhaupt tun möchten. Git funktioniert am besten, wenn Sie Ihre Arbeit mit den üblichen Befehlen git push und git fetch pushen oder ziehen und ist nicht dafür ausgelegt, einen Arbeitsbaum über Systeme hinweg zu teilen. Dies ist potenziell riskant und kann in einigen Fällen zu Repository-Beschädigungen oder Datenverlust führen.

Normalerweise führt dies dazu, dass git status jede Datei im Arbeitsbaum neu lesen muss. Darüber hinaus erlaubt das Sicherheitsmodell von Git nicht, einen Arbeitsbaum über nicht vertrauenswürdige Benutzer hinweg zu teilen, daher ist es nur sicher, einen Arbeitsbaum zu synchronisieren, wenn er nur von einem einzigen Benutzer auf allen Maschinen verwendet wird.

Es ist wichtig, keinen Cloud-Synchronisierungsdienst zum Synchronisieren von Teilen eines Git-Repositorys zu verwenden, da dies zu Beschädigungen führen kann, wie z. B. fehlende Objekte, geänderte oder hinzugefügte Dateien, defekte Refs und eine Vielzahl anderer Probleme. Diese Dienste synchronisieren tendenziell Datei für Datei kontinuierlich und verstehen die Struktur eines Git-Repositorys nicht. Dies ist besonders schlecht, wenn sie das Repository mitten in einer Aktualisierung synchronisieren, da dies sehr wahrscheinlich zu unvollständigen oder teilweisen Aktualisierungen und damit zu Datenverlust führt.

Ein Beispiel für die Art von Beschädigung, die auftreten kann, sind Konflikte über den Zustand von Refs, so dass beide Seiten unterschiedliche Commits in einem Branch haben, den die andere Seite nicht hat. Dies kann dazu führen, dass wichtige Objekte nicht mehr referenziert und möglicherweise von git gc bereinigt werden, was zu Datenverlust führt.

Daher ist es besser, Ihre Arbeit entweder zum anderen System oder zu einem zentralen Server über den normalen Push- und Pull-Mechanismus zu pushen. Dies bewahrt jedoch nicht immer wichtige Daten wie Stashes, daher ziehen es einige Leute vor, einen Arbeitsbaum über Systeme hinweg zu teilen.

Wenn Sie dies tun, ist der empfohlene Ansatz die Verwendung von rsync -a --delete-after (idealerweise mit einer verschlüsselten Verbindung wie mit ssh) auf dem Stammverzeichnis des Repositorys. Sie sollten dabei mehrere Dinge sicherstellen:

  • Wenn Sie zusätzliche Arbeitsbäume oder ein separates Git-Verzeichnis haben, müssen diese gleichzeitig mit dem Hauptarbeitsbaum und dem Repository synchronisiert werden.

  • Sie sind damit einverstanden, dass das Zielverzeichnis eine exakte Kopie des Quellverzeichnisses ist und **bereits vorhandene Daten gelöscht werden**.

  • Das Repository (einschließlich aller Arbeitsbäume und des Git-Verzeichnisses) befindet sich während der Übertragung in einem Ruhezustand (d. h. es finden keinerlei Operationen darauf statt, einschließlich Hintergrundoperationen wie git gc und Operationen, die von Ihrem Editor aufgerufen werden).

    Beachten Sie, dass die Synchronisation auf diese Weise selbst mit diesen Empfehlungen ein gewisses Risiko birgt, da sie die normale Integritätsprüfung von Git für Repositories umgeht. Daher sind Backups ratsam. Möglicherweise möchten Sie auch nach der Synchronisation eine git fsck ausführen, um die Integrität Ihrer Daten auf dem Zielsystem zu überprüfen.

Häufige Probleme

Ich habe im letzten Commit einen Fehler gemacht. Wie kann ich ihn ändern?

Sie können die entsprechende Änderung in Ihrem Arbeitsbaum vornehmen, git add <Datei> oder git rm <Datei> ausführen, um sie zu stagen, und dann git commit --amend. Ihre Änderung wird in den Commit aufgenommen, und Sie werden aufgefordert, die Commit-Nachricht erneut zu bearbeiten. Wenn Sie die ursprüngliche Nachricht wörtlich verwenden möchten, können Sie zusätzlich die Option --no-edit für git commit verwenden oder einfach speichern und beenden, wenn Ihr Editor geöffnet wird.

Ich habe eine fehlerhafte Änderung gemacht und sie wurde in den Hauptbranch übernommen. Wie kann ich sie rückgängig machen?

Der übliche Weg, damit umzugehen, ist die Verwendung von git revert. Dies bewahrt die Historie, dass die ursprüngliche Änderung gemacht wurde und ein wertvoller Beitrag war, führt aber auch einen neuen Commit ein, der diese Änderungen rückgängig macht, weil die ursprüngliche Änderung ein Problem hatte. Die Commit-Nachricht des Reverts gibt den Commit an, der rückgängig gemacht wurde, und wird normalerweise bearbeitet, um eine Erklärung dafür zu enthalten, warum der Revert erfolgte.

Wie ignoriere ich Änderungen an einer verfolgten Datei?

Git bietet keine Möglichkeit, dies zu tun. Der Grund ist, dass Git, wenn es eine Datei überschreiben muss, z. B. während eines Checkouts, nicht weiß, ob die Änderungen an der Datei wertvoll sind und behalten werden sollten, oder ob sie irrelevant sind und sicher zerstört werden können. Daher muss es den sicheren Weg gehen und sie immer beibehalten.

Es ist verlockend, bestimmte Funktionen von git update-index zu verwenden, nämlich die Bits `assume-unchanged` und `skip-worktree`, aber diese funktionieren für diesen Zweck nicht richtig und sollten nicht so verwendet werden.

Wenn Ihr Ziel darin besteht, eine Konfigurationsdatei zu ändern, kann es oft hilfreich sein, eine Datei im Repository zu haben, die eine Vorlage oder Standardeinstellungen enthält, die dann kopiert und nach Bedarf geändert werden können. Diese zweite, geänderte Datei wird normalerweise ignoriert, um ein versehentliches Committen zu verhindern.

Ich habe Git gebeten, verschiedene Dateien zu ignorieren, aber sie werden immer noch verfolgt.

Eine gitignore-Datei stellt sicher, dass bestimmte Dateien, die nicht von Git verfolgt werden, ungetrackt bleiben. Manchmal können jedoch bestimmte Dateien bereits getrackt worden sein, bevor sie in die .gitignore-Datei aufgenommen wurden, daher bleiben sie getrackt. Um Dateien/Muster zu untracen und zu ignorieren, verwenden Sie git rm --cached <file/pattern> und fügen Sie ein Muster zur .gitignore hinzu, das der <Datei> entspricht. Weitere Details finden Sie in gitignore[5].

Wie weiß ich, ob ich einen Fetch oder einen Pull machen möchte?

Ein Fetch speichert eine Kopie der neuesten Änderungen aus dem Remote-Repository, ohne den Arbeitsbaum oder den aktuellen Branch zu ändern. Sie können dann in aller Ruhe die Upstream-Änderungen überprüfen, zusammenführen, darauf rebasen oder ignorieren. Ein Pull besteht aus einem Fetch, gefolgt sofort von einem Merge oder Rebase. Siehe git-pull[1].

Kann ich einen Proxy mit Git verwenden?

Ja, Git unterstützt die Verwendung von Proxys. Git beachtet die üblichen Umgebungsvariablen http_proxy, https_proxy und no_proxy, die unter Unix üblich sind, und es kann auch mit http.proxy und ähnlichen Optionen für HTTPS konfiguriert werden (siehe git-config[1]). Die Optionen http.proxy und verwandte Optionen können pro URL-Muster angepasst werden. Darüber hinaus kann Git theoretisch normal mit transparenten Proxys im Netzwerk funktionieren.

Für SSH kann Git einen Proxy mithilfe von OpenSSH's ProxyCommand unterstützen. Häufig verwendete Werkzeuge sind netcat und socat. Sie müssen jedoch so konfiguriert sein, dass sie nicht beendet werden, wenn sie EOF auf Standardeingabe sehen, was normalerweise bedeutet, dass netcat -q benötigt und socat ein Timeout mit etwas wie -t 10 benötigt. Dies ist erforderlich, da der Git SSH-Server weiß, dass keine weiteren Anfragen gestellt werden, indem er ein EOF auf Standardeingabe erhält, aber wenn dies geschieht, hat der Server die endgültige Anfrage möglicherweise noch nicht verarbeitet, sodass das Abbrechen der Verbindung zu diesem Zeitpunkt die Anfrage unterbrechen würde.

Ein Beispiel für einen Konfigurationseintrag in ~/.ssh/config mit einem HTTP-Proxy könnte so aussehen:

Host git.example.org
    User git
    ProxyCommand socat -t 10 - PROXY:proxy.example.org:%h:%p,proxyport=8080

Beachten Sie, dass der Proxy in allen Fällen vollständig transparent sein muss, damit Git ordnungsgemäß funktioniert. Der Proxy darf die Verbindung in keiner Weise ändern, manipulieren oder puffern, sonst wird Git mit ziemlicher Sicherheit nicht funktionieren. Beachten Sie, dass viele Proxys, einschließlich vieler TLS-Middleboxen, Windows-Antiviren- und Firewall-Programme außer Windows Defender und Windows Firewall sowie Filterproxys, diesen Standard nicht erfüllen und infolgedessen Git beschädigen. Aufgrund der vielen Berichte über Probleme und ihrer schlechten Sicherheitshistorie raten wir von der Verwendung dieser Software- und Geräteklassen ab.

Zusammenführen und Rebasen

Welche Probleme können beim Zusammenführen von langlebigen Branches mit Squash-Merges auftreten?

Im Allgemeinen können eine Vielzahl von Problemen auftreten, wenn Squash-Merges verwendet werden, um zwei Branches mehrmals zusammenzuführen. Dazu gehören das Auftreten zusätzlicher Commits in der Ausgabe von git log, in einer GUI oder bei Verwendung der ...-Notation zur Angabe eines Bereichs, sowie die Möglichkeit, Konflikte immer wieder neu lösen zu müssen.

Wenn Git einen normalen Merge zwischen zwei Branches durchführt, werden genau drei Punkte betrachtet: die beiden Branches und ein dritter Commit, der sogenannte *Merge-Basis*, der normalerweise der gemeinsame Vorfahre der Commits ist. Das Ergebnis des Merges ist die Summe der Änderungen zwischen der Merge-Basis und jedem Head. Wenn Sie zwei Branches mit einem normalen Merge-Commit zusammenführen, entsteht ein neuer Commit, der als Merge-Basis fungiert, wenn sie erneut zusammengeführt werden, da es nun einen neuen gemeinsamen Vorfahren gibt. Git muss keine Änderungen berücksichtigen, die vor der Merge-Basis aufgetreten sind, sodass Sie keine Konflikte neu lösen müssen, die Sie zuvor gelöst haben.

Wenn Sie einen Squash-Merge durchführen, wird kein Merge-Commit erstellt; stattdessen werden die Änderungen von einer Seite als regulärer Commit auf die andere Seite angewendet. Das bedeutet, dass sich die Merge-Basis für diese Branches nicht geändert hat, und wenn Git zum nächsten Merge übergeht, berücksichtigt es alle Änderungen, die es beim letzten Mal berücksichtigt hat, plus die neuen Änderungen. Das bedeutet, dass Konflikte möglicherweise erneut gelöst werden müssen. Ähnlich wird alles, was die ...-Notation in git diff, git log oder einer GUI verwendet, dazu führen, dass alle Änderungen seit der ursprünglichen Merge-Basis angezeigt werden.

Daher ist es am besten, immer einen regulären Merge-Commit zu verwenden, wenn Sie zwei langlebige Branches wiederholt zusammenführen möchten.

Wenn ich eine Änderung an zwei Branches vornehme, sie aber an einem rückgängig mache, warum enthält der Merge dieser Branches die Änderung?

Standardmäßig verwendet Git beim Zusammenführen eine Strategie namens ort, die einen ausgefeilten Drei-Wege-Merge durchführt. In einem solchen Fall betrachtet Git beim Ausführen des Merges genau drei Punkte: die beiden Heads und einen dritten Punkt, die *Merge-Basis*, die normalerweise der gemeinsame Vorfahre dieser Commits ist. Git berücksichtigt überhaupt keine Historie oder einzelne Commits, die auf diesen Branches stattgefunden haben.

Infolgedessen, wenn beide Seiten eine Änderung haben und eine Seite diese Änderung rückgängig gemacht hat, ist das Ergebnis, die Änderung einzubeziehen. Dies liegt daran, dass sich der Code auf einer Seite geändert hat und auf der anderen Seite keine Nettoänderung vorhanden ist. In diesem Szenario übernimmt Git die Änderung.

Wenn dies für Sie ein Problem darstellt, können Sie stattdessen einen Rebase durchführen, indem Sie den Branch mit dem Revert auf den anderen Branch rebasen. Ein Rebase in diesem Szenario macht die Änderung rückgängig, da ein Rebase jeden einzelnen Commit, einschließlich des Reverts, anwendet. Beachten Sie, dass Rebase die Historie umschreibt, daher sollten Sie veröffentlichte Branches nur rebasen, wenn Sie sich sicher sind, dass Sie damit einverstanden sind. Weitere Details finden Sie im Abschnitt NOTES in git-rebase[1].

Hooks

Wie verwende ich Hooks, um Benutzer daran zu hindern, bestimmte Änderungen vorzunehmen?

Der einzige sichere Ort, um diese Änderungen vorzunehmen, ist im Remote-Repository (d. h. dem Git-Server), normalerweise im Hook pre-receive oder in einem Continuous Integration (CI)-System. Dies sind die Orte, an denen Richtlinien effektiv durchgesetzt werden können.

Es ist üblich, pre-commit-Hooks (oder für Commit-Nachrichten commit-msg-Hooks) zu verwenden, um diese Dinge zu überprüfen. Dies ist großartig, wenn Sie als Einzelentwickler arbeiten und möchten, dass die Werkzeuge Ihnen helfen. Die Verwendung von Hooks auf einem Entwicklerrechner ist jedoch keine effektive Richtlinienkontrolle, da ein Benutzer diese Hooks mit --no-verify umgehen kann, ohne bemerkt zu werden (neben verschiedenen anderen Möglichkeiten). Git geht davon aus, dass der Benutzer die Kontrolle über seine lokalen Repositories hat und versucht nicht, dies zu verhindern oder den Benutzer zu verraten.

Darüber hinaus empfinden einige fortgeschrittene Benutzer pre-commit-Hooks als Hindernis für Workflows, die temporäre Commits zum Stagen von Arbeit im Gange verwenden oder Fixup-Commits erstellen. Daher ist es besser, diese Art von Überprüfungen ohnehin auf den Server zu verlagern.

Plattformübergreifende Probleme

Ich bin unter Windows und meine Textdateien werden als binär erkannt.

Git funktioniert am besten, wenn Textdateien als UTF-8 gespeichert werden. Viele Programme unter Windows unterstützen UTF-8, aber einige nicht und verwenden nur das Little-Endian-UTF-16-Format, das Git als binär erkennt. Wenn Sie UTF-8 mit Ihren Programmen nicht verwenden können, können Sie eine Arbeitsbaumkodierung angeben, die angibt, mit welcher Kodierung Ihre Dateien ausgecheckt werden sollen, während Sie diese Dateien trotzdem als UTF-8 im Repository speichern. Dies ermöglicht es Tools wie git-diff[1], wie erwartet zu funktionieren, während Ihre Tools weiterhin funktionieren.

Dazu können Sie ein Muster in gitattributes[5] mit dem Attribut working-tree-encoding angeben. Zum Beispiel setzt das folgende Muster alle C-Dateien auf die Verwendung von UTF-16LE-BOM, was eine gängige Kodierung unter Windows ist:

*.c	working-tree-encoding=UTF-16LE-BOM

Sie müssen git add --renormalize ausführen, damit dies wirksam wird. Beachten Sie, dass, wenn Sie diese Änderungen an einem Projekt vornehmen, das plattformübergreifend verwendet wird, Sie diese wahrscheinlich in einer benutzerspezifischen Konfigurationsdatei oder in $GIT_DIR/info/attributes vornehmen möchten, da die Angabe in einer .gitattributes-Datei im Repository für alle Benutzer des Repositorys gilt.

Siehe den folgenden Eintrag für Informationen zur Normalisierung von Zeilenenden und gitattributes[5] für weitere Informationen zu Attributdateien.

Ich bin unter Windows und git diff zeigt meine Dateien mit einem ^M am Ende an.

Standardmäßig erwartet Git, dass Dateien mit Unix-Zeilenenden gespeichert werden. Als solches wird der Wagenrücklauf (^M), der Teil eines Windows-Zeilenendes ist, angezeigt, da er als nachfolgender Leerraum betrachtet wird. Git zeigt standardmäßig nachfolgenden Leerraum nur auf neuen Zeilen an, nicht auf vorhandenen.

Sie können die Dateien im Repository mit Unix-Zeilenenden speichern und sie automatisch auf die Zeilenenden Ihrer Plattform konvertieren. Um dies zu tun, setzen Sie die Konfigurationsoption core.eol auf native und siehe die Frage zu empfohlenen Speicher-Einstellungen für Informationen darüber, wie Dateien als Text oder Binärdateien konfiguriert werden.

Sie können dieses Verhalten auch mit der Einstellung core.whitespace steuern, wenn Sie die Wagenrückläufe nicht aus Ihren Zeilenenden entfernen möchten.

Warum habe ich eine Datei, die immer als geändert angezeigt wird?

Intern speichert Git Dateinamen immer als Byte-Sequenzen und führt keine Kodierungs- oder Groß-/Kleinschreibung-Umwandlung durch. Windows und macOS führen jedoch standardmäßig eine Groß-/Kleinschreibung-Umwandlung für Dateinamen durch. Infolgedessen ist es möglich, dass mehrere Dateien oder Verzeichnisse vorhanden sind, deren Namen sich nur in der Groß-/Kleinschreibung unterscheiden. Git kann dies problemlos handhaben, aber das Dateisystem kann nur eine dieser Dateien speichern. Wenn Git die andere Datei liest, um ihren Inhalt zu sehen, erscheint sie als geändert.

Es ist am besten, eine der Dateien zu entfernen, so dass Sie nur noch eine Datei haben. Sie können dies mit Befehlen wie den folgenden tun (angenommen, zwei Dateien AFile.txt und afile.txt) auf einem ansonsten sauberen Arbeitsbaum:

$ git rm --cached AFile.txt
$ git commit -m 'Remove files conflicting in case'
$ git checkout .

Dies vermeidet die Berührung der Festplatte, entfernt aber die zusätzliche Datei. Ihr Projekt bevorzugt möglicherweise die Übernahme einer Benennungskonvention, z. B. nur Kleinbuchstaben, um zu verhindern, dass dieses Problem erneut auftritt. Eine solche Konvention kann mit einem pre-receive-Hook oder als Teil eines Continuous Integration (CI)-Systems überprüft werden.

Es ist auch möglich, dass auf jeder Plattform dauerhaft geänderte Dateien auftreten, wenn ein Smudge- oder Clean-Filter auf Ihrem System verwendet wird, aber eine Datei zuvor committet wurde, ohne den Smudge- oder Clean-Filter auszuführen. Um dies zu beheben, führen Sie Folgendes auf einem ansonsten sauberen Arbeitsbaum aus:

$ git add --renormalize .

GIT

Teil der git[1] Suite