Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

Was fehlt?

Es liegt in der Natur der Sache: Ein Wiki ist niemals fertig. Wir geben uns große Mühe, mit der Entwicklung Schritt zu halten; lassen Supportanfragen direkt in neue Artikel einfließen … aber auch wir sind nicht perfekt. Wenn du hier nicht fündig wirst: Nicht schmollen - Bescheid sagen! Unter hallo@uberspace.de steht dir unser Team gerne bereit. Hand drauf!

development:git

git

Git ist ein verbreitetes System zur Versionskontrolle, das natürlich auch bei Uberspace.de verfügbar ist. Auf der offiziellen Website ist auch umfangreiche Dokumentation verfügbar. Besonders empfehlenswert ist hier das Git Community Book zu erwähnen, das von erfahrenen Anwendern und Entwicklern der Git-Community zusammengestellt wurde.

Wir können dir hier keine Einführung in Git allgemein liefern - dafür ist das Git-Tutorial besser geeignet. Wir wollen dir aber gerne einen kurzen Überblick geben, wie du Git bei Uberspace.de benutzen kannst, sowohl als Client (um mit Projekten zu arbeiten, die anderswo als Repository bereitgestellt werden) als auch als Server (um selbst ein Repository bereitzustellen).

Eine Besonderheit bei Git ist, dass es vom Konzept her ohne zentrales Repository auskommen kann - jeder kann ein bestehendes Repository klonen und lokal daran weiterarbeiten; andere können dann wiederum auch von dort aus weiter klonen. Kollaboratives Arbeiten kann also von daher auch so laufen, dass bei drei Benutzern jeder wann immer er will Änderungen direkt von den jeweils anderen beiden beziehen. Git unterstützt aber genauso auch den „klassischen“ Betrieb eines zentralen Repositories, was im Grunde einfach nur eine Sonderform des kollaborativen Arbeitens darstellt - dazu gleich mehr. Im Grunde ist Git also eher als eine Art Peer-to-Peer-System zu sehen, in dem jeder Teilnehmer sowohl als Client als auch als Server fungieren kann. In der Praxis bekommen Git-Repositories also ihre Rolle einfach dadurch, wie man sie benutzt.

Git als Client

Wir stellen dir den Befehl git zur Verfügung, mit dem du auf Repositories zugreifen kannst. Ein Repository ist dabei immer entweder unter einer URL erreichbar; typischerweise unter http:// oder https://, oder aber auch unter git://, wenn das Repository via git --daemon bereitgestellt wird. So kannst du beispielsweise Git selbst mittels git ins Verzeichnis mygit klonen:

[martha@eridanus ~]$ git clone git://git.kernel.org/pub/scm/git/git.git mygit

Spätere Änderungen holst du dir mittels git pull ins Haus - da sich Git beim klonen merkt, woher es geklont wurde, braucht hier keine weitere Angabe einer Quelle zu erfolgen:

[martha@eridanus ~]$ cd mygit
[martha@eridanus mygit]$ git pull

Repositories, die du mittels git clone klonst, sind sozusagen Arbeitskopie und Repository in einem, d.h. neben dem Klonen des Repositories wird implizit auch gleich ein Checkout erledigt, mit dem du dann arbeiten kannst.

Git als Server

Git ist hervorragend mit SSH integriert. Auf diese Weise ist es überhaupt kein Problem, beispielsweise von deinem lokalen Rechner aus auf ein Repository zuzugreifen, das sich auf deinem Uberspace befindet. Wir betrachten hier den einfachsten Fall, nämlich dass nur du remote mit dem Repository lesend und schreibend arbeitest.

Möchtest du mehrere Leute für den Zugriff autorisieren (und hierbei auch definieren, wer auf welches Repo mit welchen Rechten zugreifen darf), brauchst du eine Erweiterung auf deinem Uberspace, die dies bereitstellen kann; mit Git-Bordmitteln geht das nicht. Wir haben hierzu das Tool gitolite bereitgestellt und bieten dir auch Dokumentation dazu, wie du es einrichten kannst. Wenn dies für dich die interessantere Lösung ist, brauchst du hier im Grunde nicht weiterzulesen.

