Git-Installation und -Konfiguration

Installation

Für iX-Distributionen sollte Git im Standard-Repository vorhanden sein.

Das Paket git-all stellt euch eine vollständige Umgebung für Git bereit. Dieses installiert ihr wie folgt:

$ sudo apt install git-all

Geht es ausschliesslich um Git, genügt das Paket namens git:

$ sudo apt install git

Mit der Bash-Autovervollständigung lässt sich Git auf der Kommandozeile einfacher bedienen. Das entsprechende Paket dazu heisst bash-completion und ihr installiert es wie folgt:

$ sudo apt install bash-completion

Es gibt verschiedene Möglichkeiten, Git auf einem Mac zu installieren. Am einfachsten ist es vermutlich, die Xcode Command Line Tools zu installieren. Hierfür müsst ihr nur git das erste Mal vom Terminal aufrufen:

$ git --version

git-completion könnt ihr mit Homebrew installieren:

Anschließend müsst ihr folgende Zeile in der Datei ~/.bash_profile hinzufügen:

[[ -r "$(brew --prefix)/etc/profile.d/bash_completion.sh" ]] && . "$(brew --prefix)/etc/profile.d/bash_completion.sh"

Ruft dazu https://git-scm.com/download/win auf und startet den passenden Download dazu.

Siehe auch

Konfiguration

Für jede Änderung muss ersichtlich sein, wer diese verursacht hat. Dazu hinterlegt ihr euren Namen und eure E-Mail-Adresse wie folgt:

$ git config --global user.name "NAME"

legt den Namen NAME fest, der mit euren Commit-Transaktionen verknüpft wird.

$ git config --global user.email "EMAIL-ADDRESS"

legt die E-Mail-Adresse EMAIL-ADDRESS fest, die mit euren Commit-Transaktionen verknüpft wird.

Für eine bessere Lesbarkeit der Ausgabe sorgt die Kolorierung der Befehlszeilenausgabe. Diese schaltet ihr mit Hilfe dieses Aufrufs ein:

$ git config --global color.ui auto

aktiviert die Kolorierung der Befehlszeilenausgabe.

Die ~/.gitconfig-Datei

Mit den oben angegebenen Befehlen wird dir folgende ~/.gitconfig-Datei erstellt:

[user]
    name = veit
    email = veit@cusy.io

[color]
    ui = auto

In der ~/.gitconfig-Datei können jedoch auch Aliase festgelegt werden:

[alias]
    st = status
    ci = commit
    br = branch
    co = checkout
    df = diff
    dfs = diff --staged

Auch der Editor lässt sich angeben, z.B. mit:

[core]
    editor = vim

oder für Visual Studio Code mit:

[core]
    editor = code --wait

Bemerkung

Auf macOS müsst ihr zunächst Visual Studio Code starten, dann die Befehlspalette mit +-p öffnen und schließlich den Befehl Install 'code' command in PATH ausführen.

Auch die Hervorhebung von Leerzeichenfehlern in git diff lässt sich konfigurieren:

[core]
    # Highlight whitespace errors in git diff:
    whitespace = tabwidth=4,tab-in-indent,cr-at-eol,trailing-space

Bemerkung

Neben ~/.gitconfig sucht Git seit Version 1.17.12 auch in ~/.config/git/config nach einer globalen Konfigurationsdatei.

Unter Linux kann ~/.config manchmal ein anderer Pfad sein, der durch die Umgebungsvariable XDG_CONFIG_HOME festgelegt wird. Dieses Verhalten ist Teil der Spezifikation der X Desktop Group (XDG). Den anderen Pfad erhaltet ihr mit:

$ echo $XDG_CONFIG_HOME

Siehe auch

Da ihr Optionen an mehreren Ebenen festlegen könnt, möchtet ihr vielleicht nachvollziehen, woher Git einen bestimmten Wert liest. Mit git config --list [1] könnt ihr alle überschriebenen Optionen und Werte auflisten. Dies könnt ihr kombinieren mit --show-scope [2] um zu sehen, woher Git den Wert bezieht:

$ git config --list --show-scope
system  credential.helper=osxkeychain
global  user.name=veit
global  user.email=veit@cusy.io

Ihr könnt auch --show-origin [3] verwenden, um die Namen der Konfigurationsdateien aufzulisten:

$ git config --list --show-origin
file:/opt/homebrew/etc/gitconfig        credential.helper=osxkeychain
file:/Users/veit/.config/git/config     user.name=veit
file:/Users/veit/.config/git/config     user.email=veit@cusy.io

Alternative Konfigurationsdatei

