senäh

17senäh und so…

git_logo_img_only_140

Allgemein
30. Oct 2012
Kommentare: 4

Das Prinzip Git an Beispielen erklärt

Kategorien: Allgemein | 30. Oct 2012 | Kommentare: 4

Serie: Versionskontrolle for the rest of us

Jetzt wo wir die trockene Theorie gepaart mit einem genialen Schema meinerseits hinter uns gelassen und verinnerlicht haben, auf zu konkreten Beispielen.

Vorneweg muss ich euch darauf hinweisen, dass ich diesmal von der allseits beliebten Kommandozeile aus arbeite. Das hat keinen besonderen Grund, außer dass ich es diesmal – im Gegensatz zu SVN – so gelernt habe. Und gepaart mit ein paar TextExpander-Snippets geht das auch flinker von der Hand, als ich es mir in einem Client mit graphischem Interface vorstellen kann. Wenn ihr aber meinem Blog-Kompagnon Pipo lang genug auf die Nerven geht, stellt er euch bestimmt mal Source Tree vor.

Windows-User: werft mal einen Blick hierhin.

Aller Anfang ist git init

Wir machen es diesmal richtig Hands-On. Also sucht euch einen Ordner aus, den ihr mit ein paar Git-Dateien zumüllen wollt und los geht’s. Terminal auf und in den Ordner ge-cd-t. In meinem Fall

1
cd /Users/Enno/Sites/git-tut/

Weiter geht es mit der Initialisierung:

1
git init

Was passiert? Es werden die initialen Dateien angelegt – und zwar im Unterordner .git. Alles was hier drin ist braucht und soll euch nicht interessieren. Finger weg dort, schließlich geschieht hier die ganze Magie.

Git packt übrigens im Gegensatz zu SVN nicht in jeden Unterordner noch mal einen .git-Ordner. Dieser eine reicht.

Immer informiert mit git status

Einen Befehl werdet ihr gar nicht verinnerlichen müssen, weil ihr ihn immer und immer und immer und immer wieder eintippen werdet.

1
git status

Hier erhaltet ihr eine Übersicht über:

  • neue Dateien, die Git noch nicht in seine Versionkontrolle aufgenommen hat,
  • gemachte Änderungen an bestehenden Dateien,
  • Änderungen, die darauf warten comittet zu werden (Staging, siehe letzter Teil),
  • mögliche Konflikte,
  • sowie den aktuellen Branch (normalerweise der Master als Haupt-Branch).

Im Laufe dieses Tutorials werdet ihr die Wichtigkeit dieses Befehls bereits erkennen. Nehmt ihn erstmal als das hin, was er ist: die zentrale Anlaufstelle für alle weiteren Befehle.

Nach der Initialisierung sieht sein Output so aus:

1
2
3
4
# On branch master
#
# Initial commit
#

Wir sind also im Master-Branch und auf der Stufe des initialen Commits. Ein Zeichen, dass es sich um ein leeres Git-Repository handelt. Zeit das zu ändern.

Neue Dateien hinzufügen und stagen

Wir legen erstmal prophylaktisch ein einfaches Readme-File an. Wir können uns ja für unser Projekt wenigstens vornehmen, uns ein wenig um Dokumentation zu kümmern.

1
touch readme.txt

Was sagt git status jetzt?

1
2
3
4
5
6
7
8
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#    readme.txt

Wir sind immer noch in der selben Situation wie vorher (Master-Branch, Initital Commit), allerdings informiert uns Git nun darüber, dass es auf Dateien gestoßen ist, die noch nicht der Versionkontrolle unterliegen.

Ihr erkennt an dieser Stelle auch schon, dass Git uns hier und da sinnvolle Hinweise hinterlässt. In diesem Fall sagt es uns, dass wir git add verwenden sollen, um unsere Readme-Datei von Git tracken zu lassen. Lassen wir heute die Anarchie mal außen vor und tun, was uns befohlen wird.

1
git add readme.txt

Was sagt uns git status anschließend? (ja ihr seht schon, dieses git status drängt sich ziemlich auf…)

1
2
3
4
5
6
7
8
9
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#    new file:   readme.txt
#

Aus den Untracked Files sind Changes to be committed geworden. Unsere readme.txt befindet sich nun offiziel im Staging. Das bedeutet – zur Erinnerung – dass diese Datei beim nächsten Commit berücksichtigt wird. Was ihr tun müsst, um das rückgängig zu machen, zeigt euch Git wieder an. Doch das wollen wir nicht. Wir wollen produktiv sein. Wir machen weiter mit einem Commit.

Commit

Was genau das ist, solltet ihr als aufmerksame Leser dieses Blogs schon durch meine Ausführungen zu SVN wissen. Oder aber ihr habt das tolle Schema aus dem letzten Teil verinnerlicht (und ja, ich verlinke ein weiteres Mal auf den vorangegangen Artikel dieser Serie). Umgesetzt wird er in Git folgerichtig mit git commit.

Die duften Typen unter euch wissen: zu jedem Commit gehört eine Commit-Message, also eine Nachricht, die beschreibt, was man eigentlich genau gemacht hat. Erleichtert später das Suchen bestimmter Änderungen und macht Projektfortschritte besser nachvollziehbar.

Die Nachricht lässt sich über den Parameter -m mitgeben. Also tippen wir in unserem Fall ungefähr sowas hier ein:

1
git commit -m "added documentation file"

