Git-Installation und -Konfiguration#

Installation#

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

$ sudo apt install git-all

Mit der Bash-Autovervollständigung lässt sich Git auf der Kommandozeile einfacher bedienen:

$ 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 ~/.bash_profile hinzufügen:

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

Ihr könnt einfach https://git-scm.com/download/win aufrufen und den passenden Download starten.

Siehe auch

Konfiguration#

$ git config --global user.name "[name]"

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

$ git config --global user.email "[email address]"

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

$ git config --global color.ui auto

aktiviert die Kolorierung der Befehlszeilenausgabe.

Die ~/.gitconfig-Datei#

Mit den oben angegebenen Befehlen kann z.B. folgende Datei erstellt werden:

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

[color]
    diff = auto
    status = auto
    branch = 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 und die Hervorhebung von Leerzeichenfehlern in git diff:

[core]

    editor = vim

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

git diff#

Git diff lässt sich konfigurieren, sodass es auch bei Binärdateien sinnvolle Diffs anzeigen kann.

…für Excel-Dateien#

Hierfür benötigen wir openpyxl und pandas:

$ pipenv install openpyxl pandas

Anschließend können wir in exceltocsv.py pandas.DataFrame.to_csv zum Konvertieren der Excel-Dateien verwenden:

import sys

from io import StringIO

import pandas as pd


for sheet_name in pd.ExcelFile(sys.argv[1]).sheet_names:
    output = StringIO()
    print("Sheet: %s" % sheet_name)
    pd.read_excel(sys.argv[1], sheet_name=sheet_name).to_csv(
        output, header=True, index=False
    )
    print(output.getvalue())

Anschließend wird der globalen Git-Konfiguration ~/.gitconfig folgender Abschnitt hinzugefügt:

[diff "excel"]
    textconv=python3 /PATH/TO/exceltocsv.py
    binary=true

Schließlich wird in der globalen ~/.gitattributes-Datei unser excel-Konverter mit *.xlsx-Dateien verknüpft:

*.xlsx diff=excel

…für PDF-Dateien#

Hierfür wird zusätzlich pdftohtml benötigt. Es kann installiert werden mit

$ sudo apt install poppler-utils
$ brew install pdftohtml

Anschließend wird der globalen Git-Konfiguration ~/.gitconfig folgender Abschnitt hinzugefügt:

[diff "pdf"]
    textconv=pdftohtml -stdout

Schließlich wird in der globalen ~/.gitattributes-Datei unser pdf-Konverter mit *.pdf-Dateien verknüpft:

*.pdf diff=pdf

Nun wird beim Aufruf von git diff die PDF-Datei zunächst konvertiert und dann ein Diff über den Ausgaben des Konverters durchgeführt.

…für Word-Dokumente#

Auch Unterschiede in Word-Dokumenten lassen sich anzeigen. Hierfür kann Pandoc verwendet werden, das einfach installiert werden kann mit

Herunterladen und Installieren der .msi-Datei von GitHub.

$ sudo apt install pandoc
$ brew install pandoc

Anschließend wird der globalen Git-Konfiguration ~/.gitconfig folgender Abschnitt hinzugefügt:

[diff "word"]
        textconv=pandoc --to=markdown
        binary=true
        prompt=false

Schließlich wird in der globalen ~/.gitattributes-Datei unser word-Konverter mit *.docx-Dateien verknüpft:

*.docx diff=word

Die gleiche Vorgehensweise kann auch angewandt werden, um nützliche Diffs von anderen Binärdateien zu erhalten, z.B. *.zip, *.jar und andere Archive mit unzip oder für Änderungen in den Metainformationen von Bildern mit exiv2. Zudem gibt es Konvertierungswerkzeuge für die Umwandlung von *.odf, .doc und anderen Dokumentenformaten in einfachen Text. Für Binärdateien, für die es keinen Konverter gibt, reichen oft auch Strings aus.

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 ihr 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'

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

Er wird konfiguriert mit

$ 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 Git Credential Manager und fodert 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

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 ein:

[credential]
    helper = osxkeychain

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 leerer Ordner#

In obigem Beispiel seht ihr, dass mit /logs/* keine Inhalte des logs-Verzeichnis mit Git versioniert werden sollen, in der Folgezeile jedoch eine Ausnahme definiert wird: !logs/.gitkeep 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 Ordner nicht mit Git verwaltet werden können.

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

# ignore everything except .gitignore
*
!.gitignore

excludesfile#

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, warum eine bestimmte Datei ignoriert wird. Ihr könnt den Befehl git check-ignore mit der Option -v (oder --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

Die Ausgabe zeigt FILE_CONTAINING_THE_PATTERN:LINE_NUMBER_OF_THE_PATTERN:PATTERN FILE_NAME

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.