Ihr könnt für bestimmte Arbeitsverzeichnisse andere Konfigurationsdateien verwenden, z.B. um zwischen privaten und beruflichen Projekten zu unterscheiden. Dazu könnt ihr eine lokale Konfiguration in eurem Repository verwenden oder aber Conditional Includes am Ende eurer globalen Konfiguration:


[includeIf "gitdir:~/private"]
path = ~/.config/git/config-private

Dieses Konstrukt sorgt dafür, dass Git zusätzliche Konfigurationen einbezieht oder bestehende überschreibt, wenn ihr in ~/private arbeitet.

Erstellt dazu nun die Datei ~/.config/git/config-private und legt dort eure alternative Konfiguration fest, z.B.:

[user]
    email = kontakt@veit-schiele.de

[core]
    sshCommand = ssh -i ~/.ssh/private_id_rsa

Siehe auch

Anmeldedaten verwalten

Seit der Git-Version 1.7.9 lassen sich die Zugangsdaten zu git-Repositories mit gitcredentials verwalten. Um diese zu nutzen, könnt ihr z.B. folgendes angeben:

$ git config --global credential.helper Cache

Hiermit wird euer Passwort für 15 Minuten im Cache-Speicher gehalten. Der Timeout kann ggf. erhöht werden, z.B. mit:

$ git config --global credential.helper 'cache --timeout=3600'

Unter macOS lässt sich mit osxkeychain die Schlüsselbundverwaltung (Keychain) nutzen um die Zugangsdaten zu speichern. osxkeychain setzt Git in der Version 1.7.10 oder neuer voraus und kann im selben Verzeichnis wie Git installiert werden mit:

$ git credential-osxkeychain
git: 'credential-osxkeychain' is not a git command. See 'git --help'.
$ curl -s -O http://github-media-downloads.s3.amazonaws.com/osx/git-credential-osxkeychain
$ chmod u+x git-credential-osxkeychain
$ sudo mv git-credential-osxkeychain /usr/bin/
Password:
git config --global credential.helper osxkeychain

Dies trägt folgendes in die ~/.gitconfig-Datei ein:

[credential]
    helper = osxkeychain

Für Windows steht der Git Credential Manager (GCM) zur Verfügung. Er ist integriert in Git for Windows und wird standardmäßig mitinstalliert. Zusätzlich besteht jedoch auch ein eigenständiges Installationsprogramm in Releases.

GCM wird mit dem nachfolgenden Aufruf konfiguriert:

$ git credential-manager configure
Configuring component 'Git Credential Manager'...
Configuring component 'Azure Repos provider'...

Dies trägt den [credential]-Abschnitt in eure ~/.gitconfig-Datei ein:

[credential]
    helper =
    helper = C:/Program\\ Files/Git/mingw64/bin/git-credential-manager.exe

Nun öffnet sich beim Clonen eines Repository ein Fenster des GCM und fordert euch zur Eingabe eurer Zugangsdaten auf.

Zudem wird die ~/.gitconfig-Datei ergänzt, z.B. um die folgenden beiden Zeilen:

[credential "https://ce.cusy.io"]
    provider = generic

Bemerkung

Ein umfangreiches Beispiel einer Konfigurationsdatei findet ihr in meinem dotfiles-Repository: .gitconfig.

Die .gitignore-Datei

In der .gitignore-Datei eines Repository könnt ihr Dateien von der Versionsverwaltung ausschließen. Eine typische .gitignore-Datei kann z.B. so aussehen:

/logs/*
!logs/.gitkeep
/tmp
*.swp

Dabei verwendet Git Globbing-Muster, u.a.:

Muster

Beispiel

Erläuterung

**/logs

logs/instance.log, logs/instance/error.log, prod/logs/instance.log

Ihr könnt zwei Sternchen voranstellen um Verzeichnisse an einer beliebigen Stelle im Verzeichnisbaum zu finden.

**/logs/instance.log

logs/instance.log, prod/logs/instance.log aber nicht logs/prod/instance.log

Ihr könnt zwei Sternchen voranstellen um Dateien anhand ihres Namens in einem übergeordneten Verzeichnis zu finden.

*.log

instance.log, error.log, logs/instance.log

Ein Sternchen ist ein Platzhalter für null oder mehr Zeichen.

/logs
!/logs/.gitkeep

/logs/instance.log, /logs/error.log, nicht jedoch /logs/.gitkeep oder /instance.log

Ein vor ein Muster gestelltes Anführungszeichen ignoriert dieses. Wenn eine Datei mit einem Muster übereinstimmt, aber auch mit einem negierenden, das später definiert ist, wird sie nicht ignoriert.

/instance.log

