git und cogito (Versionskontrolle in Firmen) ============================================ Nico Schottelius 0.1.1, Initial Version from 2006-07-13 :Author Initials: NS Wie und warum man git und cogito (in einer Firma) nutzen kann. 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. 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. Was ist git und warum gerade git? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Git ist eine sehr einfache zu benutzende Versionskontrolle. Eine Versionskontrolle ist sinnvoll - zur Entwicklung von Programmen, - zur Verfolgung von Aenderungen (auch an Dokumenten) - um festzustellen, wer wann was woran geaendert hat. 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 - sie koennen einen Fortschritt erkennen (grosser Motivationsfaktor) - bei Streitigkeiten, kann die Fehlerursache (und der Verursacher) genau festgestellt werden Warum nun aber gerade git? - Es ist schnell. - Es ist Open Source / freie Software (siehe dazu auch "Open Source in Firmen") - Es hat sich an vielen, auch sehr grossen Projekten, wie dem Linux Kernel bewaehrt - Die Unterstuetzung von Entwicklerseite und die Hilfe in der Gemeinschaft ist hervorragend. Fehler werden sehr schnell (teilweise innerhalb von Minuten) in der offiziellen Distribution behoben! - Es ist einfach zu bedienen. 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: - intuitives Arbeiten - schnelles Einpflegen von Informationen - einfacher Zugriff auf die Aenderungen 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. 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. 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. 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. 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. 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. Arbeiten mit git und cogito --------------------------- Im Folgendem wird anhand mehrerer Beispiele die Arbeitsweise von git und cogito erklaert. 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" -------------------------------------------------------------------------------- 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. 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. 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 "

Testgit

" 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 '

Testgit

' > 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"` 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 -------------------------------------------------------------------------------- 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 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: . git und cogito installieren . Verzeichnis mit git initialisieren (`cg-init`) (eventuell vorher .gitignore anlegen) . neuen Zweig (Branch) hinzufuegen (`cg-branch-add`) . Aenderungen einpflegen (`cg-add`, `cg-commit`, `cg-rm`,...) . Aenderungen an den Server schieben (`cg-push`) . 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" -------------------------------------------------------------------------------- Arbeiten fuer Fortgeschrittene ------------------------------ 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'). .git/hooks/commit-post ^^^^^^^^^^^^^^^^^^^^^^ Wird von `cg-commit` aufgerufen nachdem der commit erfolgreich eingepflegt wurde. Dem Programm werden zwei Parameter uebergeben: . id - ID des gerade hinzugefuegten Commits . 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 -------------------------------------------------------------------------------- Wartung ------- Zur Wartung und Aktualisierung von git, cogito und gitweb existieren verschiedene Skripte, die einem das Leben einfacher machen sollen. 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. 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. Tipps ----- 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. weitere Informationen --------------------- URLs, kurze Informationen ~~~~~~~~~~~~~~~~~~~~~~~~~ - gits man-Seiten: http://www.kernel.org/pub/software/scm/git/docs/ - git-Einfuehrung: http://www.kernel.org/pub/software/scm/git/docs/tutorial.html - git-Webseite: http://git.or.cz/ - /usr/packages und /home/server ist ein Teil von fsh-alternativ, das Dokument dazu wird demnaechst auf http://nico.schotteli.us/ veroeffentlicht - git ist auch fuer Windows verfuegbar (ueber eine Cygwin-Installation). - git_create_and_push_remote.sh ist zur Zeit im git unter http://unix.schottelius.org/cgi-bin/gitweb.cgi?p=misc/netstream-sh.git;a=tree zu finden - Kontakt: Der Autor kann unter der oben stehenden E-Post-Adresse kontaktiert werden. Beitraege ~~~~~~~~~ - Die Sektion "Visualisierungsprogramme" stammt von Alex Riesen - Viele Korrekturen stammen von Johannes Schindelin