Gut, du bist noch da. Dann los - nehmen wir an, du möchtest ein Repository namens „myproject“ anlegen. Es gibt hier zwei Möglichkeiten: Ein normales Repository besteht aus einem Arbeitsverzeichnis, in der sich deine aktuell bearbeitete Arbeitskopie befindet, bei dem die eigentlichen Repo-Daten im Unterverzeichnis .git liegen. Wenn du direkt auf deinem Uberspace entwickeln willst, reicht das bereits aus. Da wir uns aber im Abschnitt „git als Server“ befinden, möchtest du vermutlich deinen Uberspace in puncto Git eher als zentrale Datenablage verwenden und die dort abgelegten Daten auf einen oder auch mehrere Rechner klonen und vor allem Änderungen auch wieder zurückspielen können (in der Git-Terminologie ein „push“). Solche Pushes erlaubt Git standardmäßig nur in sogenannte Bare-Repos - das sind Repositories, die gerade keine Arbeitskopie beinhalten, sondern eben nur die nackten Repo-Daten, die nicht von Hand zu bearbeiten sind.

Und so funktioniert's: Lege ein Verzeichnis ~/myproject.git an (die Endung .git wird als Konvention für Bare-Repos verwendet). Begib dich einfach in dieses Verzeichnis, und lege mit git init --bare ein leeres Bare-Repository an. So sieht's aus:

[martha@eridanus ~]$ mkdir myproject.git
[martha@eridanus ~]$ cd myproject.git
[martha@eridanus myproject]$ git init --bare

Möchtest du jetzt dieses Repository auf deinen lokalen Rechner klonen, gehst du so vor:

[someuser@somehost ~]$ git clone ssh://martha@eridanus.uberspace.de/home/martha/myproject.git/

Nun hast du auf deinem lokalen Rechner ein Verzeichnis myproject, ohne die Endung .git, denn im Gegensatz zu einem Bare-Repo enthält es bereits eine ausgecheckte Arbeitskopie (nur dass hier eben noch nichts vorhanden ist). Du kannst hier nun lokal arbeiten, Änderungen mit git add hinzufügen, mit git commit committen und dann mittels git push origin master auf deinen Uberspace zurückpushen. So sieht's aus:

[someuser@somehost ~]$ git clone ssh://martha@eridanus.uberspace.de/home/martha/myproject.git/
Cloning into myproject...
warning: You appear to have cloned an empty repository.
[someuser@somehost ~]$ cd myproject
[someuser@somehost myproject]$ echo "Hello, world" > test.txt
[someuser@somehost myproject]$ git add test.txt
[someuser@somehost myproject]$ git commit -m "initial commit"
[master (root-commit) bd045da] initial commit
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 test.txt
[someuser@somehost myproject]$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 226 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://martha@eridanus.uberspace.de/home/martha/myproject.git/
 * [new branch]      master -> master

Bei späteren Pushes kannst du dir das … origin master auch sparen; das ist nur beim ersten Anlegen der Branch „master“ nötig. Nun kannst du jederzeit lokal Änderungen vornehmen und auf deinen Uberspace zurückpushen, und wenn du selbst an mehreren Rechnern arbeitest, funktioniert das natürlich auch von allen aus, das heißt, du kannst dein Repo auf Rechner A und Rechner B klonen, auf A Änderungen vornehmen, committen und pushen und dir dann mit einem git pull auf Rechner B jene Änderungen auch auf Rechner B ziehen, wobei sie automatisch mit den Änderungen, die du ggf. bisher nur lokal auf Rechner B vorgenommen hast, zusammengeführt werden.

Öffentlich bereitstellen

Git hat mehrere Protokolle, mit denen du ein Repository öffentlich zugänglich machen kannst.

HTTP

Wir empfehlen dir, ein öffentliches Repository per HTTPS bereitzustellen; das geht ganz einfach über den DocumentRoot. Darüber ist aber kein Schreibzugriff möglich. Jeder andere kann dann per HTTP-URL das Repository klonen, ohne Authentifizierung. Beachte, dass die gesamte Historie deiner Arbeit damit zugänglich wird und so Passwörter herausgefischt werden können, die in der Vergangenheit kurzzeitig im Tree sichtbar waren. Um den Überblick zu behalten kannst du auch einen Klon des Repos im DocumentRoot anlegen.

Beim Export per HTTP(S) ist es wichtig, nach Änderungen im Repository den Befehl git update-server-info auszuführen. Er erstellt einige Hilfsdateien, die dem Client erleichtern, herauszufinden, was alles im Repository enthalten ist. Das musst du allerdings nicht von Hand machen: Über den post-update-Hook kann Git das automatisch tun. Du musst dazu nur den entsprechenden Hook aktivieren, der mit der Endung .sample bereits vorhanden und einfach nur inaktiv ist. Wenn du das Repository direkt per HTTP(S) ansprechen willst, musst du git update-server-info einmalig manuell ausführen; ansonsten wird es beim nächsten Update des Repos über den Hook automatisch ausgeführt.

Smart Protocol