/instance.log, nicht jedoch logs/instance.log

Mit dem vorangestellten Schrägstrich passt das Muster nur zu Dateien im Stammverzeichnis des Repository.

instance.log

instance.log, logs/instance.log

Üblicherweise passen die Muster zu Dateien in jedem Verzeichnis.

instance?.log

instance0.log, instance1.log, aber nicht instance.log oder instance10.log

Ein Fragezeichen passt genau zu einem Zeichen.

instance[0-9].log

instance0.log, instance1.log, aber nicht instance.log oder instance10.log

Eckige Klammern können verwendet werden um ein einzelnes Zeichen aus einem bestimmten Bereich zu finden.

instance[01].log

instance0.log, instance1.log, aber nicht instance2.log oder instance01.log

Eckige Klammern passen auf ein einzelnes Zeichen aus einer bestimmten Menge.

instance[!01].log

instance2.log, aber nicht instance0.log, instance1.log oder instance01.log

Ein Ausrufezeichen kann verwendet werden um ein beliebiges Zeichen aus einer angegebenen Menge zu finden.

logs

logs logs/instance.log prod/logs/instance.log

Wenn kein Schrägstrich anhängt, passt das Muster sowohl auf Dateien als auch auf den Inhalt von Verzeichnissen mit diesem Namen.

logs/

logs/instance.log, logs/prod/instance.log, prod/logs/instance.log

Das Anhängen eines Schrägstrichs zeigt an, dass das Muster ein Verzeichnis ist. Der gesamte Inhalt jedes Verzeichnisses im Repository, das diesem Namen entspricht – einschließlich all seiner Dateien und Unterverzeichnisse – wird ignoriert.

var/**/instance.log

var/instance.log, var/logs/instance.log, nicht jedoch var/logs/instance/error.log

Zwei Sternchen passen zu null oder mehr Verzeichnissen.

logs/instance*/error.log

logs/instance/error.log, logs/instance1/error.log

Wildcards können auch in Verzeichnisnamen verwendet werden.

logs/instance.log

logs/instance.log, nicht jedoch var/logs/instance.log oder instance.log

Muster, die eine Datei in einem bestimmten Verzeichnis angeben, sind relativ zum Stammverzeichnis des Repository.

Git-commit eines leeren Verzeichnisses

