Erhalten Sie Zugang zu diesem und mehr als 300000 Büchern ab EUR 5,99 monatlich.
Git ist eine der beliebtesten Versionsverwaltungen. Die Vielfalt an Kommandos, Optionen und Konfigurationen wirkt anfangs aber oft einschüchternd – obwohl die Grundkonzepte einfach sind und man schon mit wenigen davon effektiv arbeiten kann. Die Autoren dieses Buches bieten daher zunächst eine kompakte Einführung in die Konzepte und jene Befehle, die man im Entwickleralltag wirklich benötigt. Anschließend widmen sie sich ausführlich den wichtigsten Workflows bei der Softwareentwicklung im Team und zeigen, wie Git dort eingesetzt wird. Behandelt werden u.a. folgende Workflows: - Ein Projekt aufsetzen - Mit Feature-Branches entwickeln - Gemeinsam auf einem Branch arbeiten - Kontinuierlich Releases durchführen - Periodisch Releases durchführen - Große Projekte aufteilen Sie lernen in diesem Buch alle wichtigen Git-Befehle und -Funktionen kennen und erfahren, wie Sie sie effektiv anwenden – sowohl über die Kommandozeile als auch mit Tools wie Atlassian Source Tree. Darüber hinaus erfahren Sie, wie Git mit dem Build-Server Jenkins genutzt werden kann oder wie Sie auf Plattformen wie GitHub oder GitLab mit Pull-Requests arbeiten. Zudem lernen Sie fortgeschrittene Features kennen, wie z.B. Submodules, Subtrees und Worktrees. Die 5. Auflage wurde Dank des Feedbacks unserer Leser noch einmal gründlich überarbeitet und ist jetzt an vielen Stellen präziser und besser verständlich. Da Git inzwischen bei vielen Unternehmen schon lange im Einsatz ist, werden die dort versionierten Projekte auch immer größer. Deshalb ist ein neues Kapitel voll mit Tipps zum Umgang mit besonders großen Repositorys hinzugekommen. "Eine rundum gelungene Darstellung des Themas, vom Verlag nur Entwicklern empfohlen, ist jedoch auch jedem Anfänger zu empfehlen, der sich durch zunächst unbekannte Begriffe nicht abschrecken lässt. Lesenswert!" python-verband.org
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 355
Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:
René Preißel arbeitet als freiberuflicher Softwarearchitekt, Entwickler und Trainer. Er beschäftigt sich seit vielen Jahren mit der Entwicklung von Anwendungen und dem Coaching von Teams. Seine Arbeitsschwerpunkte liegen im Bereich Softwarearchitektur, Java-Entwicklung und Build-Management.
Mehr Informationen unter www.eToSquare.de.
Bjørn Stachmann arbeitet als Software Developer für die Otto GmbH & Co KG in Hamburg. Seine Schwerpunkte liegen in den Bereichen Java-Entwicklung, Softwarearchitektur und Hadoop. Sein aktuelles Arbeitsfeld ist der Hadoop-basierte Big-Data-Stack für die BI-Plattform BRAIN.
Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:
www.dpunkt.plus
René Preißel · Bjørn Stachmann
Dezentrale Versionsverwaltung im TeamGrundlagen und Workflows
5., aktualisierte und erweiterte Auflage
René Preißel
Bjørn Stachmann
Lektorat: René Schönfeldt
Lektoratsassistenz/Projektkoordinierung: Anja Weimer
Copy-Editing: Annette Schwarz, Ditzingen
Satz: Da-TeX Gerd Blumenstein, Leipzig, www.da-tex.de
Herstellung: Stefanie Weidner
Umschlaggestaltung: Helmut Kraus, www.exclam.de
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
ISBN:
Print 978-3-86490-649-7
PDF 978-3-96088-730-0
ePub 978-3-96088-731-7
mobi 978-3-96088-732-4
5., aktualisierte und erweiterte Auflage 2019
Copyright © 2019 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
Hinweis:
Dieses Buch wurde auf PEFC-zertifiziertem Papier aus nachhaltiger
Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir
zusätzlich auf die Einschweißfolie.
Schreiben Sie uns:
Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: [email protected].
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.
5 4 3 2 1 0
Dieses Buch wurde selbstverständlich mit Git erstellt:
Version (Commit-Hash):
commit ff46fbf39089cd6435367cda6038bf07d54075c6
Author: bstachmann <[email protected]>
Add section about push --force
Anzahl Commits:
2169
Änderungsstatistik:
789 files changed, 341725 insertions(+), 228 deletions(-)
Status:
On branch master
Your branch is up to date with 'fork/master'.
nothing to commit, working tree clean
Git hat eine rasante Erfolgsgeschichte hinter sich. Im April 2005 begann Linus Torvalds, Git zu implementieren, weil er keinen Gefallen an den damals verfügbaren Open-Source-Versionsverwaltungen fand. Heute, im Frühjahr 2019, liefert Google Millionen von Suchtreffern, wenn man nach »git version control« sucht. Für neue Open-Source-Projekte ist es zum Standard geworden, und viele große Open-Source-Projekte sind zu Git migriert.
Arbeiten mit Branches: Wenn viele Entwickler gemeinsam an einer Software arbeiten, entstehen parallele Entwicklungsstränge, die immer wieder auseinanderlaufen und zusammengeführt werden müssen. Genau dafür ist Git entwickelt worden. Es bietet daher umfassende Unterstützung zum Branchen, Mergen, Rebasen und Cherry-Picken.
Flexibilität in den Workflows: Manche sagen, dass Git im Grunde gar keine Versionsverwaltung sei, sondern ein Baukasten, aus dem sich jeder seine eigene Versionsverwaltung zusammensetzen kann. Git ist außergewöhnlich flexibel. Ein einzelner Entwickler kann es für sich allein nutzen, agile Teams finden leichtgewichtige Arbeitsweisen damit, aber auch große internationale Projekte mit zahlreichen Entwicklern an mehreren Standorten können passende Workflows entwickeln.
Contribution: Die meisten Open-Source-Projekte existieren durch freiwillige Beiträge von Entwicklern. Es ist wichtig, das Beitragen so einfach wie nur möglich zu machen. Bei zentralen Versionsverwaltungen wird dies oft erschwert, weil man nicht jedem schreibenden Zugriff auf das Repository geben möchte. Jeder kann ein Git-Repository klonen, damit vollwertig arbeiten und dann später die Änderungen weitergeben: »Mit Forks entwickeln« (Seite 173).
Nachvollziehbare Herkunft von Sourcecode: Die Entwickler von Git haben es als Content Tracker bezeichnet. Damit meinen sie ein Werkzeug, das die Herkunft von Inhalten, insbesondere Sourcecode, aufzeigen kann. Git kann dies selbst dann, wenn Code zusammengeführt wurde (Merge) oder Dateien verschoben und umbenannt wurden. Sogar kopierte Codeabschnitte können erkannt und zugeordnet werden.
Performance: Auch bei Projekten mit vielen Dateien und langen Historien bleibt Git schnell. In weniger als einer halben Minute wechselt es zum Beispiel von der aktuellen Version auf eine sechs Jahre ältere Version der Linux-Kernel-Sourcen – auf einem kleinen MacBook Air. Das kann sich sehen lassen, wenn man bedenkt, dass über 200.000 Commits und 40.000 veränderte Dateien dazwischenliegen.
Robust gegen Fehler und Angriffe: Da die Historie auf viele dezentrale Repositorys verteilt wird, ist ein schwerwiegender Datenverlust unwahrscheinlich. Eine genial simple Datenstruktur im Repository sorgt dafür, dass die Daten auch in ferner Zukunft interpretierbar bleiben. Der durchgängige Einsatz kryptografischer Prüfsummen erschwert es Angreifern, Repositorys unbemerkt zu korrumpieren.
Offline- und Multisite-Entwicklung: Die dezentrale Architektur macht es leicht, offline zu entwickeln, etwa unterwegs mit dem Laptop. Bei der Entwicklung an mehreren Standorten ist weder ein zentraler Server noch eine dauerhafte Netzwerkverbindung erforderlich.
Administrierbarkeit: Git ist einfach zu betreiben und zu administrieren. Alle Daten und Konfigurationen werden in einfachen Dateien gespeichert. Für Backups oder Umzüge genügen die Standardtools des Betriebssystems. Es muss kein Git-spezifischer Dienst eingerichtet werden. Alle Operationen werden durch Kommandozeilenbefehle bereitgestellt. Repositorys werden meist über SSH oder HTTP zugänglich gemacht, sodass man die Authentifizierung und Autorisierung des Betriebssystems bzw. Webservers nutzen kann. Zahlreiche mächtige Befehle erlauben es, das Repository zu manipulieren. Die dezentrale Natur von Git macht es leicht, Änderungen zuerst an einem Klon zu erproben, bevor man sie öffentlich macht.
Starke Open-Source-Community: Neben der detaillierten offiziellen Dokumentation unterstützen zahlreiche Anleitungen, Foren, Wikis etc. den Anwender. Es existiert ein Ökosystem aus Tools, Hosting-Plattformen, Publikationen, Dienstleistern und Plugins für Entwicklungsumgebungen, und es wächst stark.
Erweiterbarkeit: Git bietet neben komfortablen Befehlen für den Anwender auch elementare Befehle, die einen direkteren Zugang zum Repository erlauben. Dies macht Git sehr flexibel und ermöglicht individuelle Anwendungen, die über das hinausgehen, was Git von Haus aus bietet.
Große Repositorys → Seite 285
Git ist nun schon seit vielen Jahren im Einsatz. Die Projekte werden immer größer, die Entwickler werden mehr, und daraus ergeben sich neue Herausforderungen. Deshalb haben wir dem Umgang mit sehr großen Repositorys ein eigenes Kapitel gewidmet, in dem Konzepte wie Sparse Checkout und Shallow Clone sowie Tools wie Watchman vorgestellt werden.
Ein Abschnitt über den im Alltag sehr nützlichen show-Befehl, den wir bisher übersehen hatten, ist jetzt mit an Bord.
Das HEAD-Commit → Seite 35Schreibweisen für Commits → Seite 40Der Master-Branch → Seite 68
Das Konzept des HEAD-Commits, welches bisher in verstreuten Anmerkungen nur angerissen wurde, hat nun einen eigenen Abschnitt erhalten. Ebenso erläutern wir jetzt in einem Abschnitt gebündelt die wichtigsten Schreibweisen für Commit-Parameter.
Von Lesern und Seminarteilnehmern gab es immer mal wieder Fragen zur Bedeutung des Master-Branch. Deshalb haben wir einen Abschnitt hierzu ergänzt.
Das Origin-Repository → Seite 99
Auch für das origin-Repository haben wir einen erläuternden Abschnitt hinzugefügt.
Dringend nötig war auch die Überarbeitung des Kapitels über Jenkins, da sich sowohl beim Build-Server als auch bei den Hosting-Plattformen für Git in den letzten Jahren einiges bewegt hat.
Integration mit Jenkins → Seite 273
Dank des Feedbacks von Lesern konnten wir darüber hinaus in den Grundlagen-Kapiteln (1 bis 12) viele Dinge präziser und hoffentlich auch verständlicher formulieren.
Falls Sie Fehler entdecken, Fragen oder Vorschläge haben, können Sie Feedback über unsere Website geben:
http://kapitel26.github.io/feedback
Oder Sie schreiben uns eine E-Mail:
Ein Projekt aufsetzen → Seite 133Release durchführen → Seite 195
Wenn Sie Entwickler sind, im Team Software herstellen und wissen wollen, wie man Git effektiv einsetzt, dann halten Sie jetzt das richtige Buch in der Hand. Dies ist kein theorielastiger Wälzer und auch kein umfassendes Nachschlagewerk. Es beschreibt nicht alle Befehle von Git (es sind mehr als 100). Es beschreibt erst recht nicht alle Optionen (einige Befehle bieten über 50 an). Stattdessen beschreibt dieses Buch, wie man Git in typischen Projektsituationen einsetzen kann, z. B. wie man ein Git-Projekt aufsetzt oder wie man mit Git ein Release durchführt.
Gleich ausprobieren! → Seite 9
Erste Schritte: Auf weniger als einem Dutzend Seiten zeigt ein Beispiel alle wichtigen Git-Befehle.
Was sind Commits? → Seite 31Tipps und Tricks → Seite 117
Einführung: Auf weniger als hundert Seiten erfahren Sie, was man benötigt, um mit Git im Team arbeiten zu können. Zahlreiche Beispiele zeigen, wie man die wichtigsten Git-Befehle anwendet. Darüber hinaus werden wesentliche Grundbegriffe, wie zum Beispiel Commit, Repository, Branch, Merge oder Rebase, erklärt, die Ihnen helfen zu verstehen, wie Git funktioniert, damit Sie die Befehle gezielter einsetzen können. Hier finden Sie auch einen Abschnitt mit Tipps und Tricks, die man nicht jeden Tag braucht, die aber manchmal nützlich sein können.
Workflow-Verzeichnis → Seite 325
Workflows: Workflows beschreiben Szenarien, wie man Git im Projekt einsetzen kann, zum Beispiel wenn man ein Release durchführen möchte: »Periodisch Releases durchführen« (Seite 195). Für jeden Workflow wird beschrieben,
welches Problem er löst,
welche Voraussetzungen dazu gegeben sein müssen und
wer wann was zu tun hat, damit das gewünschte Ergebnis erreicht wird.
»Warum nicht anders?«-Abschnitte: Jeder Workflow beschreibt genau einen konkreten Lösungsweg. In Git gibt es häufig sehr unterschiedliche Wege, um dasselbe Ziel zu erreichen. Im letzten Teil eines jeden Workflow-Kapitels wird erklärt, warum wir genau diese eine Lösung gewählt haben. Dort werden auch Varianten und Alternativen erwähnt, die für Sie interessant sind, wenn in Ihrem Projekt andere Voraussetzungen gegeben sind oder wenn Sie mehr über die Hintergründe wissen wollen.
Schritt-für-Schritt-Anleitungen → Seite 323
Schritt-für-Schritt-Anleitungen: Häufig benötigte Befehlsfolgen, wie zum Beispiel »Branch erstellen« (Seite 66), haben wir in Schritt-für-Schritt-Anleitungen beschrieben.
Git ist extrem flexibel. Das ist gut, weil es für die unterschiedlichsten Projekte taugt. Vom einzelnen Sysadmin, der »mal eben« ein paar Shell-Skripte versioniert, bis hin zum Linux-Kernel-Projekt, an dem Hunderte von Entwicklern arbeiten, ist jeder damit gut bedient. Diese Flexibilität hat jedoch ihren Preis. Wer mit Git zu arbeiten beginnt, muss viele Entscheidungen treffen. Zum Beispiel:
In Git hat man dezentrale Repositorys. Aber möchte man wirklich nur dezentral arbeiten? Oder richtet man doch lieber ein zentrales Repository ein?
Git unterstützt zwei Richtungen für den Datentransfer: Push und Pull. Benutzt man beide? Falls ja: Wofür verwendet man das eine? Wofür das andere?
Branching und Merging ist eine Stärke von Git. Aber wie viele Branches öffnet man? Einen für jedes Feature? Einen für jedes Release? Oder überhaupt nur einen?
Um den Einstieg zu erleichtern, haben wir 12 Workflows beschrieben:
Die Workflows sind Arbeitsabläufe für den Projektalltag.
Die Workflows geben konkrete Handlungsanweisungen.
Die Workflows zeigen die benötigten Befehle und Optionen.
Die Workflows eignen sich gut für eng zusammenarbeitende Teams, wie man sie in modernen Softwareprojekten häufig antrifft.
Die Workflows sind
nicht
die einzige richtige Lösung für das jeweilige Problem. Aber sie sind ein guter Startpunkt, von dem man ausgehen kann, um optimale Workflows für das eigene Projekt zu entwickeln.
Wir konzentrieren uns auf die agile Entwicklung im Team für kommerzielle Projekte, weil wir glauben, dass sehr viele professionelle Entwickler (die Autoren inklusive) in solchen Umgebungen arbeiten. Nicht berücksichtigt haben wir die besonderen Belange der Open-Source-Entwicklung, obwohl es auch dafür sehr interessante Workflows mit Git gibt.
Als Autoren wünschen wir uns natürlich, dass Sie unser Buch von Seite 1 bis Seite 320 am Stück verschlingen, ohne es zwischendrin aus der Hand zu legen. Aber mal ehrlich: Haben Sie genug Zeit, um heute noch mehr als ein paar Seiten zu lesen? Wir vermuten, dass in Ihrem Projekt gerade die Hölle los ist und dass das Arbeiten mit Git nur eines von hundert Themen ist, mit denen Sie sich momentan beschäftigen. Deshalb haben wir uns Mühe gegeben, das Buch so zu gestalten, dass man es gut querlesen kann. Hier sind ein paar Tipps dazu:
Muss ich die Einführungskapitel lesen, um die Workflows zu verstehen?
Falls Sie noch keine Vorkenntnisse in Git haben, sollten Sie das tun. Grundlegende Befehle und Prinzipien sollten Sie kennen, um die Workflows korrekt einsetzen zu können.
Ich habe schon mit Git gearbeitet. Welche Kapitel kann ich überspringen?
Zusammenfassung am Ende der Einführungskapitel
Auf der letzten Seite in jedem Einführungskapitel 1 bis 14 gibt es eine Zusammenfassung der Inhalte in Stichworten. Dort können Sie sehr schnell sehen, ob es in dem Kapitel für Sie noch Dinge zu entdecken gibt oder ob Sie es überspringen können. Die folgenden Kapitel können Sie relativ gut überspringen, weil sie nur für einige Workflows relevant sind:
Überspringen Sie diese Kapitel, wenn Sie es eilig haben.
Kapitel 6, Das Repository
Kapitel 9, Mit Rebasing die Historie glätten
Kapitel 12, Versionen markieren
Kapitel 30, Abhängigkeiten zwischen Repositorys
Kapitel 13, Tipps und Tricks
Wo finde ich was?
Workflow-Verzeichnis → Seite 325
Workflows: Ein Verzeichnis aller Workflows mit Kurzbeschreibungen und Überblicksabbildung finden Sie im Anhang.
Anleitungsverzeichnis → Seite 323
Schritt-für-Schritt-Anleitungen: Wir haben alle Anleitungen im Anhang aufgelistet.
Index → Seite 330
Befehle und Optionen: Wenn Sie beispielsweise wissen wollen, wie man die Option find-copies-harder verwendet und zu welchem Befehl sie gehört, dann schauen Sie in den Index. Dort sind fast alle Verwendungen von Befehlen und Optionen aufgeführt. Oft haben wir die Nummer jener Seite fett hervorgehoben, wo Sie am meisten Informationen zu dem Befehl oder der Option finden.
Index → Seite 330
Fachbegriffe: Fachbegriffe, wie zum Beispiel »First-Parent-History« oder »Remote-Tracking-Branch«, finden Sie natürlich auch im Index.
Index → Seite 330
In den »Erste Schritte«-Kapiteln verwenden wir einige Git-Fachbegriffe, die wir erst in späteren Kapiteln ausführlicher behandeln. Diese sind kursiv gesetzt, z. B. Repository. Im Index sind jene Seitenzahlen fett hervorgehoben, wo der Begriff dann definiert oder ausführlicher erläutert wird.
Grafische Werkzeuge für Git → Seite 310
Viele Beispiele in diesem Buch beschreiben wir mit Kommandozeilenaufrufen. Das soll nicht heißen, dass es dafür keine grafischen Benutzeroberflächen gibt. Im Gegenteil: Git bringt zwei einfache grafische Anwendungen bereits mit: gitk und git-gui. Darüber hinaus gibt es zahlreiche Git-Frontends (z. B. Atlassian SourceTree1, TortoiseGit2, SmartGit3, GitX4, Git Extensions5, tig6, qgit7), einige Entwicklungsumgebungen, die Git von Haus aus unterstützen (IntelliJ8, Xcode 49), und viele Plugins für Entwicklungsumgebungen (z. B. EGit für Eclipse10, NBGit für NetBeans11, Git Extensions für Visual Studio12). Wir haben uns trotzdem für die Kommandozeilenbeispiele entschieden, weil
Git-Kommandozeilenbefehle auf allen Plattformen fast gleich funktionieren,
die Beispiele auch mit künftigen Versionen funktionieren werden,
man damit Workflows sehr kompakt darstellen kann und weil
wir glauben, dass das Arbeiten mit der Kommandozeile für viele Anwendungsfälle unschlagbar effizient ist.
In den Beispielen arbeiten wir mit der Bash-Shell, die auf Linux- und Mac-OS-Systemen standardmäßig vorhanden ist. Auf Windows-Systemen kann man die »Git-Bash«-Shell (sie ist in der »msysgit«-Installation enthalten) oder »cygwin« verwenden. Die Kommandozeilenaufrufe stellen wir wie folgt dar:
> git commit
An den Stellen, wo es inhaltlich interessant ist, zeigen wir auch die Antwort, die Git geliefert hat, in etwas kleinerer Schrift dahinter an:
> git --version
git version 2.3.7
Eine kurze Einführung in das Arbeiten mit Git-User-Interfaces zeigen wir am Beispiel von SourceTree in Kapitel »Erste Schritte mit Source-Tree« ab Seite 23. Wo wir auf Menüpunkte oder Buttons Bezug nehmen, setzen wir diese in Kapitälchen, z. B. ANSICHT | AKTUALISIEREN.
Rückblickend sind wir erstaunt, wie viele Leute auf die eine oder andere Weise zum Entstehen dieses Buchs beigetragen haben. Wir möchten uns ganz herzlich bei all jenen bedanken, ohne die dieses Buch nicht das geworden wäre, was es jetzt ist.
An erster Stelle danken wir Anke, Jan, Elke und Annika, die sich inzwischen kaum noch daran erinnern, wie wir ohne einen Laptop unter den Fingern aussehen.
Dann danken wir dem freundlichen Team vom dpunkt.verlag, insbesondere Vanessa Wittmer, Nadine Thiele und Ursula Zimpfer. Besonderer Dank gebührt aber René Schönfeldt, der das Projekt angestoßen und vom ersten Tag bis zur letzten Korrektur begleitet hat. Außerdem bekanken wir uns bei Maurice Kowalski, Jochen Schlosser, Oliver Zeigermann, Ralf Degner, Michael Schulze-Ruhfus und einem halben Dutzend anonymer Gutachter für die wertvollen inhaltlichen Beiträge, die sehr geholfen haben, das Buch besser zu machen. Für den allerersten Anstoß danken wir Matthias Veit, der eines Tages zu Bjørn kam und meinte, Subversion wäre nun doch schon etwas in die Jahre gekommen und man solle sich doch mal nach etwas Schönerem umsehen, zum Beispiel gäbe es da so ein Tool, das die Entwickler des Linux-Kernels neuerdings nutzen würden …
Ein besonders herzlicher Dank geht an unseren Leser Herrn Ulrich Windl, der das Buch aufmerksamer gelesen hat als die meisten und uns eine lange Liste von Fragen, Korrektur- und Verbesserungsvorschlägen zugesandt hat. Sie haben wesentlich dazu beigetragen, dass diese Auflage besser und präziser ist als die erste.
Ebenfalls danken wir Henrik Heine, Malte Finsterwalder und Tjabo Vierbücher für gute Hinweise und Korrekturvorschläge.
Dieses Mal gab es nicht so viel Feedback. Ein paar kleinere Fehlermeldungen haben wir dennoch erhalten, und so konnten wir das Buch wieder ein wenig verbessern. Vielen Dank dafür.
Nützliche Hinweise haben wir erhalten von: Thomas Braun, Herbert Feichtinger, Jason Stäuble (@shadyhh), Udo Heyn (@UdoHeyn) und Herrn Böckler. Vielen Dank dafür!
Ein ganz besonderer Dank geht an Dr. Oliver Thilmann, der uns eine lange E-Mail mit sehr vielen Anmerkungen und Verbesserungsvorschlägen geschrieben hat, die uns geholfen hat, diese Auflage präziser und verständlicher zu gestalten. Nützliche Hinweise haben wir außerdem erhalten von: Gerald Schroll (@gschroll), @TheDet und Hampa Brügger (@hampa-git).
Ein besonderer Dank geht an Linus Torvalds, Junio C. Hamano und die vielen Committer im Git-Projekt dafür, dass sie der Entwickler-Community dieses fantastische Tool geschenkt haben.
Vorwort
Erste Schritte
1Grundlegende Konzepte
1.1Dezentrale Versionsverwaltung – alles anders?
1.2Das Repository – die Grundlage dezentralen Arbeitens
1.3Branching und Merging – ganz einfach!
1.4Zusammenfassung
2Erste Schritte mit der Kommandozeile
2.1Git einrichten
2.2Ein paar Hinweise für Windows-User
2.3Git einrichten
2.4Das erste Projekt mit Git
2.5Zusammenarbeit mit Git
2.6Zusammenfassung
3Erste Schritte mit SourceTree
3.1SourceTree konfigurieren
3.2Das erste Projekt mit Git
3.3Zusammenarbeit mit Git
3.4Zusammenfassung
Arbeiten mit Git
4Was sind Commits?
4.1Zugriffsberechtigungen und Zeitstempel
4.2Die Befehle add und commit
4.3Exkurs: Mehr über Commit-Hashes
4.4Eine Historie von Commits
4.5Das HEAD-Commit
4.6Eine etwas andere Sichtweise auf Commits
4.7Commits untersuchen
4.8Viele unterschiedliche Historien desselben Projekts
4.9Schreibweisen für Commits
4.10Zusammenfassung
5Commits zusammenstellen
5.1Der status-Befehl
5.2Der Stage-Bereich umfasst alle Projektdateien
5.3Was tun mit Änderungen, die nicht übernommen werden sollen?
5.4Mit .gitignore Dateien unversioniert lassen
5.5Stashing: Änderungen zwischenspeichern
5.6Zusammenfassung
6Das Repository
6.1Ein einfaches und effizientes Speichersystem
6.2Verzeichnisse speichern: Blob und Tree
6.3Gleiche Daten werden nur einmal gespeichert
6.4Kompression ähnlicher Inhalte
6.5Ist es schlimm, wenn verschiedene Daten zufällig denselben Hashwert bekommen?
6.6Commits
6.7Wiederverwendung von Objekten in der Commit-Historie
6.8Umbenennen, verschieben und kopieren
6.9Zusammenfassung
7Branches verzweigen
7.1Parallele Entwicklung
7.2Bugfixes in älteren Versionen
7.3Branches
7.4Aktiver Branch
7.5Der Master-Branch
7.6Branch-Zeiger umsetzen
7.7Branch löschen
7.8Und was ist, wenn man die Commit-Objekte wirklich loswerden will?
7.9Zusammenfassung
8Branches zusammenführen
8.1Was passiert bei einem Merge?
8.2Konflikte
8.3Fast-Forward-Merges
8.4First-Parent-History
8.5Knifflige Merge-Konflikte
8.6Zusammenfassung
9Mit Rebasing die Historie glätten
9.1Das Prinzip: Kopieren von Commits
9.2Und wenn es zu Konflikten kommt?
9.3Was passiert mit den ursprünglichen Commits nach dem Rebasing?
9.4Empfehlungen zum Rebasing
9.5Cherry-Picking
9.6Zusammenfassung
10Repositorys erstellen, klonen und verwalten
10.1Ein Repository erstellen
10.2Das Repository-Layout
10.3Bare-Repositorys
10.4Vorhandene Dateien übernehmen
10.5Ein Repository klonen
10.6Wie sagt man Git, wo das Remote-Repository liegt?
10.7Kurznamen für Repositorys: Remotes
10.8Das Origin-Repository
10.9Zusammenfassung
11Austausch zwischen Repositorys
11.1Fetch, Pull und Push
11.2Remote-Tracking-Branches
11.3Einen Remote-Branch bearbeiten
11.4Ein paar Begriffe, die man kennen sollte
11.5Fetch: Branches aus einem anderen Repository holen
11.6Fetch: Aufrufvarianten
11.7Push mit --force
11.8Erweiterte Möglichkeiten
11.9Zusammenfassung
12Versionen markieren
12.1Arbeiten mit Tags erstellen
12.2Welche Tags gibt es?
12.3Die Hashes zu den Tags ausgeben
12.4Die Log-Ausgaben um Tags anreichern
12.5In welcher Version ist es »drin«?
12.6Wie verschiebt man ein Tag?
12.7Und wenn ich ein »Floating Tag« brauche?
12.8Zusammenfassung
13Tipps und Tricks
13.1Keine Panik – es gibt ein Reflog!
13.2Lokale Änderungen temporär ignorieren
13.3Änderungen an Textdateien untersuchen
13.4alias – Abkürzungen für Git-Befehle
13.5Branches als temporäre Zeiger auf Commits nutzen
13.6Commits auf einen anderen Branch verschieben
13.7Mehr Kontrolle bei Fetch, Push und Pull
13.8Git-Version auf Ubuntu Linux aktualisieren
Workflows
14Workflow-Einführung
14.1Warum Workflows?
14.2Welche Workflows sind wann sinnvoll?
14.3Aufbau der Workflows
Workflows: Entwickeln mit Git
15Ein Projekt aufsetzen
16Gemeinsam auf einem Branch entwickeln
17Mit Feature-Branches entwickeln
18Mit Forks entwickeln
Workflows: Release-Prozess
19Kontinuierlich Releases durchführen
20Periodisch Releases durchführen
21Mit mehreren aktiven Releases arbeiten
Workflows: Repositorys pflegen
22Ein Projekt mit großen binären Dateien versionieren
23Große Projekte aufteilen
24Kleine Projekte zusammenführen
25Lange Historien auslagern
26http://kapitel26.github.io
27Ein Projekt nach Git migrieren
Mehr über Git
28Integration mit Jenkins
28.1Vorbereitungen
28.2Ein einfaches Git-Projekt einrichten
28.3Hook als Build-Auslöser
28.4Ein Tag für jeden erfolgreichen Build
28.5Pull-Requests bauen
28.6Automatischer Merge von Branches
28.7Mit Jenkins Pipelines arbeiten
29Große Repositorys
29.1Repositorys mit sehr vielen Dateien
29.2Sparse Checkout
29.3Mit Watchman Dateiänderungen schneller erkennen
29.4Repositorys mit großem Speicherbedarf
29.5Shallow Clone
29.6Zusammenfassung
30Abhängigkeiten zwischen Repositorys
30.1Abhängigkeiten mit Submodulen
30.2Abhängigkeiten mit Subtrees
30.3Zusammenfassung
31Was gibt es sonst noch?
31.1Worktrees – mehrere Workspaces mit einem Repository
31.2Interaktives Rebasing – Historie verschönern
31.3Umgang mit Patches
31.4Archive erstellen
31.5Grafische Werkzeuge für Git
31.6Repository im Webbrowser anschauen
31.7Zusammenarbeit mit Subversion
31.8Hooks – Git erweitern
31.9Mit Bisection Fehler suchen
32Die Grenzen von Git
32.1Hohe Komplexität
32.2Komplizierter Umgang mit Submodulen
32.3Ressourcenverbrauch bei großen binären Dateien
32.4Repositorys können nur vollständig verwendet werden
32.5Autorisierung nur auf dem ganzen Repository
32.6Mäßige grafische Werkzeuge für die Historienauswertung
Anhang
Schritt-für-Schritt-Anleitungen
Workflow-Verzeichnis
Index
Dieses Kapitel macht Sie mit den Ideen einer dezentralen Versionsverwaltung vertraut und zeigt die Unterschiede zu einer zentralen Versionsverwaltung auf. Anschließend erfahren Sie, wie dezentrale Repositorys funktionieren und warum Branching und Merging keine fortgeschrittenen Themen in Git sind.
Bevor wir uns den Konzepten der dezentralen Versionsverwaltung widmen, werfen wir kurz einen Blick auf die klassische Architektur zentraler Versionsverwaltungen.
Abb. 1–1Zentrale Versionsverwaltung
Abbildung 1–1 zeigt die typische Aufteilung einer zentralen Versionsverwaltung, z. B. von CVS oder Subversion. Jeder Entwickler hat auf seinem Rechner ein Arbeitsverzeichnis (Workspace) mit allen Projektdateien. Diese bearbeitet er und schickt die Änderungen regelmäßig per Commit an den zentralen Server. Per Update holt er die Änderungen der anderen Entwickler ab. Der zentrale Server speichert die aktuellen und historischen Versionen der Dateien (Repository). Parallele Entwicklungsstränge (Branches) und benannte Versionen (Tags) werden auch zentral verwaltet.
Abb. 1–2Dezentrale Versionsverwaltung
Das Repository → Seite 53Was sind Commits? → Seite 31Austausch zwischen Repositorys → Seite 101
Bei einer dezentralen Versionsverwaltung (Abbildung 1–2) gibt es keine Trennung zwischen Entwickler- und Serverumgebung. Jeder Entwickler hat sowohl einen Workspace mit den in Arbeit befindlichen Dateien als auch ein eigenes lokales Repository (genannt Klon) mit allen Versionen, Branches und Tags. Änderungen werden auch hier durch ein Commit festgeschrieben, jedoch zunächst nur im lokalen Repository. Andere Entwickler sehen die neuen Versionen nicht sofort. Push- und Pull-Befehle übertragen Änderungen dann von einem Repository zum anderen. Technisch gesehen sind in der dezentralen Architektur alle Repositorys gleichwertig. Theoretisch bräuchte es keinen Server: Man könnte alle Änderungen direkt von Entwicklerrechner zu Entwicklerrechner übertragen. In der Praxis spielen Repositorys auf Servern auch in Git eine wichtige Rolle, zum Beispiel in Form von folgenden spezifischen Repositorys:
Ein Projekt aufsetzen → Seite 133
Blessed Repository: Aus diesem Repository werden die »offiziellen« Releases erstellt.
Shared Repository: Dieses Repository dient dem Austausch zwischen den Entwicklern im Team. In kleinen Projekten kann hierzu auch das Blessed Repository genutzt werden. Bei einer Multisite-Entwicklung kann es auch mehrere geben.
Workflow Repository: Ein solches Repository wird nur mit Änderungen befüllt, die einen bestimmten Status im Workflow erreicht haben, z. B. nach erfolgreichem Review.
Fork Repository: Dieses Repository dient der Entkopplung von der Entwicklungshauptlinie (zum Beispiel für große Umbauten, die nicht in den normalen Release-Zyklus passen) oder für experimentelle Entwicklungen, die vielleicht nie in den Hauptstrang einfließen sollen.
Folgende Vorteile ergeben sich aus dem dezentralen Vorgehen:
Hohe Performance: Fast alle Operationen werden ohne Netzwerkzugriff lokal durchgeführt.
Effiziente Arbeitsweisen: Entwickler können lokale Branches benutzen, um schnell zwischen verschiedenen Aufgaben zu wechseln.
Offline-Fähigkeit: Entwickler können ohne Serververbindung Commits durchführen, Branches anlegen, Versionen taggen etc. und diese erst später übertragen.
Flexibilität der Entwicklungsprozesse: In Teams und Unternehmen können spezielle Repositorys angelegt werden, um mit anderen Abteilungen, z. B. den Testern, zu kommunizieren. Änderungen werden einfach durch ein Push in dieses Repository freigegeben.
Backup: Jeder Entwickler hat eine Kopie des Repositorys mit einer vollständigen Historie. Somit ist die Wahrscheinlichkeit minimal, durch einen Serverausfall Daten zu verlieren.
Wartbarkeit: Knifflige Umstrukturierungen kann man zunächst auf einer Kopie des Repositorys erproben, bevor man sie in das Original-Repository überträgt.
In zentralen Versionsverwaltungen werden alle Projekte, selbst dann, wenn sie inhaltlich nichts miteinander zu tun haben, in einem gemeinsam genutzten Repository abgelegt. In Git hingegen bekommt jedes Projekt1 sein eigenes Repository.
Das Repository → Seite 53
Kern des Repositorys ist ein effizienter Datenspeicher: die Object Database. Dort speichert Git Dateiinhalte, Verzeichnisstruktur und Versionshistorie des Projekts, in Form von sogenannten Objekten, das sind unter anderem:
Versionen (Commits): Ein Commit in Git beschreibt einen wiederherstellbaren Gesamtzustand des Projekts. Es ist eine Momentaufnahme des Verzeichnisbaumes (Tree) mit allen Dateiinhalten (Blobs), ggf. mitsamt Unterverzeichnissen (ebenfalls Trees). Außerdem werden der Autor, die Uhrzeit, ein Kommentar und die Vorgängerversion festgehalten.
Verzeichnisse (Trees): Ein Tree ist eine Liste mit allen enthaltenen Dateien und Unterverzeichnissen. Jeder Datei ist ein Blob zugeordnet, jedem Unterverzeichnis ein Tree.
Inhalte von Dateien (Blobs): Dies sind Texte oder binäre Daten. Die Daten werden unabhängig vom Dateinamen gespeichert.
Für jedes Objekt wird ein hexadezimaler Hashwert berechnet, z. B. 1632acb65b01c6b621d6e1105205773931bb1a41. Dieser dient als Referenz zwischen den Objekten und als Schlüssel, um die Daten später wiederzufinden (Abbildung 1–3).
Die Hashwerte von Commits sind die »Versionsnummern« von Git. Haben Sie so einen Hashwert erhalten, können Sie überprüfen, ob diese Version im Repository enthalten ist, und können das zugehörige Verzeichnis im Workspace wiederherstellen. Falls die Version nicht vorhanden ist, können Sie das Commit mit allen referenzierten Objekten aus einem anderen Repository importieren (Pull).
Folgende Vorteile ergeben sich aus der Verwendung von Hashwerten und der Repository-Struktur:
Abb. 1–3Ablage von Objekten im Repository
Hohe Performance: Der Zugriff auf Daten über den Hashwert geht sehr schnell.
Redundanzfreie Speicherung: Identische Dateiinhalte müssen nur einmal abgelegt werden.
Dezentrale Versionsnummern: Da sich die Hashwerte aus den Inhalten der Dateien, dem Autor und dem Zeitpunkt berechnen, können Versionen auch »offline« erzeugt werden, ohne dass es später zu Konflikten kommt.
Effizienter Abgleich zwischen Repositorys: Werden Commits von einem Repository in ein anderes Repository übertragen, müssen nur die noch nicht vorhandenen Objekte kopiert werden. Das Erkennen, ob ein Objekt bereits vorhanden ist, ist dank der Hashwerte sehr performant.
Integrität der Objekte: Der Hashwert wird aus dem Inhalt der Objekte berechnet. Man kann Git jederzeit prüfen lassen, ob Daten und Hashwerte zueinander passen. Unabsichtliche Veränderungen oder böswillige Manipulationen der Daten werden so erkannt.
Automatische Erkennung von Umbenennungen: Werden Dateien umbenannt, wird das automatisch erkannt, da sich der Hashwert des Inhalts nicht ändert. Es sind somit keine speziellen Befehle zum Umbenennen und Verschieben notwendig.
Angenommen zwei Entwickler bearbeiten jeweils eine Kopie desselben Projekts, so entstehen zwei Versionen des Projekts, die sich an manchen Stellen in einigen Dateien unterscheiden. Eine solche Verzweigung nennt man Branch.
Interessant wird es, wenn man die Ergebnisse der beiden zu einer neuen Version zusammenführt. Man spricht dann von einem Merge. Einen Merge kann man manuell durchführen, indem man geeignete Abschnitte aus beiden Versionen zusammenkopiert. Das ist leider mühsam, fehleranfällig und später oft nicht mehr nachvollziehbar. Deshalb zählt es zu den wichtigen Fähigkeiten einer Versionsverwaltung, den Merge-Vorgang zu unterstützen und die Zusammenführung in der Historie zu dokumentieren.
Branches verzweigen → Seite 63
Das Verzweigen (Branching) und das Zusammenführen (Merging) wird von vielen Versionsverwaltungen als Sonderfall behandelt und gehört zu den fortgeschrittenen Themen. Ursprünglich wurde Git für die Entwickler des Linux-Kernels geschaffen, die dezentral über die ganze Welt verteilt arbeiten. Das Zusammenführen der Einzelergebnisse ist dabei eine große Herausforderung. Deshalb wurde Git von vornherein so konzipiert, dass es das Branching und Merging so einfach und sicher wie nur möglich macht.
In Abbildung 1–4 ist dargestellt, wie durch paralleles Arbeiten Branches entstehen. Jeder Punkt repräsentiert eine Version (Commit) des Projekts. In Git kann immer nur das gesamte Projekt versioniert werden, und somit repräsentiert so ein Punkt die zusammengehörigen Versionen mehrerer Dateien.
Beide Entwickler beginnen mit derselben Version, führen Änderungen durch und erstellen jeweils ein neues Commit. Da beide Entwickler ihr eigenes Repository haben, existieren jetzt zwei verschiedene Versionen des Projekts – zwei Branches sind entstanden. Wenn ein Entwickler die Änderungen des anderen in sein Repository importiert, kann er Git die Versionen zusammenführen lassen (Merge). Ist dies erfolgreich, so erstellt Git ein neues Commit, das beide Änderungen enthält: das Merge-Commit. Wenn der andere Entwickler dieses Commit abholt, sind beide wieder auf einem gemeinsamen Stand.
Mit Feature-Branches entwickeln → Seite 153
Im vorigen Beispiel ist eine Verzweigung ungeplant entstanden, einfach weil zwei Entwickler parallel an derselben Software gearbeitet haben. Natürlich kann man in Git eine Verzweigung auch gezielt beginnen und einen Branch explizit anlegen (Abbildung 1–5). Dies wird häufig genutzt, um die parallele Entwicklung von Features zu koordinieren (Feature-Branches).
Abb. 1–4Branches entstehen durch paralleles Arbeiten.
Abb. 1–5Explizite Branches für unterschiedliche Aufgaben
Beim Austausch zwischen Repositorys (Pull und Push) kann explizit entschieden werden, welche Branches übertragen werden. Neben dem einfachen Verzweigen und Zusammenführen erlaubt Git auch noch folgende Aktionen mit Branches:
Mit Rebasing die Historie glätten → Seite 87
Umpflanzen von Branches: Die Commits eines Branch können auf einen anderen Branch verschoben werden; dies nennt man Rebasing.
Übertragen einzelner Änderungen: Einzelne Commits können von einem Branch auf einen anderen Branch kopiert werden, z. B. Bugfixes (was Cherry-Picking genannt wird).
Interaktives Rebasing → Seite 308
Historie aufräumen: Die Historie eines Branch kann umgestaltet werden, das heißt, es können Commits zusammengefasst, umsortiert und gelöscht werden. Dadurch können die Historien besser als Dokumentation der Entwicklung genutzt werden (was man interaktives Rebasing nennt).
Nach dem Lesen der letzten Abschnitte sind Sie mit den grundlegenden Konzepten von Git vertraut. Selbst wenn Sie jetzt das Buch aus der Hand legen sollten (was wir nicht hoffen!), können Sie an einer Grundsatzdiskussion über dezentrale Versionsverwaltungen, die Notwendigkeit und Sinnhaftigkeit von Hashwerten sowie über das permanente Branching und Merging in Git teilnehmen.
Vielleicht stellen Sie sich aber auch gerade folgende Fragen:
Wie soll ich mit diesen allgemeinen Konzepten mein Projekt verwalten?
Wie koordiniere ich die vielen
Repositorys
?
Wie viele
Branches
benötige ich?
Wie integriere ich meinen Build-Server?
Erste Schritte mit der Kommandozeile → Seite 9
Um eine Antwort auf die erste Frage zu bekommen, lesen Sie das nächste Kapitel. Dort erfahren Sie konkret, mit welchen Befehlen Sie ein Repository anlegen, Dateien versionieren und Commits zwischen Repositorys austauschen können.
Workflow-Einführung → Seite 127
Als Antwort auf die anderen Fragen finden Sie nach den Grundlagenkapiteln detaillierte Workflows.
Falls Sie ein vielbeschäftigter Manager sind und noch nach Gründen suchen, warum Sie Git einsetzen müssen oder auch nicht, dann schauen Sie sich am besten als Nächstes das Kapitel »Die Grenzen von Git« ab Seite 315 an.
Sie können Git sofort ausprobieren, wenn Sie möchten. Dieses Kapitel beschreibt, wie man das erste Projekt einrichtet. Es zeigt Kommandos zum Versionieren von Änderungen, zum Ansehen der Historie und zum Austausch von Versionen mit anderen Entwicklern.
Erste Schritte mit SourceTree → Seite 23
Falls Sie lieber mit einem grafischen User-Interface starten wollen, finden Sie im nächsten Kapitel eine Anleitung dazu.
Zunächst müssen Sie Git installieren. Sie finden alles Nötige hierzu auf der Git-Website:
http://git-scm.com/download
Die Beispiele in diesem Buch wurden mit der Bash-Shell unter Mac OS und Linux entwickelt und getestet. Als die erste Auflage dieses Buchs erschien, gab es bereits eine Version für Windows. Die Integration war aber noch holprig. Die gute Nachricht für Sie: Inzwischen hat Git auch in der Welt von Windows große Verbreitung gefunden, und aktuelle Versionen bieten eine hervorragende Integration, sodass fast alle Beispiele ohne Anpassung auch unter Windows funktionieren. Für die Kommandozeile werden zwei Arten der Integration unterstützt:
Eingabeaufforderung
(
cmd.exe
): Der Git-Befehl
git
kann von der normalen Windows-Kommandozeile aus aufgerufen werden.
Git-Bash
: Git bringt eine Windows-Version der, auf Unix-artigen Systemen weit verbreiteten, Bash-Shell mit. Hier gibt es neben
git
auch ein paar weitere auf Linux viel genutzte Befehle, wie z. B.
grep
,
find
,
sort
,
wc
,
tail
und
sed
.
Der Windows-Installer, der von der oben genannten URL geladen werden kann, bietet etliche Optionen. In den meisten Fällen können Sie es einfach bei der voreingestellten Auswahl belassen. Folgendes ist empfehlenswert:
A
DJUSTING YOUR
PATH
ENVIRONMENT
: Eine gute Wahl ist U
SE
G
IT FROM THE
W
INDOWS
C
OMMAND
P
ROMPT
, denn Sie können dann Git nicht nur in der Git-Bash, sondern auch in der Windows-Eingabeaufforderung nutzen.
C
ONFIGURING THE LINE ENDING CONVERSIONS
: Windows nutzt andere Zeichen zur Markierung von Zeilenenden als Linux. Git kann Zeilenenden automatisch konvertieren. Das ist nützlich, wenn Entwickler mit unterschiedlichen Betriebssystemen am selben Projekt arbeiten. Für den Einstieg ist C
HECKOUT AS-IS
,
COMMIT AS-IS
am einfachsten.
C
ONFIGURING THE TERMINAL EMULATOR TO USE WITH
G
IT
B
ASH
: Empfehlenswert ist U
SE
M
IN
TTY, weil das Eingabefenster für die Git-Bash dann etwas mehr Komfort bietet.
Sie können den git-Befehl in der Eingabeaufforderung (cmd.exe) nutzen. Alles andere, wie Navigation, Verzeichnisanlage, Dateioperationen etc., machen Sie wie gewohnt. In der Ausgabe zeigt Git in Pfadnamen immer »/« als Trenner. Als Parameter dürfen Pfadnamen wahlweise mit »/« oder »\« angegeben werden. Letzteres ist empfehlenswert, weil dann die Autovervollständigung für Dateipfade mit der Tab-Taste funktioniert.
Die Beispiele aus diesem Kapitel und auch aus den meisten Einstiegskapiteln können direkt in der Windows-Eingabeaufforderung nachvollzogen werden. In späteren Kapiteln werden vereinzelt Features der Bash-Shell und Linux-Befehle genutzt, die es in der Windows-Eingabeaufforderung nicht gibt. Deshalb empfehlen wir, gleich mit der Git-Bash zu beginnen.
Tipp: Autovervollständigung
In der Git-Bash ist eine Tab-Vervollständigung nicht nur für Dateipfade, sondern auch für git-Befehle und -Optionen eingerichtet. Drückt man einmal Tab, dann wird versucht, das begonnene Kommando zu vervollständigen. Für Einsteiger noch wichtiger: Drückt man zweimal Tab, werden mögliche Vervollständigungen angezeigt:
> git com<TAB>
> git commit
> git c<TAB><TAB>
checkout cherry cherry-pick citool
clean clone commit config
> git commit --a<TAB><TAB>
--all --amend --author=
Achtung! In der Git-Bash müssen Sie »/« als Pfadtrenner nutzen! Die »:«-Notation für Laufwerke ist nicht zulässig. Man ersetzt z. B. G:\test durch /g/test.
Von den Befehlen in der Bash braucht man für den Anfang nicht viele. cd zur Navigation zwischen Verzeichnissen und mkdir zum Anlegen von Verzeichnissen funktionieren ganz ähnlich wie unter Windows. Statt dir nutzt man ls oder ll, um ein Inhaltsverzeichnis zu sehen.
Git ist in hohem Maße konfigurierbar. Für den Anfang genügt es aber, wenn Sie Ihren Benutzernamen und Ihre E-Mail-Adresse mit dem config-Befehl eintragen:
> git config --global user.name hmustermann
> git config --global user.email "[email protected]"
Nicht notwendig, aber empfehlenswert ist es, Ihren Lieblingstexteditor zu registrieren. Dieser wird immer dann aufgerufen, wenn Git eine Texteingabe benötigt, z. B. für einen Commit-Kommentar:
> git config --global core.editor vim # VI improved
> git config --global core.editor "atom --wait" # Atom editor
> git config --global core.editor notepad # Windows notepad
Am besten ist es, wenn Sie ein eigenes kleines Projekt verwenden, um Git zu erproben. Unser Beispiel namens erste-schritte kommt mit zwei Textdateien aus:
Abb. 2–1Unser Beispielprojekt
Tipp: Sicherungskopie nicht vergessen!
Erstellen Sie eine Sicherungskopie, bevor Sie das Beispiel mit Ihrem Lieblingsprojekt durchspielen! Es ist gar nicht so leicht, in Git etwas endgültig zu löschen oder »kaputt zu machen«, und Git warnt meist deutlich, wenn Sie dabei sind, etwas »Gefährliches« zu tun. Trotzdem: Vorsicht bleibt die Mutter der Porzellankiste.
Die Beispiele nutzen ein Top-Level-Verzeichnis /projekte zur Ablage der Projekte. Dadurch bleiben die Pfadnamen auch dort kurz, wo absolute Pfade angegeben sind. Wahrscheinlich werden Sie Ihre Projekte an anderer Stelle einrichten wollen, z. B. unter
/home/hmustermann/projekte
oder
C:\Users\hmustermann\projekte
Achtung! Denken Sie also daran, /projekte in den Beispielen durch Ihr Verzeichnis zu ersetzen! Windows-User müssen in der Git-Bash »umslashen«, z. B. zu
/c/Users/hmustermann/projekte
Als Erstes wird das Repository angelegt, in dem die Historie des Projekts gespeichert werden soll. Dies erledigt der init-Befehl im Projektverzeichnis. Ein Projektverzeichnis mit einem Repository nennt man einen Workspace.
> cd /projekte/erste-schritte
> git init
Initialized empty Git repository in /projekte/erste-schritte/.git/
Git hat im Verzeichnis /projekte/erste-schritte ein Repository angelegt, aber noch keine Dateien hinzugefügt. Achtung! Das Repository liegt in einem verborgenen Verzeichnis namens .git und wird im Explorer (bzw. Finder) unter Umständen nicht angezeigt.
Abb. 2–2Das Repository-Verzeichnis
Als Nächstes können Sie die Dateien foo.txt und bar.txt ins Repository bringen. Eine Projektversion nennt man bei Git ein Commit, und sie wird in zwei Schritten angelegt. Als Erstes bestimmt man mit dem add-Befehl, welche Dateien in das nächste Commit aufgenommen werden sollen. Danach überträgt der commit-Befehl die Änderungen ins Repository und vergibt einen 40-stelligen sogenannten Commit-Hash, der das neue Commit identifiziert. Git zeigt hier nur die ersten Stellen 2f43cf0 an.
> git add foo.txt bar.txt
> git commit --message "Beispielprojekt importiert."
master (root-commit) 2f43cd0] Beispielprojekt importiert.
2 files changed, 2 insertions(+), 0 deletions(-)
create mode 100644 bar.txt
create mode 100644 foo.txt
Jetzt ändern Sie foo.txt, löschen bar.txt und fügen eine neue Datei bar.html hinzu. Der status-Befehl zeigt alle Änderungen seit dem letzten Commit an. Die neue Datei bar.html wird übrigens als untracked angezeigt, weil sie noch nicht mit dem add-Befehl angemeldet wurde.
> git status
# On branch master
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in
# working directory)
#
# deleted: bar.txt
# modified: foo.txt
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# bar.html
no changes added to commit (use "git add" and/or "git commit -a")
Wenn Sie mehr Details wissen wollen, zeigt Ihnen der diff-Befehl jede geänderte Zeile an.
> git diff foo.txt
diff --git a/foo.txt b/foo.txt
index 1910281..090387f 100644
--- a/foo.txt
+++ b/foo.txt
@@ -1 +1 @@
-foo
\ No newline at end of file
+foo foo
\ No newline at end of file
Die Ausgabe im diff-Format empfinden viele Menschen als schlecht lesbar, sie kann dafür aber gut maschinell verarbeitet werden. Es gibt glücklicherweise eine ganze Reihe von Tools und Entwicklungsumgebungen, die Änderungen übersichtlicher darstellen können (Abbildung 2–3). Dazu nutzt man statt des diff-Befehls den difftool-Befehl.
Abb. 2–3Diff-Darstellung in grafischem Tool (kdiff3)
Änderungen fließen nicht automatisch ins nächste Commit ein. Egal ob eine Datei bearbeitet, hinzugefügt oder gelöscht1 wurde, mit dem add-Befehl bestimmt man, dass die Änderung übernommen werden soll.
> git add foo.txt bar.html bar.txt
Ein weiterer Aufruf des status-Befehls zeigt, was in den nächsten Commit aufgenommen wird:
> git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: bar.html
# deleted: bar.txt
# modified: foo.txt
#
Mit dem commit-Befehl werden genau diese Änderungen übernommen:
> git commit --message "Einiges geändert."
[master 7ac0f38] Einiges geändert.
3 files changed, 2 insertions(+), 2 deletions(-)
create mode 100644 bar.html
delete mode 100644 bar.txt
Der log-Befehl zeigt die Historie des Projekts. Die Commits sind chronologisch absteigend sortiert.
> git log
commit 7ac0f38f575a60940ec93c98de11966d784e9e4f
Author: Rene Preissel <[email protected]>
Date: Thu Dec 2 09:52:25 2010 +0100
Einiges geändert.
commit 2f43cd047baadc1b52a8367b7cad2cb63bca05b7
Author: Rene Preissel <[email protected]>
Date: Thu Dec 2 09:44:24 2010 +0100
Beispielprojekt importiert.
Sie haben jetzt einen Workspace mit Projektdateien und ein Repository mit der Historie des Projekts. Bei einer klassischen zentralen Versionsverwaltung (etwa CVS2 oder Subversion3) hat jeder Entwickler einen eigenen Workspace, aber alle Entwickler teilen sich ein gemeinsames Repository. In Git hat jeder Entwickler einen eigenen Workspacemit einem eigenen Repository, also eine vollwertige Versionsverwaltung, die nicht auf einen zentralen Server angewiesen ist. Entwickler, die gemeinsam an einem Projekt arbeiten, können Commits zwischen ihren Repositorys austauschen. Um dies auszuprobieren, legen Sie einen zusätzlichen Workspace an, in dem Aktivitäten eines zweiten Entwicklers simuliert werden.
Der zusätzliche Entwickler braucht eine eigene Kopie (genannt Klon) des Repositorys. Sie beinhaltet alle Informationen, die das Original auch besitzt, das heißt, die gesamte Projekthistorie wird mitkopiert. Dafür gibt es den clone-Befehl:
> git clone /projekte/erste-schritte
/projekte/erste-schritte-klon
Cloning into erste-schritte-klon...
done.
Im Verzeichnis erste-schritte-klon liegt nun eine Kopie der Projektstruktur wie in Abbildung 2–4 abgebildet.
Ändern Sie die Datei erste-schritte/foo.txt.
> cd /projekte/erste-schritte
> git add foo.txt
> git commit --message "Eine Änderung im Original."
Das neue Commit ist jetzt im ursprünglichen Repositoryerste-schritte enthalten, es fehlt aber noch im Klonerste-schritte-klon. Zum besseren Verständnis zeigen wir hier noch das Log für erste-schritte:
> git log --oneline
a662055 Eine Änderung im Original.
7ac0f38 Einiges geändert.
2f43cd0 Beispielprojekt importiert.
Ändern Sie im nächsten Schritt die Datei erste-schritte-klon/bar.html im Klon-Repository:
> cd /projekte/erste-schritte-klon
> git add bar.html
Abb. 2–4Das Beispielprojekt und sein Klon
> git commit --message "Eine Änderung im Klon."
> git log --oneline
1fcc06a Eine Änderung im Klon.
7ac0f38 Einiges geändert.
2f43cd0 Beispielprojekt importiert.
Sie haben jetzt in jedem der beiden Repositorys zwei gemeinsame Commits und jeweils ein neues Commit. Als Nächstes soll das neue Commit aus dem Original in den Klon übertragen werden. Dafür gibt es den pull-Befehl. Beim Klonen ist der Pfad zum Original-Repository im Klon hinterlegt worden. Der pull-Befehl weiß also, wo er neue Commits abholen soll.
> cd /projekte/erste-schritte-klon
> git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.