Wie und warum man git und cogito (in einer Firma) nutzen kann.

1. Einleitung

Dieses Dokument versucht zu erklaeren, warum ein Einsatz von git und cogito in einer Firma sinnvoll ist und wie es von Grund auf eingerichtet wird.

1.1. Fuer wen ist dieses Dokument gedacht?

Der erste Teil (die Einleitung) ist fuer Entscheidungstraeger gedacht. Er erklaert, warum git sinnvoll ist und welche Vorteile man davon hat. Je weiter man an das Ende des Dokumentes kommt, desto technischer werden die Informationen.

1.2. Was ist git und warum gerade git?

Git ist eine sehr einfache zu benutzende Versionskontrolle. Eine Versionskontrolle ist sinnvoll

Dadurch kann man Aenderungen, die zu Fehlern fuehren, schnell identifizieren und rueckgaengig machen (bzw. den entscheidenden Fehler beheben).

Die Vorteile von einer Versionskontrolle fuer Mitarbeiter sind

Warum nun aber gerade git?

1.3. Warum cogito?

Cogito ist eine Sammlung von Shellskripten, die den Umgang mit git noch staerker vereinfachen. Die Entwickler von git und cogito arbeiten sehr nahe zusammen. Dadurch ist eine optimale Zusammenarbeit gewaehrleistet. Cogito bietet durch seine Architektur folgende zusaetzliche Vorteile:

1.4. Warum gitweb?

Gitweb ermoeglicht einen einfachen Zugriff auf die Veraenderungen fuer nicht-Techniker. Des Weiteren ist die Datenbasis via Webbrowser einzusehen. Und die Visualisierung biete eine bessere Usability als cogito oder git.

2. Generelle Nutzung

Git ist eine dezentral organisierte Versionskontrolle. Das bedeutet, dass mehrere Entwicklungen parallel ablaufen koennen und das System ohne einen zentralen Server arbeitet.

Im Klartext heisst das, dass jeder Mitarbeiter jedes Projekt, dass er bearbeitet, losgeloest von den anderen entwickeln kann. Ein Ausfall eines zentralen Servers kann nicht der Grund sein, warum er nicht arbeiten kann.

Das bedeutet auch, dass der Mitarbeiter mit seinem Notebook (zum Beispiel im Zug) weiterentwickeln kann und die Aenderungen unter der Kontrolle der Versionsverwaltung stehen.

3. Installation

Die Installation kann unter modernen Betriebssystemen direkt aus deren Paketverwaltung uebernommen werden. Hier wird jedoch der universelle Weg, eine Installation vom Quelltextarchiv aus, beschrieben.

3.1. Installation git

Das neueste Archiv von http://www.kernel.org/pub/software/scm/git/ herunterladen. Mit tar entpacken (wenn es die .bz2 Version ist: tar -xvjf git-VERSION.tar.bz2). Danach mit cd in das Verzeichnis git-VERSION wechseln und mit make prefix=/usr/packages/git-initial erstellen und mit make prefix=/usr/packages/git-initial install installieren. Mit der folgenden Schleife werden dann die Binaerdaten in den Pfad gelinkt:

