Git - René Preißel - ebook

Git ebook

René Preißel

0,0

Opis

Git ist ein mächtiges Werkzeug zur verteilten Versionsverwaltung. Es macht vieles möglich, was mit klassischen Versionsverwaltungen gar nicht oder nur unter großen Mühen ging. Gits Vielfalt an Kommandos, Optionen und Konfi- gurationen wirkt anfangs oft einschüchternd - obwohl die Grundkonzepte einfach sind und man meist nur wenige Befehle benötigt. Die Autoren dieses Buches bieten daher zunächst eine kompakte Einführung in die Konzepte und jene Befehle, die man im Entwick- leralltag 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 • Ein Release durchführen • Mit Bisection Fehler suchen • Große Projekte aufteilen Das Buch richtet sich an professionelle Softwareentwickler, die bereits über Erfahrung mit klassischen Versionsverwaltungssystemen wie CVS, Subversion oder ClearCase verfügen. Sie lernen in diesem Buch alle wichtigen Git-Befehle und -Funktionen kennen und erfahren, wie Sie sie effektiv anwenden. Zudem entdecken Sie neue Einsatzgebiete von dezentralen Versionsverwaltungen, die in klassischen, zentralen Systemen nicht existieren. Die 2. Auflage wurde komplett aktualisiert und um ein Kapitel mit nützlichen Tipps und Tricks für die Praxis erweitert. Auch der neue subtree-Befehl wird erläutert. Das Buch zeigt, wie man ihn nutzen kann, um große Projekte besser zu modularisieren.

Ebooka przeczytasz w aplikacjach Legimi na:

Androidzie
iOS
czytnikach certyfikowanych
przez Legimi
Windows
10
Windows
Phone

Liczba stron: 281

Odsłuch ebooka (TTS) dostepny w abonamencie „ebooki+audiobooki bez limitu” w aplikacjach Legimi na:

Androidzie
iOS



René Preißel arbeitet als freiberuflicher Software-Architekt, Entwickler und Trainer. Er beschäftigt sich seit vielen Jahren mit der Entwicklung objektorientierter Anwendungen und Frameworks. Seine Arbeitsschwerpunkte liegen im Bereich Architektur, Java EE und Konfigurationsmanagement.

Mehr Informationen unter www.eToSquare.de.

Bjørn Stachmann arbeitet als Senior Software Engineer mit Schwerpunkt Softwarearchitektur für die etracker GmbH in Hamburg und betreut dort Produktentwicklungen in PHP, Java und C++.

Git

Dezentrale Versionsverwaltung im TeamGrundlagen und Workflows

2., aktualisierte und erweiterte Auflage

René PreißelBjørn Stachmann

René Preißel

Bjørn Stachmann

E-Mail: [email protected]

Lektorat: René Schönfeldt

Copy-Editing: Friederike Daenecke, Zülpich

Satz: Da-TeX, Leipzig

Herstellung: Birgit Bäuerlein

Umschlaggestaltung: Helmut Kraus, www.exclam.de

Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH, 33100 Paderborn

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

Buch 978-3-86490-130-0

PDF 978-3-86491-401-0

ePub 978-3-86491-402-7

2., aktualisierte und erweiterte Auflage 2014

Copyright © 2014 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

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 f7c243994f6e8cebb0e13f6a7e31bbf60f6c6d63Author: Bjørn Stachmann    Leerzeichen hinter Optionen wieder eingefügtAnzahl Commits:    1357Änderungsstatistik: 541 files changed, 271190 insertions(+), 228 deletions(-)Status:# On branch stable# Your branch is ahead of 'origin/stable' by 6 commits.#nothing to commit (working directory clean)

Vorwort

Warum Git?

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 Juli 2013, liefert Google Millionen von Suchtreffern, wenn man nach »git version control« sucht. Für neue Open-Source-Projekte ist es fast schon zum Standard geworden. Viele große Open-Source-Projekte sind bereits zu Git migriert oder sind dabei, dies zu tun.

