Skip to content

Repositories zusammenführen

Meine Daten, unter anderem den Schriftverkehr, meine Präsentationen und kleinen Skripte, verwalte ich in Git-Repositories (Mehrzahl). Nach längerer Diskussion bin ich zu der Einsicht gekommen, dass es sinnvoller ist, alles in einem einzigen Repository zu haben.

Natürlich möchte ich dabei die Historie nicht verlieren.

Der folgende Weg löst den Import für mich.

Ergänzungen von Euch sind mir jederzeit willkommen.

Im Source-Repository (ausgescheckt nach presentations.git):


$ cd presentations.git

$ tomove=$(ls -1a | egrep -v '^(.|..|.git)$' | xargs)

$ mkdir presentations

$ git mv $tomove presentations

$ git commit -am "Vorbereitung für den Merge"

$ git push

$ cd ..
 

Im Destination-Repository (ausgecheckt in main.git):


$ cd main.git

$ git remote add -f presentations URL/presentations.git

$ git merge --allow-unrelated-histories presentations/master

$ git push

$ git remote remove presentations
 

Versionsverwaltung mit Git ...

Disclaimer vorab:

Von dem Buch habe ich je ein Exemplar als E-Book vom Verlag und in gedruckter Form vom Autoren bekommen.

Da ich Sujeevan empfohlen habe, dieses Buch zu schreiben, werde ich auch in der Danksagung am Anfang des Buches erwähnt.

Der Grund für die Empfehlung war, dass Sujeevan eine sehr gute Artikelserie zum Thema Git in seinem Blog veröffentlicht hat, von der ich dachte, dass sie neu strukturiert eine gute Basis für ein Buch bieten. Und tatsächlich ist im ihm das mit dem vorliegenden Einsteigerwerk über Git auch gelungen.

Anhand eines Beispiels aus der Praxis - persönliche Webseite mit "Bootstrap" - wird der Leser nach dem obligatorischen Kapitel über Versionsverwaltung im Allgemeinen Stück für Stück mit Git vertraut gemacht.

Mir gefällt gut, dass es im Buch hauptsächlich um das Kommandozeilenprogramm git geht und nicht um grafische Clients, wenngleich diesen auch ein eigenes Kapitel gewidmet ist. Git gibt auf der Kommandozeile viele aussagekräftige Meldungen, die für ein Verständnis sehr hilfreich sind.

Wer das Grundlagenkapitel verstanden hat, weiss schoh genug, um alleine mit Git arbeiten zu können.

Die waren Stärken von Git zeigen sich jedoch erst wenn es um Branching und verteile Repositories geht, denen ist jeweils ein eigenes Kapitel gewidmet. Ich empfehle sehr, die Beispiele nachzuvollziehen und die Kapitel durchzuarbeiten, bei der trockenen Lektüre muss man sehr konzentriert bleiben, um nicht verloren zu gehen.

Ein weiterer Pluspunkt für mich ist, dass es typische Arbeitsabläufe skizziert werden und wie man diese mit Git umsetzt. Mit client- oder serverseitigen Hooks kann man sich als Nutzer - vor allem auch im Team - das Leben leichter machen. Tipps & Tricks aus der Praxis runden den Praxisteil ab.

Für mich persönlich hätte es kein Kapitel benötigt, dass den Umstieg von Subversion beschreibt, das "macht man" einmal und dann ist das auch erledigt, die Seiten hätte ich lieber in weiteren Tipps & Tricks gesehen. Trotzdem mag das Thema für einige Leser sehr hilfreich sein.

Die Befehlsreferenz am Ende des Buchs ersetzt das Handbuch in Form von man-pages nicht, hilft aber die häufigsten Optionen im schnellen Zugriff zu haben.

Fazit für mich: Für ein Buch von "nur" rund 260 Seiten ist "Versionsverwaltung mit Git" erstaunlich komplett. Wer das Buch durchgearbeitet hat, kann mit Git arbeiten. Punkt. Statt des Kapitels über Subversion hätte ich mir mehr Tipps gewünscht, das eine oder andere Hilfsprogramm mehr und eine Anleitung, wie man selber Repositories hosten kann. Im Anhang fehlt mir eine Referenz der "nur" vier Objekttypen, die es in Git gibt und auf denen Git aufgebaut ist.

Das Buch ist im wahrsten Wortes Sinn seinen Preis wert und für mich eine echte Empfehlung.

Das deutsche Git-Buch ...

Nachdem der Verlag Open Source Press leider zum 31. Dezember 2015 die Pforten geschlossen hat, haben alle Autoren die Rechte an Ihren Büchern komplett übertragen bekommen.



