-
1. Erste Schritte
-
2. Git Grundlagen
-
3. Git Branching
- 3.1 Branches auf einen Blick
- 3.2 Einfaches Branching und Merging
- 3.3 Branch-Management
- 3.4 Branching-Workflows
- 3.5 Remote-Branches
- 3.6 Rebasing
- 3.7 Zusammenfassung
-
4. Git auf dem Server
- 4.1 Die Protokolle
- 4.2 Git auf einem Server einrichten
- 4.3 Erstellung eines SSH-Public-Keys
- 4.4 Einrichten des Servers
- 4.5 Git-Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Von Drittanbietern gehostete Optionen
- 4.10 Zusammenfassung
-
5. Verteiltes Git
-
6. GitHub
-
7. Git Tools
- 7.1 Revisions-Auswahl
- 7.2 Interaktives Stagen
- 7.3 Stashen und Bereinigen
- 7.4 Ihre Arbeit signieren
- 7.5 Suchen
- 7.6 Den Verlauf umschreiben
- 7.7 Reset entzaubert
- 7.8 Fortgeschrittenes Merging
- 7.9 Rerere
- 7.10 Debuggen mit Git
- 7.11 Submodule
- 7.12 Bundling
- 7.13 Replace (Ersetzen)
- 7.14 Anmeldeinformationen speichern
- 7.15 Zusammenfassung
-
8. Git einrichten
- 8.1 Git Konfiguration
- 8.2 Git-Attribute
- 8.3 Git Hooks
- 8.4 Beispiel für Git-forcierte Regeln
- 8.5 Zusammenfassung
-
9. Git und andere Systeme
- 9.1 Git als Client
- 9.2 Migration zu Git
- 9.3 Zusammenfassung
-
10. Git Interna
-
A1. Anhang A: Git in anderen Umgebungen
- A1.1 Grafische Schnittstellen
- A1.2 Git in Visual Studio
- A1.3 Git in Visual Studio Code
- A1.4 Git in IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git in Sublime Text
- A1.6 Git in Bash
- A1.7 Git in Zsh
- A1.8 Git in PowerShell
- A1.9 Zusammenfassung
-
A2. Anhang B: Git in Ihre Anwendungen einbetten
- A2.1 Die Git-Kommandozeile
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Anhang C: Git Kommandos
- A3.1 Setup und Konfiguration
- A3.2 Projekte importieren und erstellen
- A3.3 Einfache Snapshot-Funktionen
- A3.4 Branching und Merging
- A3.5 Projekte gemeinsam nutzen und aktualisieren
- A3.6 Kontrollieren und Vergleichen
- A3.7 Debugging
- A3.8 Patchen bzw. Fehlerkorrektur
- A3.9 E-mails
- A3.10 Externe Systeme
- A3.11 Administration
- A3.12 Basisbefehle
8.2 Git einrichten - Git-Attribute
Git-Attribute
Einige dieser Einstellungen können auch für einen Pfad angegeben werden, so dass Git diese Einstellungen nur für ein Unterverzeichnis oder eine Teilmenge von Dateien anwendet.
Diese pfadspezifischen Einstellungen heißen Git-Attribute und werden entweder in einer .gitattributes
Datei in einem Ihrer Verzeichnisse (normalerweise dem Stammverzeichnis Ihres Projekts) oder in der .git/info/attributes
Datei festgelegt, falls Sie nicht wollen, dass die Attributdatei mit Ihrem Projekt verknüpft wird.
Mit Hilfe von Attributen können Sie beispielsweise separate Merge-Strategien für einzelne Dateien oder Verzeichnisse eines Projekts festlegen, Git sagen, wie man Nicht-Text-Dateien unterscheidet oder den Inhalt von Git filtern lassen, bevor Sie ihn in Git ein- oder auschecken. In diesem Abschnitt erfahren Sie mehr über einige der Attribute, die Sie in Ihrem Git-Projekt auf Ihre Pfade setzen können, und sehen einige Beispiele für die praktische Anwendung dieser Funktion.
Binäre Dateien
Ein toller Kniff, für den Sie Git-Attribute verwenden können, ist das Erkennen von binären Dateien (falls es sonst nicht möglich ist, es herauszufinden) und Git speziell anzuweisen, wie man mit diesen Dateien umgeht. So können beispielsweise einige Textdateien maschinell erzeugt und nicht mehr unterschieden werden, während andere Binärdateien unterschieden werden können. Sie werden sehen, wie Sie Git mitteilen können, welche die richtige ist.
Binärdateien identifizieren
Einige Dateien sehen aus wie Textdateien, sind aber im Grunde genommen wie Binärdateien zu behandeln.
Xcode-Projekte unter macOS enthalten beispielsweise eine Datei, die mit .pbxproj
endet, was im Grunde genommen ein JSON-Datensatz (Klartext JavaScript Datenformat) ist, der von der IDE auf die Festplatte geschrieben wird, Ihre Build-Einstellungen aufzeichnet usw.
Obwohl es sich technisch gesehen um eine Textdatei handelt (weil sie eigentlich komplett UTF-8 ist), wollen Sie sie nicht als solche behandeln, denn es handelt sich hierbei um eine sehr einfache Datenbank – Sie können den Inhalt nicht mergen, wenn zwei Personen ihn ändern sind Unterschiede im Allgemeinen nicht hilfreich.
Die Datei ist für den internen Betrieb auf einem Rechner bestimmt.
Im Prinzip sollten Sie sie wie eine Binärdatei behandeln.
Um Git anzuweisen, alle pbxprojj
Dateien als Binärdaten zu behandeln, fügen Sie die folgende Zeile zu Ihrer .gitattributes
Datei hinzu:
*.pbxproj binary
Jetzt wird Git nicht versuchen, CRLF-Probleme zu konvertieren oder zu beheben; noch wird es versuchen, ein Diff für Änderungen in dieser Datei zu berechnen oder auszugeben, wenn Sie git show
oder git diff
bei Ihrem Projekt ausführen.
Unterschiede in Binärdateien vergleichen
Sie können auch die Git-Attribut-Funktionalität verwenden, um Binärdateien effektiv zu unterscheiden. Dafür müssen Sie Git mitteilen, wie es Ihre Binärdateien in ein Textformat konvertieren soll, das über das normale diff verglichen werden kann.
Zuerst werden Sie diese Technik nutzen, um eines der lästigsten Probleme zu lösen, die es gibt: die Versionskontrolle von Microsoft Word-Dokumenten.
Wenn Sie Word-Dokumente versionieren wollen, können Sie sie in ein Git-Repository legen und ab und zu committen; aber was nützt das?
Wenn Sie git diff
wie gewohnt starten, sehen Sie nur so etwas wie das hier:
$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 88839c4..4afcb7c 100644
Binary files a/chapter1.docx and b/chapter1.docx differ
Sie können zwei Versionen nicht direkt vergleichen, es sei denn, Sie checken sie aus und scannen sie manuell, richtig?
Wie sich herausstellt, kann man das ziemlich gut mit Git-Attributen machen.
Fügen Sie die folgende Zeile in Ihre .gitattributes
Datei ein:
*.docx diff=word
Hiermit erfährt Git, dass jede Datei, die mit diesem Suchmuster übereinstimmt (.docx
), den Filter „word“ verwenden sollte, wenn Sie einen Diff anzeigen lassen wollen, der Änderungen enthält.
Was ist der Filter „word“?
Sie müssen ihn einrichten.
Nachfolgend konfigurieren Sie Git so, dass es das Programm docx2txt
verwendet, um Word-Dokumente in lesbare Textdateien zu konvertieren, die es dann richtig auswertet.
Zuerst müssen Sie docx2txt
installieren. Sie können es von https://sourceforge.net/projects/docx2txt herunterladen.
Folgen Sie den Anweisungen in der INSTALL
Datei, um es an einen Ort zu platzieren, an dem Ihre Shell es finden kann.
Als nächstes schreiben Sie ein Wrapper-Skript, um die Ausgabe in das von Git erwartete Format zu konvertieren.
Erstellen Sie eine Datei namens docx2txt
, irgendwo innerhalb Ihres Pfads und fügen Sie diesen Inhalt hinzu:
#!/bin/bash
docx2txt.pl "$1" -
Vergessen Sie nicht, die Dateirechte mit chmod a+x
zu ändern.
Schließlich können Sie Git so einrichten, dass es dieses Skript verwendet:
$ git config diff.word.textconv docx2txt
Jetzt ist Git darüber informiert, dass es bei dem Versuch, einen Diff zwischen zwei Snapshots zu machen, der Dateien enthält, die auf .docx
enden, diese Dateien durch den „word“ Filter laufen lassen soll, der als docx2txt
Programm definiert ist.
Auf diese Weise entstehen im Vorfeld gute Textversionen Ihrer Word-Dateien, die Sie leichter unterscheiden können.
Hier ist ein Beispiel: Kapitel 1 dieses Buches wurde in das Word-Format konvertiert und in ein Git-Repository committet.
Dann wurde ein neuer Absatz hinzugefügt.
Hier ist das, was git diff
zeigt:
$ git diff
diff --git a/chapter1.docx b/chapter1.docx
index 0b013ca..ba25db5 100644
--- a/chapter1.docx
+++ b/chapter1.docx
@@ -2,6 +2,7 @@
This chapter will be about getting started with Git. We will begin at the beginning by explaining some background on version control tools, then move on to how to get Git running on your system and finally how to get it setup to start working with. At the end of this chapter you should understand why Git is around, why you should use it and you should be all setup to do so.
1.1. About Version Control
What is "version control", and why should you care? Version control is a system that records changes to a file or set of files over time so that you can recall specific versions later. For the examples in this book you will use software source code as the files being version controlled, though in reality you can do this with nearly any type of file on a computer.
+Testing: 1, 2, 3.
If you are a graphic or web designer and want to keep every version of an image or layout (which you would most certainly want to), a Version Control System (VCS) is a very wise thing to use. It allows you to revert files back to a previous state, revert the entire project back to a previous state, compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more. Using a VCS also generally means that if you screw things up or lose files, you can easily recover. In addition, you get all this for very little overhead.
1.1.1. Local Version Control Systems
Many people's version-control method of choice is to copy files into another directory (perhaps a time-stamped directory, if they're clever). This approach is very common because it is so simple, but it is also incredibly error prone. It is easy to forget which directory you're in and accidentally write to the wrong file or copy over files you don't mean to.
Git sagt uns sehr treffend und klar, dass wir die Zeichenkette „Testing: 1, 2, 3.“ hinzugefügt haben, was richtig ist. Was aber nicht perfekt ist: Formatierungsänderungen würden hier nicht angezeigt – aber es offensichtlich, dass es funktioniert.
Ein weiteres spannendes Problem, das Sie auf diese Weise lösen können, ist die Unterscheidung von Bilddateien.
Die eine Methode besteht darin, Bilddateien durch einen Filter zu leiten, der ihre EXIF-Informationen extrahiert – Metadaten, die mit den meisten Bildformaten aufgezeichnet werden.
Nach dem Herunterladen und Installieren des exiftool
Programms können Sie damit die Metadaten Ihrer Bilder in Text umwandeln. So zeigt Ihnen das Diff zumindest eine schriftliche Darstellung der vorgenommenen Änderungen an.
Fügen Sie die folgende Zeile in Ihre .gitattributes
Datei ein:
*.png diff=exif
So konfigurieren Sie Git, um dieses Tool zu verwenden:
$ git config diff.exif.textconv exiftool
Wenn Sie ein Bild in Ihrem Projekt ersetzen und dann git diff
ausführen, sehen Sie etwas ähnliches wie hier:
diff --git a/image.png b/image.png
index 88839c4..4afcb7c 100644
--- a/image.png
+++ b/image.png
@@ -1,12 +1,12 @@
ExifTool Version Number : 7.74
-File Size : 70 kB
-File Modification Date/Time : 2009:04:21 07:02:45-07:00
+File Size : 94 kB
+File Modification Date/Time : 2009:04:21 07:02:43-07:00
File Type : PNG
MIME Type : image/png
-Image Width : 1058
-Image Height : 889
+Image Width : 1056
+Image Height : 827
Bit Depth : 8
Color Type : RGB with Alpha
Sie können leicht erkennen, dass sich sowohl die Dateigröße als auch die Bildgröße geändert haben.
Schlüsselwort-Erweiterung
Die SVN- oder CVS-artige Schlüsselwort-Erweiterung wird oft von Entwicklern gefordert, die mit diesen Systemen arbeiten. Das Hauptproblem in Git ist, dass Sie eine Datei mit Informationen über einen Commit nach dem Committen nicht ändern können, da zuerst die Prüfsumme der Datei von Git ermittelt wird. Wenn die Datei ausgecheckt ist können Sie jedoch Text in sie einfügen und ihn wieder entfernen, bevor er zu einem Commit hinzugefügt wird. Die Git-Attribute stellen Ihnen dafür zwei Möglichkeiten zur Verfügung.
Erstens können Sie die SHA-1-Prüfsumme eines Blobs automatisch in ein $Id$
Feld in der Datei einfügen.
Wird dieses Attribut auf eine Datei oder eine Gruppe von Dateien gesetzt, dann wird Git beim nächsten Auschecken dieses Branchs das entsprechende Feld durch den SHA-1 des Blobs ersetzen.
Dabei muss man beachten, dass es nicht das SHA-1 des Commits ist, sondern das des Blobs an sich.
Fügen Sie die folgende Zeile in Ihre .gitattributes
Datei ein:
*.txt ident
Hinzufügen einer $Id$
Referenz zu einer Testdatei:
$ echo '$Id$' > test.txt
Beim nächsten Auschecken dieser Datei fügt Git den SHA-1 des Blobs ein:
$ rm test.txt
$ git checkout -- test.txt
$ cat test.txt
$Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $
Dieses Ergebnis ist jedoch von begrenztem Nutzen. Wenn Sie die Ersetzung von Schlüsselwörtern in CVS oder Subversion verwendet haben, können Sie einen Datums-Stempel hinzufügen – der SHA-1 ist nicht allzu hilfreich, weil er eher willkürlich ist und Sie nicht erkennen können, ob ein SHA-1 älter oder neuer als ein anderer ist, den Sie sich ansehen.
Es zeigt sich, dass Sie Ihre eigenen Filter schreiben können, um Ersetzungen in Dateien auf einem Commit/Checkout durchzuführen.
Diese werden als „saubere“ (engl. clean) und „verschmutzte“ (engl. smudge) Filter bezeichnet.
In der Datei .gitattributes
können Sie einen Filter für bestimmte Pfade setzen und dann Skripte einrichten, die die Dateien verarbeiten, kurz bevor sie ausgecheckt werden (für „smudge“, siehe Der „smudge“ Filter wird beim Auschecken ausgeführt) und kurz bevor sie zum Commit vorgemerkt werden (für „clean“, siehe Der „clean“ Filter wird ausgeführt, wenn Dateien zum Commit vorgemerkt werden).
Diese Filter können so eingestellt werden, um damit alle möglichen interessanten Aufgaben zu erledigen.
Die ursprüngliche Commit-Meldung dieser Funktion zeigt ein einfaches Anwendungsbeispiel, wie Sie Ihren gesamten C-Quellcode vor dem Commit durch das indent
Programm laufen lassen können.
Sie können es so einrichten, dass das Filterattribut in Ihrer .gitattributes
Datei so gesetzt ist, dass *.c
Dateien mit dem Filter „indent“ gefiltert werden:
*.c filter=indent
Dann weisen Sie Git an, was der „indent“ Filter bei smudge
und clean
bewirkt:
$ git config --global filter.indent.clean indent
$ git config --global filter.indent.smudge cat
Wenn Sie in diesem Fall Dateien committen, die mit *.c
übereinstimmen, wird Git sie das Indent-Programm durchlaufen lassen, bevor es sie der Staging-Area hinzufügt. Dann werden sie durch das cat
Programm laufen, bevor es sie wieder auf die Festplatte auscheckt.
Das cat
Programm macht im Grunde genommen nichts: Es übergibt die gleichen Daten, die es bekommt.
Diese Kombination filtert effektiv alle C-Quellcode-Dateien durch Einrückung (engl. indent
), bevor sie committet werden.
Ein weiteres interessantes Beispiel ist die $Date$
Schlüsselwort-Erweiterung im RCS-Stil.
Um das richtig anzuwenden, benötigen Sie ein kleines Skript, das einen Dateinamen anlegt, das letzte Commit-Datum für dieses Projekt ermittelt und das Datum in die Datei einfügt.
Hier ist ein kleines Ruby-Skript, das das erledigt:
#! /usr/bin/env ruby
data = STDIN.read
last_date = `git log --pretty=format:"%ad" -1`
puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')
Alles, was das Skript macht, ist das neueste Commit-Datum aus dem git log
Befehl zu ermitteln, es in alle $Date$
Zeichenketten zu übertragen, die es in stdin erkennt und die Ergebnisse auszugeben. Es sollte einfach sein, es in der Programmiersprache zu erstellen mit der Sie am besten zurechtkommen.
Sie können diese Datei expand_date
nennen und in Ihren Pfad aufnehmen.
Jetzt müssen Sie einen Filter in Git einrichten (nennen Sie ihn z.B. dater
) und ihm sagen, dass er Ihren expand_date
Filter verwenden soll, um die Dateien beim Auschecken zu bearbeiten (smudge).
Ein Perl-Ausdruck dient dazu, das beim Commit zu bereinigen:
$ git config filter.dater.smudge expand_date
$ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
Dieses Perl-Snippet entfernt alles, was es in einer $Date$
Zeichenkette sieht, um an den Ausgangspunkt zurückzukehren.
Nachdem Ihr Filter jetzt fertig ist, können Sie ihn testen, indem Sie ein Git-Attribut für diese Datei einrichten, das den neuen Filter aktiviert und eine Datei mit Ihrem $Date$
Schlüsselwort erstellen:
date*.txt filter=dater
$ echo '# $Date$' > date_test.txt
Wenn Sie diese Änderungen committen und die Datei erneut auschecken, sehen Sie das Schlüsselwort ordnungsgemäß ersetzt:
$ git add date_test.txt .gitattributes
$ git commit -m "Test date expansion in Git"
$ rm date_test.txt
$ git checkout date_test.txt
$ cat date_test.txt
# $Date: Tue Apr 21 07:26:52 2009 -0700$
Sie sehen, wie leistungsfähig diese Technik für maßgeschneiderte Anwendungen sein kann.
Sie müssen jedoch vorsichtig sein, da die .gitattributes
Datei committed und mit dem Projekt weitergegeben wird, der Treiber (hier: dater
) aber nicht. Es wird also nicht überall funktionieren.
Wenn Sie diese Filter entwerfen, sollten sie, bei fehlerhaften Ergebnissen, problemlos in der Lage sein das Projekt trotzdem einwandfrei laufen zu lassen.
Exportieren Ihres Repositorys
Mit den Daten von Git-Attribute können Sie interessante Aufgaben beim Export eines Archivs Ihres Projekts erledigen.
export-ignore
Sie können Git anweisen, bestimmte Dateien oder Verzeichnisse nicht zu exportieren, wenn Sie ein Archiv erstellen.
Wenn es ein Unterverzeichnis oder eine Datei gibt, die Sie nicht in Ihre Archivdatei aufnehmen möchten, aber in Ihr Projekt einchecken möchten, können Sie diese Dateien über das Attribut export-ignore
bestimmen.
Angenommen, Sie haben einige Testdateien in einem test/
Unterverzeichnis und es ist nicht sinnvoll, sie in den Tarball-Export Ihres Projekts aufzunehmen.
Man kann die folgende Zeile zu der Datei mit den Git-Attributen hinzufügen:
test/ export-ignore
Wenn Sie nun git archive
ausführen, um einen Tarball Ihres Projekts zu erstellen, wird dieses Verzeichnis nicht in das Archiv aufgenommen.
export-subst
Beim Exportieren von Dateien für die Verteilung können Sie die Formatierung und Schlüsselwort-Erweiterung von git log
auf ausgewählte Teile von Dateien anwenden, die mit dem Attribut export-subst
markiert sind.
Wenn Sie beispielsweise eine Datei mit dem Namen LAST_COMMIT
in Ihr Projekt aufnehmen möchten und Metadaten über den letzten Commit automatisch in das Projekt eingespeist werden sollen, sobald git archive
läuft, können Sie beispielsweise Ihre .gitattributes
und LAST_COMMIT
Dateien so einrichten:
LAST_COMMIT export-subst
$ echo 'Last commit date: $Format:%cd by %aN$' > LAST_COMMIT
$ git add LAST_COMMIT .gitattributes
$ git commit -am 'adding LAST_COMMIT file for archives'
Wenn Sie git archive
ausführen, sieht der Inhalt der archivierten Datei so aus:
$ git archive HEAD | tar xCf ../deployment-testing -
$ cat ../deployment-testing/LAST_COMMIT
Last commit date: Tue Apr 21 08:38:48 2009 -0700 by Scott Chacon
Die Ersetzungen können z.B. die Commit-Meldung und beliebige git notes
enthalten, und git log
kann einfache Zeilenumbrüche durchführen:
$ echo '$Format:Last commit: %h by %aN at %cd%n%+w(76,6,9)%B$' > LAST_COMMIT
$ git commit -am 'export-subst uses git log'\''s custom formatter
git archive uses git log'\''s `pretty=format:` processor
directly, and strips the surrounding `$Format:` and `$`
markup from the output.
'
$ git archive @ | tar xfO - LAST_COMMIT
Last commit: 312ccc8 by Jim Hill at Fri May 8 09:14:04 2015 -0700
export-subst uses git log's custom formatter
git archive uses git log's `pretty=format:` processor directly, and
strips the surrounding `$Format:` and `$` markup from the output.
Das so entstandene Archiv ist für die Verwendung geeignet, aber wie jedes andere exportierte Archiv ist es nicht zur weiteren Entwicklungsarbeit verwendbar.
Merge-Strategien
Sie können Git-Attribute auch verwenden, um Git anzuweisen, verschiedene Merge-Strategien für spezifische Dateien in Ihrem Projekt zu verwenden. Eine sehr nützliche Option ist es, Git anzuweisen, dass es nicht versuchen soll, bestimmte Dateien zusammenzuführen, wenn sie Konflikte haben, sondern Ihre Version der Daten zu benutzen, anstelle der von jemand anderem.
Das ist nützlich, wenn ein Branch in Ihrem Projekt auseinander gelaufen ist oder sich spezialisiert hat. Wenn Sie jedoch Änderungen wieder in ihn einfügen möchten und einige Dateien ignorieren möchten.
Angenommen, Sie haben eine Datenbank-Einstellungsdatei namens database.xml
, die sich in zwei Branches voneinander unterscheidet. Sie wollen in Ihrer zweiten Branch verschmelzen, ohne die Datenbankdatei zu beschädigen.
Dann können Sie so ein Attribut einrichten:
database.xml merge=ours
Dann definieren Sie die Dummy-Merge-Strategie ours
mit:
$ git config --global merge.ours.driver true
Wenn Sie in den zweiten Branch verschmelzen, ohne in Merge-Konflikte mit der Datei database.xml
zu laufen, sehen Sie so etwas wie hier:
$ git merge topic
Auto-merging database.xml
Merge made by recursive.
In diesem Fall bleibt die Datei database.xml
auf der Version, die sie ursprünglich gehabt hat.