Arbeiten mit Branches: Mit Git können viele Entwickler parallel auf dezentralen Repositorys arbeiten. Dabei entstehen viele unterschiedliche Entwicklungsstränge. Die Stärke von Git liegt in den Werkzeugen, die helfen, diese Entwicklungsstränge wieder zusammenzuführen: Merging, Rebasing, Cherry-Picking etc.

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 alleine 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 (siehe auch »Pull-Request« auf Seite 125).

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 Mac-Book Air. Das kann sich sehen lassen, wenn man bedenkt, dass über 200.000 Commits und 40.000 veränderte Dateien dazwischen liegen.

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.

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 Plug-ins 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.

Zur zweiten Auflage

Ein Buch für professionelle Entwickler

Ein Projekt aufsetzen → Seite 111

Release durchführen → Seite 179

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. Dieses Buch 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.

Die Zutaten

Gleich ausprobieren! → Seite 9

Erste Schritte: In weniger als einem Dutzend Seiten zeigt ein Beispiel alle wichtigen Git-Befehle.

Was sind Commits? → Seite 19

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.

Tipps und Tricks → Seite 101

Workflow-Verzeichnis → Seite 263

Workflows: Workflows beschreiben Szenarien, wie man Git im Projekt einsetzen kann, zum Beispiel wenn man ein Release durchführen möchte (»Ein Release durchführen« (Seite 179)). Für jeden Workflow wird beschrieben,

welches Problem er löst,

welche Voraussetzungen dazu gegeben sein müsssen 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 260

»Schritt für Schritt«-Anleitungen Häufig benötigte Befehlsfolgen, wie zum Beispiel »Einen Branch verschieben« (Seite 69), haben wir in »Schritt für Schritt«-Anleitungen beschrieben.

Warum Workflows?

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 alles machbar. 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 11 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, so 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 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 speziellen Anforderungen, die sich für Großprojekte ergeben, weil sie die Workflows deutlich aufgebläht hätten und weil wir glauben, dass sie für die meisten Entwickler nicht so interessant sind. Ebenfalls unberücksichtigt bleibt die Open-Source-Entwicklung, obwohl es auch dafür sehr interessante Workflows mit Git gibt.

Tipps zum Querlesen

Als Autoren wünschen wir uns natürlich, dass Sie unser Buch von Seite 1 bis Seite 258 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 gerade 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, lautet die Antwort: am besten ja. 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 11 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 5, Das Repository

Kapitel 8, Mit Rebasing die Historie glätten

Kapitel 10, Versionen markieren

Kapitel 11, Abhängigkeiten zwischen Repositorys

Wo finde ich was?

Workflow-Verzeichnis → Seite 263

Workflows: Ein Verzeichnis aller Workflows mit Kurzbeschreibungen und Überblicksabbildung finden Sie im Anhang.

Anleitungsverzeichnis → Seite 260

»Schritt für Schritt«-Anleitungen: Wir haben alle Anleitungen im Anhang aufgelistet.

Index → Seite 269

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 jene Seitenzahl fett hervorgehoben, wo Sie am meisten Informationen zu dem Befehl oder der Option finden.

Index → Seite 269

Fachbegriffe: Fachbegriffe, wie zum Beispiel »First-Parent-Historie« oder »Remote-Tracking-Branch«, finden Sie natürlich auch im Index.

Beispiele und Notation

Grafische Werkzeuge für Git → Seite 246

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 Plug-ins 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 funk-tionieren,

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 --versiongit version 1.8.3.4

Danksagungen

Danksagungen zur ersten Auflage

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-Kernel neuerdings nutzen würden . . .

Danksagungen zur zweiten Auflage

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 Korrekturvorschlägen, Fragen 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.

»Standing on the Shoulders of Giants«

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.

http://www.sourcetreeapp.com/http://code.google.com/p/tortoisegit/http://www.syntevo.com/smartgit/http://gitx.frim.nl/http://code.google.com/p/gitextensions/http://jonas.nitro.dk/tig/http://sourceforge.net/projects/qgit/http://www.jetbrains.com/idea/http://developer.apple.com/technologies/tools/http://eclipse.org/egit/http://nbgit.org/http://code.google.com/p/gitextensions/