Valentin Haenel und Julius Plenz, die beiden Autoren von "Git - Verteilte Versionsverwaltung für Code und Dokumente" haben sich entschieden Ihr Buch unter einer Creative Commons Lizenz frei zu geben.



Webseite, das Buch, das Repository und Foliensätze für eine Schulung.



Ich zitiere einmal aus der README.md-Datei:

Falls Du ein DocBook-Experte und/oder Webprogrammierer bist, und denkst: Das Design könnte man ja wohl mal professionalisieren – dann gerne! Ich habe aus den Quelldateien nur schnell eine halbwegs ansehnliche Webseite zusammengestoppelt. Auch sind gegebenenfalls eine PDF- oder EPUB-Version interessant; falls Du dies übernehmen willst, gerne!

Globales gitignore ...

Wenn man Dateien aus der Versionskontrolle mit git ausschliessen möchte, kann man im Repository eine Datei .gitignore anlegen. Das ist sinnvoll, wenn es Dateien gibt, die in nur einem Repository ausgeschlossen werden sollen.

Anders ist es, wenn man Backupdateien des Editors ausschliessen möchte. Da in der Regel mehrere Menschen an einem Projekt arbeiten und vielleicht sogar jeder einen anderen Editor benutzt, ist es sinnvoller, dass jeder die Dateien ausschliesst, die seinem Editor entsprechen.

Dazu kann mit dem folgenden Kommando die globale Variable core.excludesfile gesetzt werden, die einen Dateinamen beinhaltet, in der die globalen Ausschlusskriterien zu finden sind.
git config --global core.excludesfile ~/.gitignore_global


Bei mir enthält sie derzeit nur:
*~
Das sind die Backupdateien von vim.

Git swapped beim Packen ...

Von Zeit zu Zeit lohnt es sich Git-Repositories neu zu packen oder den Müll weg zu bringen (mittels "garbage collection, der Befehl ist git gc).

Auch beim Auschecken oder Klonen von grossen Repositories packt Git neu.

Da ich mit den Standard-Einstellungen regelmässig ware Swap-Orgien erlebt habe, lohnt es sich, die Ressourcen für Git zu begrenzen.

In der Standard-Einstellung benutzt Git pro Core und Hyper-Threading je einen Thread. Da Hyperthreading keinen "echten Prozessor" zur Basis hat, steht aufgrund vieler Kontextwechsel das System nahezu still. Ein System mit zwei Kernen und Hyperthreading wird von Git mit vier Threads konfiguriert und jedem Thread steht im Standard der komplette Arbeitsspeicher zur Verfügung.

Das ist ein bisschen viel. Und die folgenden Konfigurationsoptionen begrenzen das ein wenig.

git config --global pack.threads 2
git config --global pack.windowMemory 1073741824

git config --global pack.depth 250
git config --global pack.window 250


Die genaue Beschreibung der einzelnen Optionen lassen sich auf der git-config-Manpage nachlesen.

Das Repack-Skript auf der oben verlinkten Webseite hat sich damit natürlich auch verändert.

#!/bin/bash

case $(uname) in
    "Linux")
        renice -n 19 -p $$
        ionice -c 2 -n 7 -p $$
        ;;
    "SunOS")
        renice -n 19 -p $$
        ;;
esac

start_directory=$PWD
for i in $(find ${start_directory} -name '.git' -type d); do
    du -hs ${i}/..
    cd ${i}/..

    git gc
    git repack -a -d

    du -hs ${i}/..
    echo
done


Dieses Skript ist Teil meines littlehelpers-Repositories auf GitHub.

Git-Server auf CentOS ...

centos Eigentlich ist "Git-Server" etwas hoch gegriffen, da als Server-Komponente SSH zum Einsatz kommt. Nichtsdestowenigertrotz ist das Endergebnis ein Git-Repository-Server, den man sehr bequem nutzen kann.

Für den Server habe ich einen User git (UserID 600) angelegt, mit dem die Repositories verwaltet werden sollen und das Homeverzeichnis soll unter /srv/git liegen:
groupadd -g 600 git
useradd -u 600          \
        -g 600          \
        -d /srv/git     \
        -m -s /bin/bash \
        git


Eine Besonderheit unter CentOS ist, dass dort SELinux läuft und wir dem System bekanntgeben müssen, dass es sich bei /srv/git um ein Homeverzeichnis handelt. Die einfachste Methode ist, den Kontext eines bestehenden Homeverzeichnisses auf das neue Verzeichnis zu übertragen.
semanage fcontext -a -e /home/dirk /srv/git
restorecon -R -v /srv/
ls -Zd /srv/git