Falls dir HTTP nicht ausreicht, weil du viele Zugriffe oder ein riesiges Repo vorliegen hast, kannst du auch das Smart Protocol verwenden. Dazu musst du Git dauerhaft starten und dir von uns einen Port freischalten lassen. Dann kann das Repo über git: geklont werden. Eine Anleitung dazu findest du im Git-Handbuch.

Am besten sorgst du auch gleich dafür, dass dein Git-Dienst per daemontools dauerhaft läuft. In unserer entsprechenden Sammlung haben wir ein passendes run-Script verlinkt.

Repo verschieben

So verschiebst du das Repo in den DocumentRoot, aktivierst den Hook und legst einmalig die Server-Info-Dateien an:

[martha@eridanus ~]$ mv myproject html
[martha@eridanus ~]$ cd html/myproject
[martha@eridanus myproject]$ mv .git/hooks/post-update.sample .git/hooks/post-update
[martha@eridanus myproject]$ git update-server-info

So können andere nun das Repository klonen (es ist wichtig, das /.git am Ende mit anzugeben - bedenke: Im Verzeichnis myproject liegt nicht das Repo, sondern die ausgecheckte Arbeitskopie; das Repo liegt dann im Unterverzeichnis .git):

[someuser@somehost ~]$ git clone https://martha.eridanus.uberspace.de/myproject/.git

Repo klonen

Wenn du das Repo klonen willst, kannst du auf die Arbeitskopie verzichten. Git nennt dies dann ein „bare repository“, was also nur aus dem besteht, was sich sonst im Unterverzeichnis .git eines normalen Repos befindet. Per Konvention sollten solche Bare-Repos ein .git im Verzeichnisnamen haben; wir benennen das Bare-Repo daher myproject.git. So klonst du es in den DocumentRoot, aktivierst den Hook und legst einmalig die Server-Info-Dateien an:

[martha@eridanus ~]$ git clone --bare myproject html/myproject.git
[martha@eridanus ~]$ cd html/myproject.git
[martha@eridanus myproject.git]$ mv hooks/post-update.sample hooks/post-update
[martha@eridanus myproject.git]$ git update-server-info

So können andere nun das Repository klonen:

[someuser@somehost ~]$ git clone https://martha.eridanus.uberspace.de/myproject.git

Bedenke, dass dieser Klon nicht automatisch aktualisiert wird, wenn du in deinem Original-Repo auf dem Uberspace etwas änderst. Um Änderungen zum HTTP(S)-Export-Klon zu pushen, musst du nach dem Aktualisieren deines Repos auf deinem Uberspace ausführen:

[martha@eridanus ~]$ cd myproject
[martha@eridanus myproject]$ git push ~/html/myproject.git

Du willst, dass das nach einem Commit automatisch geschieht? Dann kannst du den post-commit-Hook dafür benutzen:

[martha@eridanus myproject]$ echo "git push ~/html/myproject.git" > .git/hooks/post-commit
[martha@eridanus myproject]$ chmod +x .git/hooks/post-commit

Das war's - jede Änderung, die auf deinem Uberspace committed wird, wird dann automatisch in den HTTP(S)-Export-Klon übertragen, und Dritte können ihren lokalen Klon des HTTP(S)-Repos mittels eines einfachen git pull ebenfalls auf den neuesten Stand bringen.

RAM-Nutzung

In bisher sehr seltenen Fällen konnten wir reproduzierbar feststellen, dass bei bestimmten Operationen (push, clone, fetch,…) auf einem gar nicht mal sonderlichen großen Repository das auf einem Uberspace liegt, der RAM-Verbrauch des git-Prozesses permanent anstieg, bis der gesamte zur Verfügung stehende Arbeitsspeicher erschöpft war. Gemäß unserer Hausordnung mussten wir in diesem Fall den Prozess hart beenden, um die Beeinträchtigung der anderen Uberspaces auf dem fraglichen Host zu minimieren.

Der entscheidende Hinweis, wie dies sauber in den Griff zu kriegen ist, fand sich bei http://kidsreturn.org/2011/06/setup-git-server-gitolite/ - diese Befehle (die du auf deinem Uberspace ausführen musst) begrenzen die RAM-Nutzung:

[martha@eridanus ~]$ git config --global core.packedGitWindowSize 16m
[martha@eridanus ~]$ git config --global core.packedGitLimit 64m
[martha@eridanus ~]$ git config --global pack.windowMemory 64m
[martha@eridanus ~]$ git config --global pack.packSizeLimit 64m
[martha@eridanus ~]$ git config --global pack.thread 1
[martha@eridanus ~]$ git config --global pack.deltaCacheSize 1m

Anschließend war ein Pushen ins Repository wieder problemlos und schnell möglich.

development/git.txt · Zuletzt geändert: 2014/07/01 17:00 von uber