Inhaltsverzeichnis

Erste Schritte

1        Grundlegende Konzepte

1.1     Dezentrale Versionsverwaltung – alles anders?

1.2     Das Repository – die Grundlage dezentralen Arbeitens

1.3     Branching und Merging – ganz einfach!

1.4     Zusammenfassung

2        Erste Schritte

2.1     Git einrichten

2.2     Das erste Projekt mit Git

2.3     Zusammenarbeit mit Git

2.4     Zusammenfassung

Arbeiten mit Git

3        Was sind Commits?

3.1     Zugriffsberechtigungen und Zeitstempel

3.2     Die Befehle add und commit

3.3     Exkurs: Mehr über Commit-Hashes

3.4     Eine Historie von Commits

3.5     Eine etwas andere Sichtweise auf Commits

3.6     Viele unterschiedliche Historien desselben Projekts

3.7     Zusammenfassung

4        Commits zusammenstellen

4.1     Der Status-Befehl

4.2     Der Stage-Bereich speichert Momentaufnahmen

4.3     Was tun mit Änderungen, die nicht übernommen werden sollen?

4.4     Mit .gitignore Dateien unversioniert lassen

4.5     Stashing: Änderungen zwischenspeichern

4.6     Zusammenfassung

5        Das Repository

5.1     Ein einfaches und effizientes Speichersystem

5.2     Verzeichnisse speichern: Blob & Tree

5.3     Gleiche Daten werden nur einmal gespeichert

5.4     Kompression ähnlicher Inhalte

5.5     Ist es schlimm, wenn verschiedene Daten zufällig denselben Hashwert bekommen?

5.6     Commits

5.7     Wiederverwendung von Objekten in der Commit-Historie

5.8     Umbenennen, verschieben und kopieren

5.9     Zusammenfassung

6        Branches verzweigen

6.1     Parallele Entwicklung

6.2     Bugfixes in älteren Versionen

6.3     Branches

6.4     Swimlanes

6.5     Aktiver Branch

6.6     Branch-Zeiger umsetzen

6.7     Branch löschen

6.8     Und was ist, wenn man die Commit-Objekte wirklich loswerden will?

6.9     Zusammenfassung

7        Branches zusammenführen

7.1     Was passiert bei einem Merge?

7.2     Konflikte

7.3     Bearbeitungskonflikte

7.4     Konfliktmarkierungen

7.5     Bearbeitungskonflikte lösen

7.6     Und was ist mit den inhaltlichen Konflikten?

7.7     Fast-Forward-Merges

7.8     First-Parent-History

7.9     Knifflige Merge-Konflikte

7.10   Egal, es wird schon irgendwie gehen

7.11   Zusammenfassung

8        Mit Rebasing die Historie glätten

8.1     Das Prinzip: Kopieren von Commits

8.2     »Diamantenketten« vermeiden

8.3     Und wenn es zu Konflikten kommt?

8.4     Branches umpflanzen

8.5     Was passiert mit den ursprünglichen Commits nach dem Rebasing?

8.6     Warum ist es problematisch, Original und Kopie eines Commits im gleichen Repository zu haben?

8.7     Cherry-Picking

8.8     Zusammenfassung

9        Austausch zwischen Repositorys

9.1     Repositorys klonen

9.2     Wie sagt man Git, wo das andere Repository liegt?

9.3     Anderen Repositorys einen Namen geben

9.4     Abholen von Daten

9.5     Remote-Tracking-Branches: Wissen, was in anderen Repositorys »los« ist

9.6     Lokal mit Branches aus anderen Repositorys arbeiten

9.8     Für Diamantenhasser: --rebase

9.9     Push – das Gegenstück zu Pull

9.10   Jeder so, wie er mag

9.11   Zusammenfassung

10      Versionen markieren

10.1    Arbeiten mit Tags erstellen

10.2    Welche Tags gibt es?