Zu SELinux gibt es reichlich Dokumentation, ich verweise hier einmal auf den SELinux User's and Administrator's Guide bei RedHat. SELinux kann man auch abschalten, wenn einem der Aufwand zu hoch ist.

Der Rest ist relativ einfach und geht strikt nach der gitolite-Anleitung.

Den eigenen Public-Key (wird benötigt, um gitolite zu verwalten) in das Verzeichnis /srv/git kopieren, für mich hat sich dafür das Format user-host.pub bewährt (ich habe auf jedem Host einen separaten SSH-Key und nutze nicht überall den gleichen).
git clone git://github.com/sitaramc/gitolite
mkdir -p ${HOME}/bin
gitolite/install -to ${HOME}/bin
export PATH=${HOME}/bin:${PATH}
echo 'PATH=${HOME}/bin:${PATH}' >> ${HOME}/.bashrc
gitolite setup -pk user-host.pub


Fertig!

Die restliche Konfiguration läuft über das admin-Repository, das man auschecken muss und dann bearbeitet. Die neue Konfiguration ist direkt nach einem git push aktiv.
git clone git@host:gitolite-admin.git gitolite-admin-host.git


Dort finden sich im keydir-Verzeichnis alle Public Keys von Usern, die Zugriff auf irgendeines der Repositories haben sollen und im Verzeichnis conf liegt die gitolite.conf mit einem Beispiel-Repository.

Viel Spass!

GitMinutes und Vimcasts ...

podcast Git ist schon ein geniales Stück Software, vielleicht werde ich in meinem nächsten Leben Software und Configuration Manager, die Aufgabe ist hinreichend komplex, so dass sie lang anhalten Spass machen könnte. Zu Git habe ich den Podcast GitMinutes (Englisch, Episoden finden sich hier) entdeckt, den ich gerade mit sehr grossem Interesse höre. Man kann dort sehr viel über die "Git-Philosophie" und das Umfeld rund um Git erfahren.

Gerade bin ich bei Episode 8 angekommen, in der es um vim und den Workflow mit vim und Git geht. Und da findet sich mein zweites Fundstück, Vimcasts. Vimcasts ist eine Sammlung von - bis jetzt - 50 kurzen Screencasts rund um vim. Gerade in der ersten Folge geht es darum, die unsichtbaren Zeichen (wie Tab und Zeilenenden) anzuzeigen und sinnvoll darzustellen.

GitHub-Universum ...

Je länger ich mich mit Git und insbesondere mit GitHub beschäftige, je besser gefällt es mir. Und das liegt natürlich auch an den Produkten, aber viel mehr gefällt mir die Herangehensweise an Aufgaben und wie die Leute miteinander umgehen. Dass die Seiten - sowohl von Git wie auch von GitHub - ganz ansehnlich sind, schadet natürlich auch nicht.

Wenn Ihr Euch fragt, wie ich auf das Miteinander komme, schaut ich mal das Blog und die Artikel dort an. Wird Zeit, dass die mal hier in der Nähe einen Drinkup machen/

Im GitHub-Universum habe ich die folgenden Dienste entdeckt und würde mich freuen, wenn Ihr mir weitere nennt, solltet Ihr noch andere kennen.

  • GitHub Pages ist "so etwas wie" Webhosting.
  • Gauges ist ein kommerzieller Dienst, der Webstatistiken generiert.
  • Shop für Fanartikel
  • Gist ist eine Art Pastebin für Codeschnippsel, natürlich versionier- und abonnier- und klonbar.
  • Jobs ist die Stellenbörse.
  • Training kann man dort auch buchen.


Last not least möchte ich Speakerdeck erwähnen. Ich habe zwar auch einen Account bei Slideshare, aber als ich Speakerdeck entdeckt habe, hat mir das gleich deutlich besser gefallen. Bei Speakerdeck fehlt das ganze Brimborium und das Ganze ist (für mich) so gut umgesetzt, dass ich gleich alle meine Präsentationen zusammengesucht und dort hochgeladen habe.

Ich bin gespannt, was bei GitHub noch alles passieren wird.

Einführung in Git ...

Bei Google+ wurde ich danach gefragt, ob ich die Kurzeinführung in Git, die ich auf der Arbeit gehalten habe, veröffentlichen könnte. Hier ist sie.

Die Beispiele lohnen sich nur, wenn man sie versucht, nachzuvollziehen.



Viel Spass.

Das PDF (rund 100 kB) kann man hier herunterladen: einfuehrung-git.pdf

Lizenz ist CC-BY, das liefere ich auch noch im PDF nach.

