Großreinemachen im Repository – Git filter-branch

Es kann durchaus passieren, dass man im frühen Stadium eines Projektes ein Git-Repository aufsetzt, dass alles enthält, was man für das Projekt benötigt. Im Laufe der Zeit fällt dann vielleicht auf, dass man das Ganze besser doch inhaltlich teilen sollte und der Wunsch nach verschiedenen Repositories für Unterordner/Module wächst. Nun könnte man dem ganz naiven Ansatz folgen und einfachwei neue Repos anlegen und den Inhalt aus dem Original kopieren. Das funktioniert. Jedoch wäre es schade um die History. 😉

Zum Glück bringt Git schon ein paar Tools mit, mit welchen man ganz elegant die Repositories managen kann. Die Zauberworte heißen git filter-branch. Damit ist es möglich Dateien und Ordner komplett aus einem Repository, den verschiedenen Branches und deren History zu entfernen.

Angenommen, wir haben ein Repo mit drei Unterordnern A, B und C. Diese sollen jeweils in ein eigenes Repository umziehen. Einen möglicher Weg wäre folgender.

  1. Da filter-branch eine destruktive Operation ist, empfiehlt es sich, ein Backup des Reops anzulegen.
  2. Nun checkt man das original Repo dreimal aus:
    1. git checkout foo@123.456.78.9:bar.git A
    2. git checkout foo@123.456.78.9:bar.git B
    3. git checkout foo@123.456.78.9:bar.git C
  3. Folgende Schritte wiederholt man in jedem der drei ausgecheckten Repos und passt dabei Ordnernamen an. Es werden zuerst die nicht benötigten Ordner aus dem Repository entfernt und anschließend die History bereinigt, wobei leere Commits entfernt werden.
    1. git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch /B /C" --prune-empty -- --all
    2. rm -rf .git/refs/original/ && git reflog expire --all && git gc --aggressive --prune
  4. Zuletzt legt man, sofern erwünscht, auf seinem Server drei neue Repos an, ändert in den drei .git/config Dateien auf dem Client die Pfade zum Remote und pusht seine Änderungen dort hin.
    mkdir A.git
    cd A.git
    git --bare init

    // für alle drei Unterordner angepasst wiederholen

    cd A/
    vim .git/config
    //URL zum Remote anpassen von foo@123.456.78.9:bar.git nach foo@123.456.78.9:A.git
    git push --all
    // für alle drei Unterordner angepasst wiederholen

Auf dem Blog von David Underhill findet man eine ähnliche Anleitung und ein Script, mit dem man das Ganze etwas komfortabler machen kann. Allerdings sollte im filter-branch Command am Ende HEAD durch --prune-empty -- --all ersetzt werden, um die Änderungen auch wirklich auf alle Branches anzuwenden!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.