Simon Szustkowski

Ein Blog über alles, was mir gerade so durch den Kopf geht

Nov 29, 2011

Dotfiles Sync mit git und bash

Dieses Problem dürfte jedem bekannt sein, der mit mehreren Computern mit unixoidem Betriebssystem arbeitet. Man arbeitet an einem Rechner, aber es fehlen aliase und Funktionen, die nur auf einem anderen Computer definiert sind. Eine Sync-Lösung für die .bashrc und andere Dateien (d.h. Dotfiles) wäre praktisch.

Wenn man etwas googlet, findet man mehrere Lösungen. An einer Stelle wird die Dropbox vorgeschlagen, was aber teilweise Root-Rechte auf allen beteiligten Systemen voraussetzt, und immer voraussetzt, dass sämtliche Dropbox-Ordner mitgesynct werden, und man dann Symlinks auf die Stellen setzt, wo das System die Dateien erwartet. Ist mir etwas zu oversized.

Eine weitere Lösung ist der Sync über ein Version Control System, z.B. git. Dies hätte den Vorteil, dass man bei der Programmierung der Scripte auch wirklich den Workflow hat, den man beim sonstigen Programmieren hätte. Es erschien mit aber unzweckmäßig, mein gesamtes Homeverzeichnis in ein git zu packen, und mit der .gitignore unerwünschte Dateien rauszufiltern, weil sich die .gitignore auch auf Unterverzeichnisse auswirkt. Da ich in den Unterverzeichnissen teilweise auch noch andere git-Repos drin hatte, war mir diese Lösung zu riskant. Murphys Law sagt nunmal, dass genau da Nebeneffekte auftreten, wo man sie am wenigsten erwartet.

Eine verbreitete Lösung ist nun, das git-Repo in einem Subfolder anzulegen, und dann mit einem Rakefile die Symlinks zu erzeugen. Das kommt meiner Lösung schon näher, aber wieso unbedingt rake, wenn das die Bash doch auch nativ kann?

Ich habe etwas gegooglet, und bin auf ein Bash-Script gestoßen, was in Zusammenarbeit mit git genau jenes kann. Ich habe es etwas modifizieren müssen, damit es auf Mac OS arbeitet (schließlich unterscheiden sich unter Mac OS und Linux die Pfade zum Homeverzeichnis), und habe hier jetzt die Mac-Version und die Linux-Version am Start.

Die Nutzung ist relativ einfach:

  • Man kopiert das Script irgendwo hin, wo es noch im PATH liegt.
  • Dann konfiguriert man ein Remote Repository so, dass man es ansprechen könnte. Z.B. addet man bei Github den Public Key des Rechner.
  • Jetzt initialisiert man das Dotfiles Repository mit dotfiles setup. Dies legt ein Ordner ~/.dotfiles an, und initialisiert da drin ein git Repository.
  • Das Remote Repository fügt man mit dotfiles setup-remote <url> hinzu.
  • Nun kann man mit dotfiles add <file> die Dateien hinzufügen. Die Datei wird ins Repository kopiert, und der führende Punkt entfernt. Auch das Hinzufügen von Dateien in Unterordnern funktioniert. In der dotfiles.map Datei wird festgehalten, welche Datei im Repository zu welcher “echten” Datei gehört. Um Platz zu sparen wird die Datei nicht wirklich kopiert, sondern ein Hardlink erzeugt. Deswegen ist es auch wichtig, dass ~/.dotfiles auf der gleichen Partition liegt wie das Homeverzeichnis.
  • Der Befehl dotfiles sync synct die Dotfiles nun auf den Server. Hierzu wird das lokale Repo erst committed, dann vom Server gepullt und dabei gemerged, und letztendlich wieder gepusht.
  • Auf einem anderen Server kann man nun mit dotfiles use <file> oder dotfiles use :all die Dateien aus dem gesyncten Repository benutzen. Sollte die entsprechende Datei schon vorhanden sein, wird die vorhandene Datei mit dem Suffix .local gebackupt. Es sei denn natürlich, dass die schon vorhandene Datei identisch ist, dann wird sie einfach überschrieben.
  • Wenn eine solche Datei verändert wurde, können mit dotfiles update die upgedateten Dateien ins Repository reingelinkt werden.

Die Commit-Messages werden automatisch angelegt, und beinhalten die Info, welcher Hostname wann welche Datei geupdatet hat. Wenn man das dann auf allen beteiligten Rechnern gemacht hat, und die Dateien entsprechend gemerged hat, hat man eine einfache Sync-Lösung, die außer git und ssh keine weiteren Tools benötigt.

DISCLAIMER: Ich weiß zwar nicht mehr so wirklich, wo ich das Script her habe, aber da es unter der GPLv2 angeboten wurde, ist mein abgeändertes Script für Mac OS natürlich auch unter der GPLv2 verfügbar.