Commit-Identifier

Der Terminal-Output sagt jetzt folgendes:

1
2
3
[master (root-commit) 9f19cd4] added documentation file
 0 files changed
 create mode 100644 readme.txt

Die Zahlenfolge 9f19cd4 wird bei euch anders sein. Diese ist der Anfang der Commit-Nummer, die weltweit eindeutig ist. Hier wird also nicht wie bei SVN die Revisionsnummer einfach hochgezählt. Stattdessen gibt es unique Commit-Identifier. Das ist dahingehend sinnvoll, dass Git eigentlich von dezentraler Natur ist. Da es keine zentrale Stelle für ein Repository gibt, macht auch das Hochzählen einer zentralen Revisionsnummer keinen Sinn. In der Praxis sieht das mit den dezentralen Repositories ein bisschen anders aus, aber das ist halb so wild. Wichtig ist, dass ihr mit der kryptischen Zahlenfolge etwas anzufangen wisst.

Der Rest der Ausgabe sagt nur etwas über die Vorgänge beim Commit aus. Erstmal nicht weiter wichtig. Ein anschließendes git status wird uns bestätigen, dass wir keine Änderungen mehr zu comitten haben. Man spricht von einem cleanen Working-Directory. Unterstützend noch mal der genaue Output:

1
2
# On branch master
nothing to commit (working directory clean)

Batch-Staging bei Änderungen

Wir haben bisher nur eine neue Datei angelegt. Wie genau unterscheidet sich der Vorgang, wenn wir eine existierende Datei ändern?

Unwesentlich. Öffnet die readme.txt und schreibt Ich bin die erste Zeile (oder irgendwas anderes) hinein. Anschließend rufen wir einmal mehr git status auf der Kommandozeile auf. Was sagt Herr Output?

1
2
3
4
5
6
7
8
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   readme.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

Die Datei unserer Begierde taucht plötzlich unter Changes not staged for commit auf. Wer aufgepasst hat, weiß: die Datei muss noch gestaged werden. Wer nicht aufgepasst hat, könnte dies auch aus den stets hilfreichen Kommentaren im Output sehen.

  • use “git add …” to update what will be committed oder
  • no changes added to commit (use “git add” and/or “git commit -a”).

Stagen also. Bei einer Datei mag das ja noch ok sein. Was aber wenn wir 10 Dateien haben, die alle noch geadded bzw. gestaged werden müssen? Muss man für jede Datei einzeln git add <Dateiname> aufrufen?

Nein. Es gibt 2 Möglichkeiten. Numero Uno: wir benutzten den Punkt als Wildcard für alle Dateien:

1
git add .

Was auch funktioniert – übrigens immer, wenn es um Datei- bzw. Pfadangaben geht – ist der von den regulären Ausdrücken bekannte Stern. Beispiel:

1
git add path/to/files/*.png

Die zweite Möglichkeit für das Batch-Staging besteht darin, direkt im Commit zu bestimmen, dass alle ungestageten Änderungen mitcomittet werden sollen. Das geschieht über den Parameter -a für all:

1
git commit -a -m "Committed all unstaged files automagically"

Dass ihr hier auch tunlichst darauf achten solltet, dass tatsächlich auch alle Änderungen den aktuellen Commit betreffen, versteht sich von selbst.

What’s left?

Puh, ich hätte anfangs gar nicht gedacht, dass es so viel wird. Und trotzdem gibt es noch eine Reihe von Aspekten, die ich erklären möchte. Darum dürft ihr euch auf den nächsten Teil freuen.

Inhalt?

  • Stashing
  • Reverting
  • GitHub, push und pull
  • Merge

Anschließend solltet ihr aber perfekt gewappnet sein, um in den ersten Kneipengesprächen mit ein bisschen Git-Halbwissen protzen zu können ;)

Wer bis dahin ein bisschen Lust auf Hausaufgaben hat, darf sich gern mal den von Code School (in Kollaboration mit GitHub) erarbeiteten interaktiven Kurs TryGit anschauen. Empfehlung meinerseits!

Autor: Enno

Ich bin Enno. PHP ist mein Ding, aber auch alles Neue rund um die Themen HTML5, CSS3 & Co finde ich interessant. Ich mag es Leuten zu helfen und mein Wissen weiterzugeben. Sollte dir mein Beitrag gefallen haben, lass doch nen Kommentar da oder benutze einen der Social Buttons, um deinen Dank auszudrücken ;)

Kommentare (4)

  1. Für Linux-User, die sich nicht mit der Kommandozeile abgeben wollen, kann ich „git-cola“ empfehlen.

    Cherry-Pick-Staging nicht vergessen, das ist mal das mega-Hammer-Feature im Gegensatz zu svn :) 

    • Danke für den Hinweis für Linux-User :)

      Mit Cherry-Pick-Staging meinst du die Fähigkeit pro Datei jede Änderung einzeln durchgehen zu können um zu bestimmen, ob Sie gestaged werden soll, oder nicht?

    • Jop. Das meine ich. Aber das ist nicht cherry pick. Das ist einfach nur interaktives adden/stagen. So viele verschiedene Sachen. Hab git auch noch lange nicht vollständig begriffen.

    • Wusste ich von, finde ich auch cool. Habe ich aber bisher nie gebraucht, weswegen ich es auch nicht erklären werde.
      Angebot des Gastbeitrags steht aber immer noch ;)