In obigem Beispiel seht ihr, dass mit /logs/* keine Inhalte des logs-Verzeichnisses mit Git versioniert werden sollen, in der Folgezeile jedoch eine Ausnahme definiert wird:

!logs/.gitkeep

Diese Angabe erlaubt, dass die Datei .gitkeep mit Git verwaltet werden darf. Damit wird dann auch das logs-Verzeichnis in das Git-Repository übernommen. Diese Hilfskonstruktion ist erforderlich, da leere Verzeichnisse nicht mit Git verwaltet werden können.

Eine andere Möglichkeit besteht darin, in einem leeren Verzeichnis eine .gitignore-Datei mit folgendem Inhalt zu erstellen:

# ignore everything except .gitignore
*
!.gitignore

Dateien zentral mit excludesfile ausschließen

Ihr könnt jedoch auch zentral für alle Git-Repositories Dateien ausschließen. Hierfür wird üblicherweise in der ~/.gitconfig-Datei folgendes angegeben:

[core]

    # Use custom `.gitignore`
    excludesfile = ~/.gitignore
    

Bemerkung

Hilfreiche Vorlagen findet ihr in meinem dotfiles-Repository oder auf der Website gitignore.io.

Ignorieren einer Datei aus dem Repository

Wenn ihr eine Datei ignorieren wollt, die in der Vergangenheit bereits dem Repository hinzugefügt wurde, müsst ihr die Datei aus eurem Repository löschen und dann eine .gitignore-Regel für sie hinzufügen. Die Verwendung der Option --cached bei git rm bedeutet, dass die Datei aus dem Repository gelöscht wird, aber als ignorierte Datei in eurem Arbeitsverzeichnis verbleibt.

$ echo *.log >> .gitignore
$ git rm --cached *.log
rm 'instance.log'
$ git commit -m "Remove log files"

Bemerkung

Ihr könnt die Option --cached weglassen, wenn ihr die Datei sowohl aus dem Repository als auch aus eurem lokalen Dateisystem löschen wollt.

Commit einer ignorierten Datei

Es ist möglich, den Commit einer ignorierten Datei an das Repository mit der Option -f (oder --force) bei git add zu erzwingen:

$ cat data/.gitignore
*
$ git add -f data/iris.csv
$ git commit -m "Force add iris.csv"

Ihr könnt dies in Erwägung ziehen, wenn ihr ein allgemeines Muster (wie *) definiert habt, aber eine bestimmte Datei übertragen wollt. Eine bessere Lösung ist meist jedoch, eine Ausnahme von der allgemeinen Regel zu definieren:

$ echo '!iris.csv' >> data/.gitignore
$ cat data/.gitignore
*
!iris.csv
$ git add data/iris.csv
$ git commit -m "Add iris.csv"

Dieser Ansatz dürfte für euer Team offensichtlicher und weniger verwirrend sein.

Fehlersuche in .gitignore-Dateien

Bei komplizierten .gitignore-Mustern oder bei Mustern, die über mehrere .gitignore-Dateien verteilt sind, kann es schwierig sein, herauszufinden, ob oder warum eine bestimmte Datei ignoriert wird.

Mit dem Aufruf git status --ignored=matching [4] wird der Ausgabe ein Abschnitt Ignorierte Dateien hinzugefügt, der zusätzlich alle von Git ignorierten Dateien und Verzeichnisse beinhaltet:

$ git status --ignored=matching
Auf Branch main
Ignorierte Dateien:
  (benutzen Sie "git add -f <Datei>...", um die Änderungen zum Commit vorzumerken)
    .DS_Store
    docs/.DS_Store
    docs/_build/doctrees/
    docs/_build/html/
    docs/clean-prep/.ipynb_checkpoints/

    nichts zu committen, Arbeitsverzeichnis unverändert

Ihr könnt den Befehl git check-ignore [5] mit der Option -v (Langform: --verbose) verwenden, um festzustellen, welches Muster die Ursache für das Ignorieren einer bestimmten Datei ist:

$ git check-ignore -v data/iris.csv
data/.gitignore:2:!iris.csv data/iris.csv

Obige Ausgabe besteht aus vier Feldern (Trennzeichen sind drei Doppelpunkte und ein Leerzeichen) und beinhaltet:

FILE_CONTAINING_THE_PATTERN

den Namen der Datei, die das Muster enthält.

LINE_NUMBER_OF_THE_PATTERN

die Zeilennummer, in der in der Datei FILE_CONTAINING_THE_PATTERN das Muster gefunden wurde.

PATTERN

das gefundene Muster.

FILE_NAME

den Namen der Datei inklusive Pfad, die Git ignoriert.

Ihr könnt mehrere Dateinamen an git check-ignore übergeben, wenn ihr möchtet, und die Namen selbst müssen nicht einmal den Dateien entsprechen, die in eurem Repository existieren.

Eine vollständige Liste aller ignorierten Dateien erhaltet ihr mit git ls-files --ignored --exclude-standard --others [6]. Mit --exclude-standard werden die Standard-ignore-Dateien gelesen und mit --others werden die nicht-versionierten Dateien statt der versionierten angezeigt:

$ git ls-files --ignored --exclude-standard --others
.DS_Store
_build/doctrees/clean-prep/bulwark.doctree
_build/doctrees/clean-prep/dask-pipeline.doctree
_build/doctrees/clean-prep/deduplicate.doctree

Gelegentlich möchtet ihr vielleicht die globale ~/.gitignore-Datei umgehen um zu sehen, welche Dateien Git unabhängig von eurer Konfiguration immer ignoriert. Ihr könnt dies tun, indem ihr zu einer anderen exclude-Option wechselt, --exclude-per-directory, die nur die .gitignore-Dateien des Repositorys verwendet:

$ git ls-files --ignored --exclude-per-directory=.gitignore --others
docs/_build/doctrees/clean-prep/bulwark.doctree
docs/_build/doctrees/clean-prep/dask-pipeline.doctree
docs/_build/doctrees/clean-prep/deduplicate.doctree

Beachtet, dass die Datei .DS_Store nicht mehr als ignoriert aufgeführt wird.

Wenn ihr --others durch --cached ersetzt, listet git ls-files Dateien auf, die ignoriert werden würden, es sei denn, sie wurden bereits übertragen:

$ git ls-files --ignored --exclude-per-directory=.gitignore --cached
data/iris.csv

Möglicherweise habt ihr solche Dateien, weil jemand sie vor den relevanten Mustern in einer .gitignore-Datei hinzugefügt hat, oder weil jemand sie mit git add --force hinzugefügt hat. So oder so, wenn ihr die Datei nicht mehr mit Git verwalten wollt, könnt ihr sie mit dem folgenden Einzeiler aus der Git-Verwaltung nehmen, sie aber nicht löschen:

$ git ls-files --ignored --exclude-per-directory=.gitignore --cached | xargs -r git rm --cached
rm 'data/iris.csv'