10.3    Die Hashes zu den Tags ausgeben

10.4    Die Log-Ausgaben um Tags anreichern

10.5    In welcher Version ist es »drin«?

10.6    Wie verschiebt man ein Tag?

10.7    Und wenn ich ein »Floating Tag« brauche?

10.8    Zusammenfassung

11      Abhängigkeiten zwischen Repositorys

11.1    Abhängigkeiten mit Submodulen

11.2    Abhängigkeiten mit Subtrees

11.3    Zusammenfassung

12      Tipps und Tricks

12.1    Keine Panik – Es gibt ein Reflog!

12.2    Lokale Änderungen temporär ignorieren

12.3    Änderungen an Textdateien untersuchen

12.4    alias – Abkürzungen für Git-Befehle

12.5    Branches als temporäre Zeiger auf Commits nutzen

12.6    Commits auf einen anderen Branch verschieben

Workflows

13      Workflow-Einführung

13.1    Warum Workflows?

13.2    Welche Workflows sind wann sinnvoll?

13.3    Aufbau der Workflows

Workflows: Entwickeln mit Git

14      Ein Projekt aufsetzen

14.1    Ablauf und Umsetzung

14.2    Warum nicht anders?

15      Gemeinsam auf einem Branch entwickeln

15.1    Ablauf und Umsetzung

15.2    Warum nicht anders?

16      Mit Feature-Branches entwickeln

16.1    Ablauf und Umsetzung

16.2    Warum nicht anders?

17      Mit Bisection Fehler suchen

17.1    Ablauf und Umsetzung

17.2    Warum nicht anders?

Workflows: Entwicklungsprozess

18      Mit einem Build-Server arbeiten

18.1    Ablauf und Umsetzung

18.2    Warum nicht anders?

19      Ein Release durchführen

19.1    Ablauf und Umsetzung

19.2    Warum nicht anders?

Workflows: Repositorys pflegen

20      Große Projekte aufteilen

20.1    Ablauf und Umsetzung

20.2    Warum nicht anders?

21      Kleine Projekte zusammenführen

21.1    Ablauf und Umsetzung

21.2    Warum nicht anders?

22      Lange Historien auslagern

22.1    Ablauf und Umsetzung

22.2    Warum nicht anders?

Workflows: Umstieg auf Git

23      Andere Versionsverwaltungen parallel nutzen

23.1    Ablauf und Umsetzung

23.2    Warum nicht anders?

24      Ein Projekt nach Git migrieren

24.1    Ablauf und Umsetzung

24.2    Warum nicht anders?

Mehr über Git

25      Was gibt es sonst noch?

25.1    Interaktives Rebasing – Historie verschönern

25.2    Umgang mit Patches

25.3    Patches per Mail versenden

25.4    Bundles – Pull im Offline-Modus

25.5    Archive erstellen

25.6    Grafische Werkzeuge für Git

25.7    Repository im Webbrowser anschauen

25.8    Zusammenarbeit mit Subversion

25.9    Aliase für Befehle

25.10  Notizen an Commits

25.11  Hooks – Git erweitern

25.12  Github – Hosting von Repositorys

26      Das sechsundzwanzigste Kapitel

27      Grenzen von Git

27.1    Hohe Komplexität

27.2    Komplizierter Umgang mit Submodulen

27.3    Ressourcenverbrauch bei großen binären Dateien

27.4    Repositorys können nur vollständig verwendet werden

27.5    Autorisierung nur auf dem ganzen Repository

27.6    Mäßige grafische Werkzeuge für Historienauswertung

Index und Verzeichnisse

»Schritt für Schritt«-Anleitungen

Workflow-Verzeichnis

Index

1 Grundlegende Konzepte

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.

1.1 Dezentrale Versionsverwaltung – alles anders?

Bevor wir uns den Konzepten dezentraler Versionsverwaltung widmen, werfen wir einen kurzen Blick auf die klassische Architektur zentraler Versionsverwaltungen.

Abb. 1-1 Zentrale Versionsverwaltung