Das kann doch nicht so schwer sein ...

Nachdem ich jetzt fünf mal nacheinander den gleichen Fehler gemacht habe, muss ich das schnell weg dokumentieren.

16:06:27 [root@rico:/srv/www/myown-it.com] # git init .
Initialized empty Git repository in /srv/www/myown-it.com/.git/
16:06:59 [root@rico:/srv/www/myown-it.com] # git add .
16:07:08 [root@rico:/srv/www/myown-it.com] # git remote add origin gitosis@rico.yawnrz.net:www-myown-it.com.git
16:07:23 [root@rico:/srv/www/myown-it.com] # git commit -m "init"
[master (root-commit) 16540f0] init
3296 files changed, 340870 insertions(+)
...
16:07:38 [root@rico:/srv/www/myown-it.com] 1 # git push origin master
Counting objects: 3344, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3263/3263), done.
Writing objects: 100% (3344/3344), 5.47 MiB | 5.52 MiB/s, done.
Total 3344 (delta 794), reused 0 (delta 0)
To gitosis@rico.yawnrz.net:www-myown-it.com.git
* [new branch] master -> master


Ja, das ist Teil meines Backup-Konzeptes.

Git-Repositories packen ...

So ein lebendes Git-Repository ist ziemlicher "Platzverschwender". Mein Hauptrepository, in dem alle meine Dokumente und Scans und Bewerbungen und Skripte und einfach alles liegen, wurde grösser und grösser. Zum Schluss war es bei 16 GB obwohl die "Nutzdaten" nur einen Bruchteil des Repositories ausmachten.

Zeit, einmal einen git repack anzustossen.

Wenn man das unbedarft auf ein grosses Repository loslässt, merkt man sehr schnell, wie langsam der Rechner werden kann, wenn er ins Swapping fällt. Um das einzugrenzen, sollte der Parameter --window-memory gesetzt werden. Meine Beobachtung ist, dass der pro Core gilt. Die Parameter --window und --depth geben die Tiefe und die Anzahl der Objekte für die Delta-Kompression an. -a sorgt dafür, dass alles in gross Packs gepackt wird und -d, dass obsolet gewordene Packs gelöscht werden.

Damit kann man eine Menge erreichen.

16G	ddeimeke.git
Counting objects: 19947, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7173/7173), done.
Writing objects: 100% (19947/19947), done.
Total 19947 (delta 14053), reused 17947 (delta 12645)
6.4G	ddeimeke.git


Allerdings bremst das den Rechner so aus, dass kaum noch arbeiten möglich ist, was man aber mit nice und ionice in den Griff bekommt. Ersteres sorgt dafür, dass die CPU-Benutzung limitiert wird und zweiteres tut gleiches für I/O.

In Summe resultiert das in folgendes kleine Skript.

#!/bin/bash

for i in *.git
do
        du -hsx "${i}"
        cd "${i}"
        nice -n 19 ionice -c 2 -n 7 git repack -a -d --depth=250 --window=250 --window-memory=1g
        cd ..
        du -hsx "${i}"
        echo
done

Arkane Techniken ...

Mir geht schon den ganzen Tag eine Passage aus dem Interview mit Linus Torvalds aus den Fundstücken der letzten Woche nicht aus dem Kopf.

Leute, insbesondere (aber nicht nur) Computerfuzzies, wählen eine Technologie nicht nach objektiven Kriterien.

Insbesondere in der Anfangszeit von Linux, war es ein Zeichen des "anders Seins", dass man ein Betriebssystem nutzt, was die "breite Masse" nicht benutzt. Selbst innerhalb der mittlerweile recht grossen Linux-Community suchen wir nach Linuxen, die jenseits des Mainstreams sind (siehe dazu auch die Distributionssuche bei DeimHart). Git war so lange für die "Hardcore-Geeks" interessant bis es GitHub gab und Git massentauglich wurde. Apple Produkte waren vor allem interessant als sie nur von einer kleinen Masse von Menschen benutzt wurden. Die "Kreativen" wollten sich von der Masse der anderen Anwender abheben.

Linus wird so zitiert:
No technology can ever be too arcane or complicated for the black t-shirt crowd.


Die Kriterien für die Auswahl richten sich selten nach objektiven Kriterien, sondern werden nach Coolness, hohem (!) Preis, Komplexität, und so weiter ... gefällt. Die Hauptsache ist, dass es nicht für jeden taugt oder, dass es sich nicht jeder leisten kann.

Das zeigt in Summe auch grob, die beiden hauptsächlichen Stossrichtungen:
  1. Ich möchte mich von der Masse abheben.
  2. Ich möchte in der Masse untertauchen.


