git 1.7, apache2 über https mit smart-http
git 1.7, apache2 über https mit smart-http
git ist svn in vielen Belangen überlegen. Am Eindrücklichsten werden die Vorteile von git von Linus Torvalds, dem Autor von git, erklärt. Es gibt etliche Tutorials und Einführungen zu git.
Seit git-Version 1.6.6 kann man ein remote repository sehr effizient über http(s) betreiben, wenn man smart-http aktiviert. Dies geht, indem man das cgi-Modul von git in einen Webserver einbaut. Dieser Weg ist ähnlich effizient wie git über ssh oder über das git-Protokoll.
Schön ist, dass man für jedes repository einen eigenen apache-vhost verwenden kann. So sind alle Haupt-Projekte sauber voneinander getrennt und haben ihre eigene Benutzerverwaltung. Die Benutzerverwaltung kann natürlich auf alle Arten, die der Apache beherrscht, erfolgen, z.B. LDAP. Im Beispiel verwenden wir Digest-Dateien, man könnte aber auch htpasswd verwenden, solange man ausschließlich https benutzt (hier wird das Passwort verschlüsselt übertragen).
Außerdem müssen keine System-Benutzer für die Verwendung von ssh angelegt werden.
Server-Konfiguration (hier: debian squeeze 6.0)
Voraussetzung: apache2 ist bereits installiert. HTTPS verfügbar, Zertifikate stehen bereit (hier: nicht self-signed)
apt-get install git-coreDatei erzeugen: /etc/apache2/sites-available/git.example.com-ssl
<VirtualHost *:443>
ServerName git.example.com
DocumentRoot /var/www/git.example.com/git
ErrorLog /var/log/apache2/error-git.log
CustomLog /var/log/apache2/access-git.log common
<Location />
AuthType Digest
AuthName git
AuthDigestDomain /
AuthDigestProvider file
AuthUserFile /var/www/git.example.com/password/users.digest
Order allow,deny
Deny from all
Satisfy any
Require valid-user
</Location>
SetEnv GIT_PROJECT_ROOT /var/www/git.example.com/git
SetEnv GIT_HTTP_EXPORT_ALL
# 64 bit only!
ScriptAlias / /usr/lib64/git-core/git-http-backend/
SSLEngine on
SSLProtocol all
SSLCipherSuite HIGH:MEDIUM
SSLCertificateFile /etc/ssl/certs/example_com.crt
SSLCertificateKeyFile /etc/ssl/private/example_com.key
SSLCertificateChainFile /etc/ssl/certs/RapidSSL_Intermediate_CA.pem
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
</VirtualHost>a2ensite git.example.com-sslmkdir /var/www/git.example.com
cd /var/www/git.example.commkdir password
htdigest -c password/users.digest git newusermkdir git
cd gitIm Folgenden wird ein git Repository erzeugt. git Push ist ab Version 1.7 nur noch mit repositories möglich, die mit --bare erzeugt wurden. Das erzeugte Repository ist insofern keine Arbeitskopie.
git init --bareSchreibrechte für apache-Benutzer setzen:
cd ..
chown -R www-data git
service apache2 restartUpdate debian squeeze auf wheezy
Der Skriptalias lautet jetzt:
ScriptAlias / /usr/lib/git-core/git-http-backend/
statt
ScriptAlias / /usr/lib64/git-core/git-http-backend/
Danach apache neu starten:
service apache2 restartFür jedes repository ist Folgendes zu tun:
cd var/www/git.xyz.de/git/<repo-name>
git update-server-info
mv hooks/post-update.sample hooks/post-update
git config http.receivepack true
chown -R www-data *Hierbei werden folgende Probleme gelöst:
Mit dem neuen ScriptAlias wird das git-http-backend wieder richtig eingebunden.
git update-server-info löst folgenden Fehler:
fatal: https://git.xyz.de/git/<repo>/info/refs not found: did you run git update-server-info on the server?.git/hooks/post-update erledigt ein update-server-info automatisch bei Änderungen
http.receivepack true erlaubt pushes. Ansonsten kommt folgender Fehler:
error: Cannot access URL https://heinz@git.xyz.de/git/<repo>/, return code 22. fatal: git-http-push failedMultible Projekte -> Multible repositories
git betrachtet jedoch immer das komplette Projekt, nie einzelne Dateien. Man kann daher nicht wie bei svn einzelne Unterverzeichnisse auschecken. Daher sollte man jedes Projekt in ein eigenes repository legen. Dieser Schritt ist nicht nötig, wenn man nur ein Projekt verwendet (wie im Beispiel oben) oder wenn man jedes Projekt in seinen eigenen apache vhost legt (auch wie im Beispiel)
Auf dem Server lassen sich die verschiedenen repositories in einem apache vhost z.B. so anlegen:
cd /var/www/git.example.com/git
mkdir projectA
cd projectA
git init --bare
cd ..
chown -R www-data projektA
mkdir projectB
cd projectB
git init --bare
cd ..
chown -R www-data projektAusw. Beim Auschecken muss man dann das entsprechende Projekt angeben:
git clone https://git.example.com/projectA projectAClient-Installation (hier: Ubuntu natty 11.04)
git installieren:
sudo apt-get install git In $HOME/.netrc kann das Login festgelegt werden:
machine git.example.com
login newuser
password newuserpassRechte setzen:
chmod 600 ~/.netrcNamen und E-Mail hinterlegen
git config --global user.name "Your Name Comes Here"
git config --global user.email you@yourdomain.example.comvim als Standard-Editor festlegen
git config --global core.editor vimSyntax Highlighting (farbige Formatierung)
git config --global color.branch auto
git config --global color.diff auto
git config --global color.interactive auto
git config --global color.status automaster-Branch erstellen
Da wir Server-seitig keine Arbeitskopie haben, müssen wir den master-Branch Client-seitig erstellen. Dies wird gemacht, indem auf dem Client ein erster commit gemacht wird:
Lokale Arbeitskopie des repositories vom Server herunterladen:
git clone https://git.example.com tmpgit
cd tmpgitÄnderung machen und lokal committen:
touch readme
git add readme
git commit -aAktuelle Branches anzeigen:
git branch liefert die Ausgabe
* mastermaster branch mit auf den Server hochladen:
git push origin master
cd ..Workflow
Mit diesem Workflow werden Änderungen für ein neues Feature zunächst in einem neuen lokalen Branch gemacht. Dort kann beliebig oft committed werden (lokal und remote), ohne den master-Branch anzufassen. Wenn das Feature fertig ist, wird in den master-Branch gemerged. Lokale Arbeitskopie herunterladen (clone) oder bestehende Arbeitskopie aktualisieren (pull):
git clone https://git.example.com gitdir
cd gitdir
git pullStatt git pull kann man auch erstmal die Änderungen prüfen:
git fetch
git diff master origin/master
git merge origin/master Neuen Branch namens new-feature erzeugen, wechseln in new-feature
git checkout --track -b new-featureNun können Änderungen am Quellcode erfolgen, wobei Dateien unter Versionskontrolle zu stellen sind. Beispiel:
touch readme
git add readmeIn branch new-feature committen (nur lokal!), dann den branch new-feature auch ins remote repository stellen (Optional. git push funktioniert ab Version 1.7 nur mit einem bare repository (s.o))
git commit -a
git push origin new-featureAndere Team-Mitglieder können jetzt diesen remote branch auschecken und können darauf mit git pull und git push arbeiten, ohne den master branch anfassen zu müssen.
Wechseln auf master-Branch (im selben Verzeichnis sieht man nun wieder den alten Stand vom master-Branch):
git checkout master
git merge new-featureJetzt sind alle Änderungen des Branches new-feature auch im Branch master und mit einem
git pushauch im master-Branch des Remote Repositories.
Remote Branch auschecken
git clone checkt immer den default Branch aus. Dieser lässt sich pro Repository festlegen und verweist meistens auf den master Branch bzw. auf den letzten Entwicklungsstand. Wenn man jedoch an einem anderen Branch arbeiten möchte, muss man diesen so auschecken:
default branch auschecken:
git clone https://example.com/ gittest
cd gittestgit branch zeigt hierbei nur den default Branch an (hier entsprechend den master Branch):
* masterMan kann jedoch auch alle Branches, inklusive der Remote Branches, anzeigen:
git branch -a Remote Branch experimental auschecken:
git checkout --track -b experimental origin/experimental Jetzt arbeitet man in der lokalen Arbeitskopie auf dem Branch experimental.
Branch löschen
Branch new-feature im lokalen Repository löschen:
git branch -d new-featureBranch new-feature im Remote Repository löschen:
git push origin :new-featureWeitere git Kommandos
Datei untracken (Datei wird danach nicht mehr committed. Datei wird trotz rm nicht gelöscht). Alternative: Von Anfang an .gitignore benutzen.
git rm --cached filenameVersionstag setzen:
git tag -a v0.1Tags auflisten:
git tag -lTag löschen:
git tag -d v0.1Letzte Commit-Kommentare verändern, Commits zusammenfassen
git rebase -i HEAD~5Log formatieren (hier Datum und Commit-Text):
git log --date=short --pretty="tformat:%ad %s"Benutzerverwaltung
git verfügt selbst über keine Benutzerverwaltung. In Verbindung mit smart-http kann man zunächst nur die Authentifizierungsmechanismen des Apache-Webservers benutzen. Hiermit lässt sich immerhin über eine Passwort-Datei definieren, wer Zugriff auf ein Repository bekommt.
Immerhin müssen in Verbindung mit der Apache-Authorisierung keine Systembenutzer angelegt werden, was z.B. bei der Verwendung von ssh nötig wäre.
Benötigt man eine feingranularere Benutzerverwaltung, bietet sich die Verwendung von gitolite an. Dieses funktioniert in neueren Versionen auch mit smart-http.