Abbildung 1-1 zeigt die typische Aufteilung einer zentralen Versions-verwaltung, z. B. von CVS oder Subversion. Jeder Entwickler hat auf seinem Rechner ein Arbeitsverzeichnis (Workspace) mit allen Projektdateien. Diese bearbeitet er, und er 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-2 Dezentrale Versionsverwaltung

Das Repository → Seite 37

Was sind Commits? → Seite 19

Austausch zwischen Repositorys → Seite 73

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:

Blessed Repository: Aus diesem Repository werden die »offiziellen« Releases erstellt.

Ein Projekt aufsetzen → Seite 111

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 Releasezyklus 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.

1.2 Das Repository – die Grundlage dezentralen Arbeitens

Das Repository ist im Kern ein effizienter Datenspeicher. Im Wesentlichen enthält es:

Das Repository → Seite 37

Inhalte von Dateien (Blobs): Dies sind Texte oder binäre Daten. Die Daten werden unabhängig von Dateinamen gespeichert.

Verzeichnisse (Trees): Verzeichnisse verknüpfen Dateinamen mit Inhalten. Verzeichnisse können wiederum andere Verzeichnisse beinhalten.

Versionen (Commits): Versionen definieren einen wiederherstellbaren Zustand eines Verzeichnisses. Beim Anlegen einer neuen Version werden der Autor, die Uhrzeit, ein Kommentar und die Vorgänger-version gespeichert.

Abb. 1-3 Ablage von Objekten im Repository

Für alle Daten wird ein hexadezimaler Hashwert berechnet, z. B. 1632acb65b01c6b621d6e1105205773931bb1a41. Diese Hashwerte dienen 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:

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 zwischenRepositorys: 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 Daten: Der Hashwert wird aus dem Inhalt der Daten berechnet. Man kann Git jederzeit prüfen lassen, ob Daten und Hash-werte zueinanderpassen. 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 Inhaltes nicht ändert. Es sind somit keine speziellen Befehle zum Umbenennen und Verschieben notwendig.

1.3 Branching und Merging – ganz einfach!

Branches verzweigen → Seite 45

Die Entwicklung aufzuzweigen (Branching) und wieder zusammenzuführen (Merging) sind bei den meisten Versionsverwaltungen Ausnahmesituationen und gehören 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 vielen Einzelergebnisse ist dabei eine der größten Herausforderungen. Deshalb ist Git 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. Nachdem beide Entwickler Änderungen durchgeführt haben, wird jeweils ein neues Commit angelegt. 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 entsteht daraus ein Merge-Commit, das beide Änderungen enthält. Wenn der andere Entwickler dieses Commit abholt, sind beide wieder auf einem gemeinsamen Stand.

Abb. 1-4 Branches entstehen durch paralleles Arbeiten.

Mit Feature-Branches entwickeln → Seite 135

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 (siehe Abbildung 1-5). Dies wird häufig genutzt, um die parallele Entwicklung von Features zu koordinieren (Feature-Branches).

Abb. 1-5 Explizite 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:

Umpflanzen von Branches: Die Commits eines Branch können auf einen anderen Branch verschoben werden.

Mit Rebasing die Historie glätten → Seite 65

Übertragen einzelner Änderungen: Einzelne Commits können von einen Branch auf einen anderen Branch kopiert werden, z. B. Bugfixes (was Cherry-Picking genannt wird).

Historie aufräumen: Die Historie eines Branch kann umgestaltet werden, d. h., 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).

Interaktives Rebasing → Seite 243

1.4 Zusammenfassung

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 → Seite 9

Workflow-Einführung → Seite 107

Für die erste Frage lesen Sie schnell das nächste Kapitel. Dort erfahren Sie konkret, mit welchen Befehlen Sie ein Repository anlegen, Dateien versionieren und Commits zwischen Repositorys austauschen können. Für die anderen Fragen gibt es 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 »Grenzen von Git« ab Seite 253 an.

2 Erste Schritte

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.

2.1 Git einrichten