Persönlich fürchte ich, dass ich zur ersten Gruppe zähle und das zum Teil extrem. Und ich kenne viele Argumente, um meine Beweggründe so umformulieren, dass sie nach objektiven Entscheidungen aussehen und nicht nur einfach auf "anders sein" beruhen.

Fakt ist, wer heute Apple benutzt, gibt sich der Uniformität hin, viele Geräte sind objektiv besser es hat aber vor allem auch nichts mehr mit Kreativität zu tun, ein Apple-Device zu verwenden. Ein Betriebssystem, beispielsweise eine Linux-Distribution, nach "nicht Mainstream" auszuwählen, hat auch nichts mit objektiven Kriterien zu tun.

Ach ja, Menschen, die "ums verrecken" anders sein wollen, nennen sich häufig selber Geeks oder Nerds. Wenn man es aber genau nimmt, sollten andere jemanden so nennen ... "Ich bin der König der Welt". Mal sehen, wo die die anders sein wollen, jetzt hingehen.

Mal sehen, wohin der Tross weiterzieht und was der neue "heisse Scheiss" wird.

Fast vergessen: Diese Art der Gruppenbildung und der Abgrenzung gegen andere hat primär nichts mit Technik zu tun. Wo es ganz offensichtlich ist, ist bei reichen Menschen, die sich über exorbitant teure Dinge abheben wollen.

Git Repositories auf andere Server umziehen ...

Mit unserem Umzug von Hetzner zu Manitu müssen auch die ganzen Git-Repositories bewegt werden und ich verstehe jetzt, warum man sagt, dass Git nicht gut mit grossen Binärdateien umgehen kann.

Nach einer Änderung der URL in der .git/config des Repositories und einem herzlichen git push origin --all verabschiedet sich die Maschine ins Swapping. Yippieh!

Ein git gc zeigt das gleiche Resultat. Mit einem git repack --window-memory=1g, gefolgt von einem git push origin --all bin ich allerdings zum Ziel gekommen.

Auf einer zweiten Maschine habe ich die URL auch geändert und ein git pull dort funktioniert bestens.

Gibt es einen geschickteren Weg das anzugehen oder ist die Verfahrensweise richtig so?

$ cd /pfad/zum/repository
$ git repack --window-memory=1g
$ sed -i 's/alter Server/neuer Server/' .git/config
$ git push origin --all

Migration zu Git ...

Jetzt am Wochenende habe ich alle privaten Repositories, darunter die des Adminbuchs von Subversion auf Git umgestellt. Das ganze Verfahren und die Stolpersteine werde ich mal für die Adminstories aufarbeiten. Auf unseren root-Servern habe ich Gitosis installiert (hier ist eine gute Anleitung dazu). Für die eigentliche Migration lohnt sich ein Blick auf den entsprechenden Abschnitt des Pro Git Buchs.

Zum Schluss musste noch die verschiedenen Trac-Instanzen mit einem Git-Plugin aufgerüstet werden.

Um die neuen Vokabeln zu lernen, lohnt sich ein Blick auf den Git - SVN Crash Course.

Versionskontrollsysteme ...

Nachdem ich heute fast drei Stunden lang mein Verzeichnis mit den Dokumenten aufgeräumt habe, denke ich, dass es an der Zeit ist, das alles zusätzlich zu den Skripten und Konfigurationen in ein Versionskontrollsystem zu werfen.

Seit gefühlten 100 Jahren nutze ich Subversion (SVN) und bin auch sehr zufrieden damit, es macht alles, was ich brauche und das sogar sehr gut. Concurrent Versioning System (CVS) habe ich übersprungen, ich bin nie so richtig warm damit geworden. Die Stärken von verteilten "next Generation"-Versionskontrollsystemen - Bazaar (BZR), Git (GIT) und Mercurial (HG) - nutze ich als einzelne Person garantiert nicht aus, aber, da ich eine "faule Sau" bin und auch an Projekten beteiligt bin, die git benutzen, werde ich jetzt darauf umstellen. Dann heisst es nur einmal Vokabeln lernen ;-)

Bedingung war und ist, das über http(s) nutzen zu können, da ich nicht immer in Netzen bin, in denen ssh-Zugriff nach aussen erlaubt ist. Das ist bei git mit Gitosis und Gitweb möglich.

Wen das auch interessiert, dem empfehle ich das Hören von Chaosradio Express 130, da ging es um verteilte Versionskontrollsysteme und da habe ich es auch her, dass sich die einzelnen Systeme nur in Einzelheiten unterscheiden.