for bin in /usr/packages/git-initial/bin/*; do
   ln -s "$bin" /usr/local/bin
done

Nun sollte ein Aufruf von git —version die Version von git ausgeben.

3.2. Installation cogito

Aehnlich wie git wird auch cogito installiert.

Das neueste Archiv von http://www.kernel.org/pub/software/scm/cogito/ herunterladen. Mit tar entpacken (wenn es die .bz2 Version ist: tar -xvjf cogito-VERSION.tar.bz2). Danach mit cd in das Verzeichnis cogito-VERSION wechseln und mit make prefix=/usr/packages/cogito-initial erstellen und mit make prefix=/usr/packages/cogito-initial install installieren. Mit der folgenden Schleife werden dann die Binaerdaten in den Pfad gelinkt:

for bin in /usr/packages/cogito-initial/bin/*; do
   ln -s "$bin" /usr/local/bin
done

Nun sollte ein Aufruf von cg —version die Version von cogito ausgeben.

3.3. Installation gitweb

Die Installation von gitweb wird an dieser Stelle nur der Vollstaendigkeit halber wegen dokumentiert. Gitweb braucht nicht auf "normalen" Rechnern installiern zu werden, sondern nur auf demjenigen, der nachher via Web erreichbar sein soll.

Gitweb benoetigt git installiert. Gitweb selbst ist im aktuellen git enthalten, im Unterverzeichnis gitweb.

Man kopiere gitweb.cgi in das entsprechende cgi-bin des Webservers. Die gitweb.css sollte irgendwo erreichbar auf dem Webserver kopiert werden. Eventuell muessen die Berechtigungen angepasst werden.

Folgende Teile sind in gitweb.cgi anzupassen:

our $gitbin = "/usr/local/bin";
our $projectroot = "/home/server/git";
our $home_text = "$projectroot/indextext.html";
our $stylesheet = "/gitweb.css";
our $projects_list = "$projectroot/git-index";
Note
/home/server ist spezifisch von fsh-alternativ.

Dann muss noch /home/server/git mit mkdir -p /home/server/git angelegt werden. Die weitere Konfiguration wird spaeter am Ende des Dokumentes behandelt.

4. Arbeiten mit git und cogito

Im Folgendem wird anhand mehrerer Beispiele die Arbeitsweise von git und cogito erklaert.

4.1. Neues Projekt

Zunaechst legen wir ein neues Verzeichnis an (mkdir testprojekt) und wechseln dort hinein (cd testprojekt). Anschliessend legen wir eine Testdatei namens test.source an (echo ein test > test.source). Nun initialisieren wir das Verzeichnis und fuegen alle neuen Dateien der Versionskontrolle hinzu (cg-init). Mit cg-log -s wird eine Kurzuebersicht ueber alle eingepflegten Aenderungen angezeigt. Als naechstes veraendern wir die Datei (echo test2 >> test.source) und lassen uns die offenen Aenderungen anzeigen (cg-diff). Dass etwas geaendert wurde, sagt auch cg-status (generell, dass, aber nicht was). Mit cg-commit -m "etwas veraendert" wird die Aenderung in git eingepflegt.

Nun erstellen wir eine neue Datei (echo neu > datei). cg-status zeigt wieder an, dass sich etwas geaendert hat. Mit cg-add datei wird die Datei zur Aufnahme hinzugefuegt. Dies bestaetigt cg-status. Mit cg-commit -m "Datei xyz hinzugefuegt" wird die Datei zur git Datenbank hinzugefuegt.

Zum Loeschen einer Datei aus git wird cg-rm verwendet. Wenn man auch gleich die Datei mitloeschen moechte, so ruft man cg-rm -f auf. Dies ueberprueft man wieder mit cg-status und bestaetigt es mit cg-commit.

Kurzfassung (kann direkt so in die Shell kopiert werden):

# Verzeichnis erstellen
mkdir testprojekt

# Hineinwechseln
cd testprojekt

# Testdatei erstellen
echo ein test > test.source

# git Datenbank initialisieren, alle Dateien im Verzeichnis hinzufuegen
cg-init

# Aenderungen anzeigen lassen:
cg-log -s

# Datei aendern
echo test2 >> test.source

# Unterschied anzeigen lassen
cg-diff

# Generell anzeigen lassen, ob etwas veraendert wurde.
cg-status

# Aenderung einpflegen
cg-commit -m "Was veraendert wurde"

# neue datei erzeugen
echo test2 >> test.source

# anzeigen lassen, dass sich etwas geaendert hat
cg-status

# Datei zum hinzufuegen vormerken
cg-add datei

# hinzufuegen bestaetigen
cg-commit -m "Datei xyz hinzugefuegt"

# Datei aus git Loechen: cg-rm
# Datei aus git Loeschen und auch entfernen: cg-rm -f
cg-rm -f test.source

# Status anzeigen lassen
cg-status

# Loeschen bestaetigen
cg-commit -m "Test.source geloescht"

4.2. Zusammenarbeiten und Visualisierung

Die obige Methode zeigte, wie man alleine mit der Versionsverwaltung git arbeitet. Im Folgenden wird nun gezeigt, wie man mit anderen zusammenarbeitet. Der Einstieg wird ueber eine simple Visualisierung via gitweb gemacht.

4.2.1. Wer anders: Ein Branch

Ein "Branch" ist zu deutsch ein "Zweig" und beschreibt in git einen weiteren Ort, der sich mit denselben Daten beschaeftigt wie wir. Ein Branch hat immer einen Namen (z.B. webserver) und einen zugewiesenen URL.

4.2.2. Beispiel Visualisierung

Vorraussetzung fuer dieses Kapitel ist, dass gitweb, wie oben beschrieben, installiert ist. Es sollte beim Aufruf von gitweb ueber den Browser anzeigen, dass keine Projekte vorhanden sind. Als erstes legen wir die Datei indextext.html' an und schreiben dort "<h1>Testgit</h1>" hinein. Als naechstes erzeugen wir eine leere git-Datenbank mit dem Namen testprojekt.git unterhalb von /home/server/git (`GIT_DIR=/home/server/git/testprojekt.git git-init-db).

Die neue leere Datenbank wird in den git-index mit aufgenommen (echo testprojekt.git >> git-index). Jetzt sollte gitweb im Browser das Projekt anzeigen. Wenn dies nicht der Fall ist, sollte man die Berechtigungen und die Einstellungen in gitweb.cgi ueberpruefen.

Jetzt fuegen wir lokal, in unserem bestehendem Projekt, einen neuen Zweig (Branch) hinzu (cg-branch-add webserver git+ssh://webserver/home/server/git/testprojekt.git). Wir benutzen im Beispiel ssh als Transportprotokoll, es sind jedoch noch viele andere moeglich (siehe cg-branch-add —long-help). Als naechstes uebertragen wir unsere Aenderungen dorthin (cg-push webserver). Nun sollten die Aenderungen im gitweb sichtbar sein. Den Prozess mit cg-push kann man nach jeder Aenderung wiederholen, wenn man den Webserver auch immer aktuell halten moechet.

Zum Abschluss koennen wir im Webserver noch die Beschreibung der git-Datenbank aendern (echo Testprojekt > /home/server/git/testprojekt.git/description).

Zusammenfassung:

# Ins git Verzeichnis wechseln
cd /home/server/git

# indextext.html erzeugen
echo '<h1>Testgit</h1>' > indextext.html

# temporaeres Verzeichnis fuer eine leere git-Datenbank
# Den Namen, den echo ausgibt, ist der Verzeichnisname
tmpgit=$(mktemp -d /tmp/tempgit.XXXXXXX)
echo $tmpgit

# in das neue Verzeichnis wechseln
cd "$tmpgit"

# leere git-Datebank ereugen
git init-db

# .git verschieben
mv .git /home/server/git/testprojekt.git

# leeres Verzeichnis entfernen
rmdir "$tmpgit"

# neue projekt in den index aufnehmen fuer gitweb
echo testprojekt.git >> git-index

# lokal, im bestenden testprojekt (NICHT AUF DEM WEBSERVER!) einen neuen Branch
# hinzufuegen
cg-branch-add webserver git+ssh://webserver/home/server/git/testprojekt.git

# Lokal eingepflegte Sachen in Datenbank auf dem Webserver kopieren
cg-push webserver

# Auf dem Webserver die Beschreibung aendern
echo Testprojekt > /home/server/git/testprojekt.git/description

Dieser gesamte Ablauf ist in dem Skript git_create_and_push_remote.sh zusammengefasst. Man uebergibt dem Skript den Rechner, auf den es uebertragen werden soll, das Unterverzeichnis, den gewuenschten lokalen Zweig und eine Beschreibung: git_create_and_push_remote.sh webserver testprojekt.git webserver "Unser Testprojekt"

4.3. Zusammenarbeiten

Nehmen wir nun an, wir moechten nun mit jemanden (ob eine oder n Personen, n>1, ist relativ egal) zusammenarbeiten. Wir muessen zunaechst unser .git irgendwie verfuegbar machen. Um an das obige Beispiel anzuknuepfen, waere die einfachste Moeglichkeit, /home/server/git via HTTP freizugeben. Die andere Person kann nun mit cg-clone die Datenbank zu sich uebertragen. Dieser kann nun wie gewohnt Aenderungen vornehmen. Das Zurueckuebertragen kann auf mehrere Arten geloest werden: - die zweite Person macht seine Aenderungen auch via Web verfuegbar - die zweite Person bekommt Schreibzugriff via ssh auf unseren Webserver - noch einige andere Methoden, die hier nicht erlaeutert werden

Im ersten Fall, fuegen wir unserer Datenbank einen neuen Zweig (Branch) hinzu (cg-branch-add) und holen uns von dort die aktuellen Aenderungen. Nun koennen wir erstmal seine Aenderungen holen (cg-fetch) ohne sie mit unseren zusammenzufuehren. Das Zusammenfuehren (cg-merge) kann Konflikte hervorrufen, die dann manuell behoben werden muessten. Die beiden Schritte koennen auch vereint werden (cg-update). Nun koennen wir unsere Aenderungen wieder auf unseren Webserver uebertragen (cg-push), danach kann die andere Person sie von dort aus uebertragen (cg-fetch), sie bei sich zusammenfuehren, neue Aenderungen hochladen (cg-push), …

Die zweite Methode waere der Person entweder einen eigenen Benutzer auf unserem System zu geben (useradd) oder einen Benutzer zu definieren, der nur fuer diesen Zweck existiert. Der Zugriff kann dann auch via oeffentlichen Schluesseln ("ssh public keys") geregelt werden. Im Falle, dass verschiedene Nutzer auf das selbe Verzeichnis schreiben ist eventuell eine Regelung ueber Gruppenrechte (sgid bit auf Verzeichnissen) oder ACLs (access control lists) zu verwenden.

Eine weitere Moeglichkeit waere, dass die beiden Personen sich direkt austauschen. Im diesem Fall muss man nur den webserver durch den Rechner des Gegenuebers ersetzen.

Zusammenfassung:

# Datenbank als jemand anders holen
cg-clone http://webserver/git/testprojekt.git

### 1. Fall: Zweite Person bietet seine Aenderungen ueber http an
cg-branch-add weranders http://seinwebserver/url/zur/git/datenbank

# aktuelle Aenderungen von dort holen
cg-fetch weranders

# Aenderungen mit unseren zusammenfuehren
cg-merge

### 2. Fall: Wir geben der zweiten Person Zugriff auf unseren Server
# Die zweite Person fuegt einen neuen Branch hinzu
cg-branch-add webserver git+ssh://person2@webserver/home/server/git/testprojekt.git

# Die zweite Person holt sich unsere Aenderungen
cg-fetch webserver

# Die zweite Person fuegt unsere Aenderungen mit seinen zusammen
cg-fetch webserver

# Die zweite Person kopiert ihre Aenderungen auf unseren Webserver
cg-push webserver

4.4. Visualisierungsprogramme

Die Tatsache, dass die Verwendung von Branches in Git so leicht und schnell ist, fuehrt zu einer bestimmten Arbeitsweise: die Projekte entwickeln viele Branches, und die haben viele und oft komplizierte Zusammenhänge miteinander. Eine Moeglichkeit diese Abhaengigkeiten graphisch darzustellen hilft dem Benutzer sich in seinen Projekten besser orientieren.

Git hat zwei solche Programme mitgeliefert: Gitk und Gitview. Das erste (Gitk) ist das aelteste und am weitesten entwickelte und gehoert zur Git-Standartinstallation. Gitk funktioniert auf allen von Git unterstuetzten Platformen. Gitview wird nicht mitinstalliert, man findet es in compat-Verzeichnis der Git-Quellendistribution. Es ist ein relativ schnelles und einfaches Visualisierungsprogram fuer Git-Graphen. Ein anderes Program is QGit (http://sourceforge.net/projects/qgit). Es ist besser fuer die Entwickler geignet die einige Erfahrung mit CVS oder SVN gesammelt haben. Weitere Visualisierungstools findet man auf Git-Homepage: http://git.or.cz/gitwiki/InterfacesFrontendsAndTools

4.5. Einpflegen von existierenden Quellen

Ein haeufiges Beispiel ist, dass eine Firma neu auf eine Versionskontrolle setzt und nun alle vorhandenen Quellen unter Versionskontrolle stellen moechte. Das folgende Beispiel ist eine Wiedergabe eines echten Falles:

Eine Firma besitzt ca. 40 Unixserver, auf denen Skripte installiert sind und programmiert werden. Es gibt einen neuen Server, auf dem gitweb installiert wurde. Es waere nun der folgende Plan fuer jeden Server abzuarbeiten:

  1. git und cogito installieren

  2. Verzeichnis mit git initialisieren (cg-init) (eventuell vorher .gitignore anlegen)

  3. neuen Zweig (Branch) hinzufuegen (cg-branch-add)

  4. Aenderungen einpflegen (cg-add, cg-commit, cg-rm,…)

  5. Aenderungen an den Server schieben (cg-push)

  6. eventuell Aenderungen vom Server holen (cg-fetch, cg-update)

So sieht man alle Projekte auf dem zentralen Server (sichtbar fuer den Vorgesetzten) und die Programmierer koennen weiterhin auf "ihrem" Server entwickeln.

So koennte es aussehen:

# git und cogito sind schon installiert
# in das richtige Verzeichnis wechseln
cd /pfad/zum/quelltext

# Liste der zu ignorierenden Dateien bearbeiten
$EDITOR .gitignore

# Alle Dateien und Verzeichnisse rekursiv zu git hinzufuegen
# ACHTUNG: Wenn das Verzeichnisse andere Projekte enthaelt,
# die auch unter git-Versionskontrolle stehen, kann es
# zu problemen kommen!
cg-init

# Alternativ: Nur die .git-Datenbank erzeugen
# Anschliessend mit cg-add Dateien hinzufuegen
git-init-db

# Nun den Webserver als Branch hinzufuegen und dort ein Verzeichnis
# erzeugen und das ganze dem git-index hinzufuegen:
#
# Webserver = webserver.firma
# newsletter.git = Unterverzeichnis im git Verzeichnis fuer gitweb
# webserver = Name des Zweigs lokal
# "Newsletter Skripte" = Kommentar fuer gitweb
~/bin/git_create_and_push_remote.sh webserver.firma newsletter.git webserver "Newsletter Skripte"

5. Arbeiten fuer Fortgeschrittene

5.1. Hooks

Hooks sind kleine Programme oder Skripte die bei bestimmten Aktionen (commit, update) automatisch von git oder cogito ausgefuehrt werden.

Alle hooks liegen unterhalb von .git/hooks/. Damit ein Hook ausgefuehrt wird, muss dieser als ausfuehrbar gekennzeichnet sein (chmod u+rx .git/hook/name).

5.1.1. .git/hooks/commit-post

Wird von cg-commit aufgerufen nachdem der commit erfolgreich eingepflegt wurde. Dem Programm werden zwei Parameter uebergeben:

  1. id - ID des gerade hinzugefuegten Commits

  2. branch - Names des Branches

Beispiel:

# Skript erzeugen
echo '#!/bin/sh'        > .git/hooks/commit-post
echo 'echo "Sag etwas"' > .git/hooks/commit-post

# Ausfuehrbar machen
chmod u+rx                .git/hooks/commit-post

# Commit ausfuehren
[11:29] hydrogenium:test% cg-commit -m "Nachricht"
M fo
Committed as 2dc34b3d76406245fbb0004ee2c099e513186a8c
Sag etwas

6. Wartung

Zur Wartung und Aktualisierung von git, cogito und gitweb existieren verschiedene Skripte, die einem das Leben einfacher machen sollen.

6.1. git und cogito

Wenn git und cogito installiert sind, koennen diese beiden wieder durch git und cogito selbst aktualisiert werden. Dazu wird das Skript update-git+cogito.sh verwendet (zu beziehen unter http://unix.schottelius.org/scripts/#update-git+cogito.sh).

Dieses legt aktuelle git und cogito Versionen unter /usr/packages ab und verlinkt die aktuellen Binaerprogramme nach /usr/local/bin.

6.2. gitweb

Zur Aktualisierung von gitweb kann das Skript update-gitweb.sh benutzt werden (zu beziehen unter http://unix.schottelius.org/scripts/#update-gitweb.sh). Es uebertraegt die Konfigurationen aus dem alten gitweb.cgi in das neue gitweb.cgi.

7. Tipps

7.1. Wenn der Autor oder Commiter nicht richtig gesetzt ist…

Es besteht die Moeglichkeit diese Werte manuell via Variablen zu setzen:

export GIT_AUTHOR_NAME="Nico Schottelius"
export GIT_AUTHOR_EMAIL="nico@hydrogenium.schottelius.org"
export GIT_COMMITTER_NAME="Nico Schottelius"
export GIT_COMMITTER_EMAIL="nico@hydrogenium.schottelius.org"

Diese Informationen kann man zum Beispiel in die .profile eintragen, damit sie bei jedem Anmelden verfuegbar sind.

8. weitere Informationen

8.1. URLs, kurze Informationen

8.2. Beitraege