Zunächst müssen Sie Git installieren. Sie finden alles Nötige hierzu auf der Git-Website:

http://git-scm.com/download

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.email "[email protected]"

2.2 Das erste Projekt mit Git

Am besten ist es, wenn Sie ein eigenes Projekt verwenden, um Git zu erproben. Beginnen Sie mit einem einfachen kleinen Projekt. Unser Beispiel zeigt ein winziges Projekt namens erste-schritte mit zwei Textdateien.

Abb. 2-1 Unser 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.

Repository anlegen

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 initInitialized 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-2 Das Repository-Verzeichnis

Das erste Commit

Als Nächstes können Sie die Dateien foo.txt und bar.txt ins Repository bringen. Eine Projektversion heißt bei Git ein Commit und 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 sogenannten Commit-Hash (hier 2f43cd0), der das neue Commit identifiziert.

> 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

Status abfragen

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.htmlno changes added to commit (use "git add" and/or "git commit -a")

Abb. 2-3 Diff-Darstellung in grafischem Tool (kdiff3)

Wenn Sie mehr Details wissen wollen, zeigt Ihnen der diff-Befehl jede geänderte Zeile an. 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).

> git diff foo.txtdiff --git a/foo.txt b/foo.txtindex 1910281..090387f 100644--- a/foo.txt+++ b/[email protected]@ -1 +1 @@-foo\ No newline at end of file+foo foo\ No newline at end of file

Ein Commit nach Änderungen

Für jedes neue Commit müssen die Änderungen angemeldet werden. Für geänderte und neue Dateien erledigt dies der add-Befehl. Gelöschte Dateien müssen mit dem rm-Befehl als gelöscht markiert werden.

> git add foo.txt bar.html> git rm bar.txtrm '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 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

Historie betrachten

Der log-Befehl zeigt die Historie des Projekts. Die Commits sind chronologisch absteigend sortiert.

> git logcommit 7ac0f38f575a60940ec93c98de11966d784e9e4fAuthor: Rene Preissel <[email protected]>Date:   Thu Dec 2 09:52:25 2010 +0100    Einiges geändert.commit 2f43cd047baadc1b52a8367b7cad2cb63bca05b7Author: Rene Preissel <[email protected]>Date:   Thu Dec 2 09:44:24 2010 +0100    Beispielprojekt importiert.

2.3 Zusammenarbeit mit Git

Sie haben jetzt einen Workspace mit Projektdateien und ein Repository mit der Historie des Projekts. Bei einer klassischen zentralen Versionsverwaltung (etwa CVS1 oder Subversion2) hat jeder Entwickler einen eigenen Workspace, aber alle Entwickler teilen sich ein gemeinsames Repository. In Git hat jeder Entwickler einen eigenen Workspacemit einem eigenenRepository, 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.

Repository klonen

Der zusätzliche Entwickler braucht eine eigene Kopie (genannt Klon) des Repositorys. Sie beinhaltet alle Informationen, die das Original auch besitzt, d. h., die gesamte Projekthistorie wird mitkopiert. Dafür gibt es den clone-Befehl.

> git clone /projekte/erste-schritte            /projekte/erste-schritte-klonCloning into erste-schritte-klon...done.

Die Projektstruktur sieht nun so wie in Abbildung 2-4 auf Seite 14 aus.

Änderungen aus einem anderen Repository holen

Ändern Sie die Datei erste-schritte/foo.txt.

> cd /projekte/erste-schritte> git add foo.txt> git commit --message "Eine Änderung im Original."

Abb. 2-4 Das Beispielprojekt und sein Klon

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 --onelinea662055 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> git commit --message "Eine Änderung im Klon."> git log --oneline1fcc06a 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 pullremote: Counting objects: 5, done.remote: Compressing objects: 100% (2/2), done.remote: Total 3 (delta 0), reused 0 (delta 0)Unpacking objects: 100% (3/3), done.From /projekte/erste-schritte   7ac0f38..a662055   master    -> origin/masterMerge made by recursive. foo.txt |   2 +- 1 files changed, 1 insertions(+), 1 deletions(-)

Der pull-Befehl hat die neuen Änderungen aus dem Original abgeholt, mit den lokalen Änderungen im Klon verglichen und beide Änderungen im Workspace zusammengeführt und ein neues Commit daraus erstellt. Man nennt dies einen Merge.

Branches zusammenführen → Seite 53

Achtung! Gelegentlich kommt es beim Merge zu Konflikten. Dann kann Git die Versionen nicht automatisch zusammenführen. Dann müssen Sie die Dateien zunächst manuell bereinigen und die Änderungen danach mit einem Commit bestätigen.

Ein erneuter log-Befehl zeigt das Ergebnis der Zusammenführung nach dem pull an. Diesmal nutzen wir eine grafische Variante des Logs.

> git log --graph*  9e7d7b9 Merge branch 'master' of /projekte/erste-schritte|\| * a662055 Eine Änderung im Original.* | 1fcc06a Eine Änderung im Klon.|/* 7ac0f38 Einiges geändert.* 2f43cd0 Beispielprojekt importiert.

Die Historie ist nun nicht mehr linear. Im Graphen sehen Sie sehr schön die parallele Entwicklung (mittlere Commits) und das anschließende Merge-Commit, mit dem die Branches wieder zusammengeführt wurden (oben).

Änderungen aus beliebigen Repositorys abholen

Der pull-Befehl ohne Parameter funktioniert nur in geklonten Repositorys, da diese eine Verknüpfung zum originalen Repository haben. Beim pull-Befehl kann man den Pfad zu einem beliebigen Repository angeben. Als weiterer Parameter kann der Branch (Entwicklungszweig) angegeben werden, von dem Änderungen geholt werden. In unserem Beispiel gibt es nur den Branchmaster, der als Default von Git automatisch angelegt wird.

> cd /projekte/erste-schritte> git pull /projekte/erste-schritte-klon masterremote: Counting objects: 8, done.remote: Compressing objects: 100% (4/4), done.remote: Total 5 (delta 0), reused 0 (delta 0)Unpacking objects: 100% (5/5), done.From /projekte/erste-schritte-klon *  branch          master       -> FETCH_HEADUpdating a662055..9e7d7b9Fast-forward bar.html |    2 +- 1 files changed, 1 insertions(+), 1 deletions(-)

Ein Repository für den Austausch erstellen

Abb. 2-5 »Bare-Repository«: ein Repository ohne Workspace

Neben dem pull-Befehl, der Commits von einem anderen Repository holt, gibt es auch einen push-Befehl, der Commits in ein anderes Repository überträgt. Der push-Befehl sollte allerdings nur auf Repositorys angewendet werden, auf denen gerade kein Entwickler arbeitet. Am besten erzeugt man sich dazu ein Repository ohne einen Workspace drumherum. Ein solches Repository wird als Bare-Repository bezeichnet. Es wird durch die Option --bare des clone-Befehls erzeugt. Man kann es als zentrale Anlaufstelle verwenden. Entwickler übertragen ihre Commits mit dem (push-Befehl) dorthin und holen sich mit dem pull-Befehl die Commits der anderen Entwickler dort ab. Man verwendet die Endung .git, um ein Bare-Repository zu kennzeichnen. Das Ergebnis sehen Sie in Abbildung 2-5.

> git clone --bare /projekte/erste-schritte                   /projekte/erste-schritte-bare.gitCloning into bare repository erste-schritte-bare.git...done.

Änderungen mitpushhochladen

Abb. 2-6 Austausch über ein gemeinsames Repository

Zur Demonstration des push-Befehls ändern Sie noch mal die Datei erste-schritte/foo.txt und erstellen ein neues Commit.

> cd /projekte/erste-schritte> git add foo.txt> git commit --message "Weitere Änderung im Original."

Dieses Commit übertragen Sie dann mit dem push-Befehl in das zentrale Repository (Abbildung 2-6). Dieser Befehl erwartet dieselben Parameter wie der pull