Gibt es Fallstricke, um $ HOME in Git zu setzen, anstatt Punktdateien zu verknüpfen?

38

Ich habe seit vielen Jahren mein gesamtes $HOMEVerzeichnis in Subversion eingecheckt. Dies beinhaltete alle meine Punktedateien und Anwendungsprofile, viele Skripte, Tools und Hacks, meine bevorzugte Basisstruktur für das Home-Verzeichnis, nicht nur einige seltsame Projekte und ein Warehouse mit zufälligen Daten. Das war eine gute Sache. Solange es dauerte.

Aber es ist außer Kontrolle geraten. Die grundlegende Kaufabwicklung ist auf Dutzenden von Systemen gleich, aber nicht alle diese Dinge sind für alle meine Maschinen geeignet. Es spielt nicht einmal alles gut mit verschiedenen Distributionen.

Ich bin gerade dabei, das Haus zu säubern - die Daten dort zu trennen, wo sie hingehören, einige Skripte als separate Projekte aufzuteilen, einige defekte Links in Sachen zu reparieren, die automatisiert werden sollten usw.

Meine Absicht ist , zu ersetzen , subversionmit gitder Top - Level - Kasse von $HOME, aber ich möchte diese nach unten pare nur auf die Dinge , die ich auf alle meine Systeme haben möchten, was bedeutet , dotfiles, einige Verzeichnisse und einige grundlegende benutzerdefinierte Skripts.

Beim Online-Lesen scheinen viele Leute dies mit dem Symlink-Ansatz zu tun: Klonen Sie in ein Unterverzeichnis und erstellen Sie dann Symlinks aus $HOMEdem Repository. Nachdem ich $HOMEüber ein Jahrzehnt lang unter voller Versionskontrolle war, mag ich die Idee dieses Ansatzes nicht und ich kann nicht herausfinden, warum die Leute der direkten Checkout-Methode so abgeneigt erscheinen. Gibt es Fallstricke, die ich gitals Top-Level-Checkout kennen muss $HOME?

PS: Zum Teil als Übung für gutes Coding plane ich auch, meinen Root-Checkout auf Github zu veröffentlichen. Es ist beängstigend, wie viele sicherheitsrelevante Informationen ich in Dateien sammeln darf, die ohne weiteres gemeinsam genutzt werden können! WiFi-Passwort, nicht passphrasierte RSA-Schlüssel usw. Eeek!

Caleb
quelle
5
Neugierig, was zu der Annahme geführt hat, dass $ HOME ohne weiteres gemeinsam genutzt werden kann. Sogar verschlüsselte private RSA-Schlüssel sollten nicht weitergegeben werden.
Derobert
3
Wenn Sie tatsächlich über das Einfügen des Inhalts Ihres Home-Verzeichnisses in git sprechen, beachten Sie Folgendes: Es ist schwierig (aber nicht unmöglich), den Verlauf von git zu durchsuchen und sensible Elemente dauerhaft sorgfältig zu entfernen (git soll helfen, den Verlust von Dingen zu verhindern) Denken Sie auch daran, dass beim gitWechseln von Zweigen oder beim Auschecken eine frühere Revision die Berechtigungen Ihrer Dateien auf 644nach dem Auschecken ändert, was für Dinge wie private SSH-Schlüssel schlecht ist. Es ist jedoch etckeepereine Lösung für die Verwendung von Git mit Berechtigungen für / etc /
cwd
@derobert: Das weiß ich sehr gut. Ich habe nicht darüber gesprochen, $ HOME öffentlich zu machen, sondern nur Dotfiles und Convenience-Skripte. Dort habe ich Dinge gefunden, die nicht dazugehören. Und ja, ich sollte in der Lage sein, meine und ähnliche Dinge zu teilen .zshrc, .vimrcohne sie zuerst desinfizieren zu müssen!
Caleb
4
Wenn Sie es nicht gesehen haben, sehen Sie sich das Wiki und die Mailinglisten von vcs-home an , in denen genau dies besprochen wird - wie Sie Ihr $ HOME unter Versionskontrolle halten.
Jim Paris
Ich weiß nicht, wie sehr Sie das Verhalten von git ändern können, aber zumindest, wie es außerhalb des Debian-Repositorys funktioniert, ist es ziemlich gierig, wenn es um die Suche nach verfolgten / nicht verfolgten / geänderten Dateien und automatisch geht fühlt sich für jede Datei verantwortlich. mrb hat das schon gesagt. Manchmal ärgere ich mich über dieses gierige Verhalten, selbst in relativ kleinen Projekten, die ich nicht in meinem Home-Verzeichnis haben möchte. Warum willst du Git benutzen? Ich verwende auch ein Versionsverwaltungssystem, um meine Konfigurationsdateien über Hosts hinweg zu synchronisieren, und ich bin mit CVS sehr zufrieden, weil es so einfach ist! Dafür ist Git (auch!) Sehr mächtig
Bananguin

Antworten:

17

Ja , es gibt mindestens eine große Gefahr, wenn Sie überlegen git, ein Basisverzeichnis zu verwalten, mit dem Sie sich nicht befassen subversion.

Git ist standardmäßig sowohl gierig als auch rekursiv .

Subversion ignoriert naiv alles, was es nicht kennt, und stoppt die Verarbeitung von Ordnern nach oben oder unten von Ihrem Checkout aus, wenn es einen Ordner erreicht, von dem es nichts weiß (oder der zu einem anderen Repository gehört). Auf der anderen Seite kehrt Git immer wieder in alle untergeordneten Verzeichnisse zurück, wodurch verschachtelte Auscheckvorgänge aufgrund von Namespace-Problemen sehr kompliziert werden. Da Ihr Home-Verzeichnis wahrscheinlich auch der Ort ist, an dem Sie verschiedene andere Git-Repositorys auschecken und bearbeiten, wird ein Home-Verzeichnis in Git mit ziemlicher Sicherheit Ihr Leben zu einem unmöglichen Chaos machen.

Wie sich herausstellt, ist dies der Hauptgrund, warum Leute ihre Punktedateien in einen isolierten Ordner auschecken und dann einen Symlink dazu erstellen. Es hält git aus dem Weg, wenn Sie etwas anderes in einem untergeordneten Verzeichnis von Ihrem tun $HOME. Während dies nur eine Frage der Präferenz ist, wenn Sie Ihr Zuhause in Subversion einchecken, wird es eine Frage der Notwendigkeit, wenn Sie Git verwenden.

Es gibt jedoch eine alternative Lösung. Git erlaubt so etwas wie ein "Fake Root", bei dem alle Repository-Maschinen in einem alternativen Ordner versteckt sind, der physisch vom Arbeitsverzeichnis für das Auschecken getrennt werden kann. Das Ergebnis ist, dass das Git-Toolkit nicht verwirrt wird: Es wird nicht einmal Ihr Repository sehen, sondern nur die Arbeitskopie. Durch Setzen einiger Umgebungsvariablen können Sie git mitteilen, wo sich die Waren für die Momente befinden, in denen Sie Ihr Home-Verzeichnis verwalten. Ohne die Umgebungsvariablen ist niemand weiser und Ihr Zuhause sieht aus wie ein klassisches Dateiselbst.

Um diesen Trick flüssiger zu gestalten, gibt es einige großartige Tools. Die vcs-home-Mailingliste scheint der Ausgangspunkt zu sein, und die About-Seite bietet eine praktische Zusammenfassung der Anleitungen und Erfahrungen der Benutzer. Auf dem Weg dorthin sind einige raffinierte kleine Werkzeuge wie vcsh , mr . Wenn Sie Ihr Home-Verzeichnis direkt in Git halten möchten, ist vcsh fast ein Muss. Wenn Sie Ihr Home-Verzeichnis hinter den Kulissen in mehrere Repostories aufteilen, kombinieren Sie es vcshmit, mrum eine schnelle und nicht sehr schmutzige Möglichkeit zu haben, alles auf einmal zu verwalten.

Caleb
quelle
2
aber warum nicht einfach '*' zu deiner .gitignore-Datei hinzufügen? Auf diese Weise ignoriert git alles außer den Dateien, die sich bereits im Repository befinden, und Sie können mit neue Dateien hinzufügen git add -f <file>.
ALiX
@ALiX: Weil die gitTools immer noch davon ausgehen würden, dass Sie an Ihrem Home-Verzeichnis-Repo arbeiten, selbst wenn Sie sich in einem Unterverzeichnis befänden, das für ein bestimmtes Projekt ein separates Git-Repo war. Diese Lösung würde Ihr gesamtes Home-Verzeichnis für alle anderen Git-Arbeiten unzugänglich machen.
Caleb
5
Ein '*' in Ihrem .gitignore bedeutet jedoch, dass alle Dateien, die sich nicht in Ihrem Home-Verzeichnis befinden, ignoriert werden. und wenn Sie ein neues Git-Repo in einem Unterverzeichnis auschecken, sollte immer noch alles wie erwartet funktionieren (glaube ich). Soweit mir bekannt ist, suchen die Git-Tools nach dem ersten Git-Verzeichnis, während sie die Verzeichnishierarchie nach oben verschieben. Wenn Sie also im Unterverzeichnis arbeiten, wird das richtige Git-Repository verwendet. Wenn Sie die Umgebungsvariablen von git verwenden, kann es natürlich zu Problemen kommen. Aber sonst verstehe ich nicht, warum das nicht funktionieren würde.
ALiX
@ALiX ist richtig. Geschachtelte Git-Repos scheinen gut zu funktionieren, solange Sie sie im übergeordneten Repo ablegen. Ich frage mich, was die Nachteile dieses sehr einfachen Ansatzes sind, abgesehen von möglichen Problemen mit den Umgebungsvariablen von git.
Evanrmurphy
1
Hab heute damit experimentiert. Ich denke, /*funktioniert besser als, *weil es immer noch alles standardmäßig ignoriert, aber es viel einfacher macht, Verzeichnisse hinzuzufügen. Stattdessen verwende git add -fich !vorab festgelegte Muster wie !/.vimrcund !/.gitignore(für die .gitignore-Datei selbst), um Dinge explizit in das Repo aufzunehmen.
Evanrmurphy
14

Ich möchte nicht, dass mein gesamtes Ausgangsverzeichnis in die Versionskontrolle eingecheckt wird, nur weil jedes Unterverzeichnis, in das ich gehe, den Versionskontrollkontext meines Ausgangsverzeichnisses enthält. Befehle wie git checkouthaben in diesem Fall eine tatsächliche Aktion, die Probleme verursacht, wenn ich versehentlich etwas aus dem falschen Verzeichnis starte, sei es das, was sich gitselbst befindet, oder ein Skript, das git aufruft.

Es macht es auch wahrscheinlicher, dem Repo etwas hinzuzufügen, das Sie nicht möchten, was kein Problem gewesen wäre, wenn Sie alles eingecheckt hätten, aber jetzt zu einem Problem wird. Was ist, wenn Sie versehentlich eine private Schlüsseldatei hinzufügen (möglicherweise aus Gewohnheit) und diese an github senden?

Trotzdem denke ich, dass die Hauptnachteile nicht wirklich technisch sind - ich möchte mich nur vor mir selbst retten.

Was Symlinks betrifft: Sie können Ihr Repo in ein Unterverzeichnis klonen und über ein Skript verfügen, das alle zu aktualisierenden Symlinks aktualisiert. Der für dieses Skript erforderliche Wartungsaufwand kann jedoch die Vorteile eines solchen Skripts aufwiegen. symlinking könnte sich als weniger arbeit herausstellen.

Mit Symlinks können Sie auch problemlos distro-spezifische (oder sogar host-spezifische) Ergänzungen vornehmen, die in Git eingecheckt werden. Ihr Symlink-Update-Skript ignoriert Dateien, die für inkompatible Plattformen oder andere Hosts bestimmt sind, und aktualisiert nur die entsprechenden.

So etwas wie:

HOMEREPO=$HOME/homerepo
HOST=$(hostname)
UNAME=$(uname)

for dotfile in $HOMEREPO/shared/* $HOMEREPO/host-$HOST/* $HOMEREPO/uname-$UNAME/*
do
    target=$HOME/$(basename $dotfile)
    [ ! -r $target ] && ln -s $dotfile $target
done

Persönlich: Ich verwende Symlinks und verknüpfe keine Verzeichnisse. nur die Dateien innerhalb. Dies gibt mir die Flexibilität, in diesen Verzeichnissen standortlokale Änderungen vorzunehmen (dh Dateien hinzuzufügen / zu entfernen). Das Einrichten meines Kontos auf einem neuen System ist mühsam, da ich alle Symlinks von Hand neu erstellen muss.

mrb
quelle
Alle gitBefehle, die ich ausführe, gelten entweder für das Basisverzeichnis selbst oder sind mindestens einmal tief in einem nicht festgeschriebenen Verzeichnis vergraben. Die Verwendung svndieser einen Ordnerisolation ist sehr effektiv und hat mir seit einem Jahrzehnt keine Probleme mehr bereitet. Ihr erster Absatz weist auf etwas anderes hin. Ist dies tatsächlich ein Unterschied in der Funktionsweise git?
Caleb
Außerdem sind in meinen Konfigurationen und Skripten bereits Bedingungslogiken für verschiedene Hosts und Plattformen integriert. Die Verwendung eines Skripts zum Einrichten verschiedener Verknüpfungen als Bedingung scheint daher kein großer Vorteil für das giteinfache Verwalten von Zweigen zu sein. Ich vermisse immer noch etwas oder kommt das auf den Punkt?
Caleb
3
Die Ein-Ordner-Isolation isoliert nicht wirklich git- nicht sicher svn-, aber ein Beispiel git init foo && mkdir -p foo/bar/baz/spam && cd foo/bar/baz/spam && git status(oder andere Git-Befehle) zeigt, dass Sie sich immer noch im fooVersionskontrollkontext befinden.
Mrb
Configs & Scripts: Nicht alle Dotfiles unterstützen Bedingungen, weshalb ich den alternativen Ansatz vorgeschlagen habe. Dies sind alles Gründe, für die die Leute die Versionskontrolle nicht bevorzugen $HOME- und die Versionierung ist für dotfiles imo nicht wirklich wertvoll -, aber letztendlich ist es Ihr Home-Verzeichnis. Wenn Sie also Git bevorzugen und dies keine Probleme für Sie sind, Tue es!
mrb
Danke für die Information. Eigentlich ist Ihr Kommentar zu Git, der keine Isolation zulässt, das nützlichste Bit. Sie könnten das prominent in Ihre Antwort einarbeiten. Subversion verhält sich in diesem Punkt sehr unterschiedlich und ist für diesen Anwendungsfall von Bedeutung.
Caleb
6

Um eine andere Sichtweise zu geben: Ich habe mein $ HOME seit einiger Zeit unter git und habe keine Nachteile festgestellt. Ich synchronisiere dieses Git-Repo offensichtlich nicht mit Github. Ich benutze einen Service, der private Repos hat. Ich stelle auch keine Mediendateien, Downloads oder Pakete unter Git-Kontrolle.

  • git status ist eine Art Checkliste "zu tun, zu reinigen".

  • Ich habe eine ~/tmpfür temporäre Dinge, die gitignored ist.

  • Ich möchte in allem sehen git status, dass eine kürzlich installierte Software es wagt, zu meinem $ HOME hinzuzufügen und diese Dateien häufig zu löschen oder sogar die Schuldigen zu deinstallieren.

  • Ich füge manuell die wirklich nützlichen lokalen Dateien und Verzeichnisse hinzu .gitignore, die einen "Wissen, was Sie bei der Installation tun" -Nutzen haben .

  • Wenn ich eine neue VM baue oder einen neuen PC installiere, klone ich einfach mein Remote-Home nach $ HOME und habe sofort alles unter der Hand, was ich brauche.

  • Dinge wie vundle für vim Plugins sind nicht mehr nötig.

Ich mag Komplexität nicht. Wenn ich ein rcfile optimiere, mache ich es einfach, setze fest und drücke. Dann, als Reflex, ziehe ich jeden zweiten Tag $ HOME ein und habe immer die aktuellste Konfiguration. So einfach ist das.

Derzeit unter diesem Regime stehende Computer: Heim-Laptop, Arbeits-PC, Arbeits-VM sowie 3 oder 4 Remote-Server.

gb.
quelle
Haben Sie noch andere GIT-Kassen in Ihrem Haus?
Caleb
Nein, ich lege andere Dinge in ein / work-Verzeichnis und klone keine kleinen Tools wie vim pugins.
gb.
1
Ich habe Arbeit in einer ~ / Sites und mache diesen Ansatz auch, es gibt kein Problem mit verschachtelten Git Repos
Philfreo
1
Ich benutze dieses Setup für eine Weile. Ich habe einen Alias ​​sq = git status -uno und kümmere mich nicht viel um .gitignore (ab und zu schaue ich mir die ganze Kruft an und sage dann "meh"). Ich hatte noch nie Probleme mit verschachtelten Git-Repos. Ich habe einen privaten Server, auf dem ich einen git init --barePush-Vorgang über ssh ausgeführt habe (obwohl ich keine Passwörter in das Repo geschrieben habe, habe ich meine Notizen-Dateien dort).
Unhammer
5

Ich habe beide ausprobiert und am Ende den Symlink-Ansatz bevorzugt :

  • Überprüfen Sie, wohin auch immer
  • make install
  • Melden Sie sich ab und wieder an, um die X-Einstellungen zu laden

Nachteile:

  • Müssen Sie Dateien in das Repo verschieben, bevor Sie sie hinzufügen
  • Müssen die Liste der symbolischen Links im Makefile pflegen

Vorteile:

  • Keine Notwendigkeit für eine massive .gitignore(Ich habe 133 Dotfiles in ~meiner bescheidenen Ubuntu-Box)
  • Kann Wartungsskripte und andere ~Dinge (wie Makefileund cleanup.sh) aus dem Weg räumen
  • Kann die Versionskontrolle für persönliche und öffentliche Einstellungen separat durchführen

Beschränkungen:

  • Im Gegensatz zu @mrb erstelle ich nur Symlinks in ~. Das vereinfacht die Verknüpfung und macht es trivial, neue Dateien beispielsweise ~/.vimauf Kosten einer sehr seltenen .gitignoreWartung zu bemerken .

Die letzten beiden Vorteile waren für mich ausschlaggebend: Ich möchte das Home-Verzeichnis nicht überladen und den privaten und den öffentlichen Inhalt klar voneinander trennen.

Die einzige mir bekannte Anwendung, die Probleme mit der Behandlung von Symlinks hat (oder zumindest hatte), war Pidgin - Es überschrieb meine Symlinks immer wieder mit normalen Dateien.

l0b0
quelle
Vielen Dank für Ihren Beitrag zu den Vor- und Nachteilen jedes Ansatzes. In meinem Follow-up habe ich festgestellt, dass es einen dritten Ansatz gibt , der das Beste aus beiden Welten machen könnte, wenn Sie die zusätzliche Verkabelung einrichten , um loszulegen.
Caleb
3

Hier ist eine: Wenn Sie dies versuchen git rebase -i --rootund .gitconfigdas erste Commit im Repository eingecheckt haben , wird die .gitconfigDatei von git vorübergehend entfernt , was wiederum dazu führt, dass der Rebase-Vorgang nicht abgeschlossen werden kann, da Ihr Name und Ihre E-Mail-Adresse erforderlich sind das, was in dieser Datei gespeichert sind.

Sie können sie erneut konfigurieren und dies tun git rebase --continue, aber nachdem ich das getan und den Rebase-Vorgang abgeschlossen habe, hat mein Git-Repository vor dem Commit, das zuvor das erste Commit im Repository war, ein leeres Commit ohne eine Commit-Nachricht erhalten, das ich nicht kenne wie man los wird.

Ich weiß nicht, was passiert, wenn Sie git rebase -i <commit>stattdessen tun , und .gitconfigwird zusammen mit einem Commit nach eingecheckt <commit>.

Vielleicht ist es die einfachste Lösung .gitconfig, das Repository nicht hinzuzufügen und stattdessen in aufzulisten .gitignore.

Hallo Auf Wiedersehen
quelle
2

So mache ich es:

  1. Installiere ein sauberes Linux (nicht notwendig, aber macht das Leben in Schritt 4 angenehmer)
  2. Installieren Sie etckeeper
  3. renn git initin dein Zuhause
  4. erstelle .gitignore und füge alles hinzu, was dich anscheinend nicht interessiert oder was sich sehr ändern könnte. Achten Sie darauf, fügen Sie Dinge wie *.cache, *.lockusw. Ich weiß nicht empfehlen das Hinzufügen/*weil Sie nicht automatisch benachrichtigt werden, wenn Ihrem Zuhause etwas Neues hinzugefügt wird. Es ist ein Blacklist-Ansatz im Vergleich zu einem Whitelist-Ansatz, bei dem ich meine Konfiguration für alle Software-Komponenten beibehalten möchte, außer für flüchtige Komponenten und einige Software-Komponenten, die mir egal sind. Wenn Sie später Systeme zusammenführen, migrieren oder vergleichen, ist es sehr praktisch, alles unterscheiden zu können. Sie können Ihre neuen Systeme viel schneller einrichten, als wenn Sie nur .bashrc und einige andere Punktedateien gespeichert hätten. Auf diese Weise behalten Sie die Konfiguration bei, die Sie andernfalls über die GUI festgelegt haben, und wissen nicht, in welchen Dotfiles die Einstellungen gespeichert sind. (Wenn sich jemals herausstellt, dass Sie flüchtige Dateien festgeschrieben haben, können Sie git trotzdem anweisen, davon auszugehen, dass sie unverändert sind.)
  5. Lauf etckeeper init -d /home/username
  6. Lauf git commit -d /home/username
  7. Richten Sie Aliase in Ihrer Shell ein, um die Befehlszeile zu optimieren homekeeper checkout

Der Grund für die Verwendung von etckeeper ist, dass Metadaten wie Berechtigungen für Ihre Dateien gespeichert werden (ziemlich wichtig für bestimmte Dinge wie SSH-Schlüssel). Sie sollten jetzt einen Pre-Commit-Hook haben, der Metadaten automatisch speichert. Ich bin mir nicht so sicher, ob ich nach dem Auschecken komme. Sie sollten wahrscheinlich verwenden, etckeeper checkout xxx -d /home/userich werde es etwas genauer untersuchen und diese Antwort ausarbeiten.


quelle
-1

Mein Hauptproblem bei der Verwendung von Git im Ausgangsverzeichnis ist, dass Git keine Dateiattribute wie Dateiberechtigungen und Zeitstempel speichert. Für mich ist es wichtig zu wissen, wann bestimmte Dateien erstellt wurden. Dies kann bei Ihnen der Fall sein oder nicht. Darüber hinaus .sshist es problematisch , Berechtigungen für Dateien und Verzeichnisse wie zu verlieren . Ich verstehe, dass Sie vorhaben, .sshsich von Git fernzuhalten, aber es wird andere Stellen geben, an denen Berechtigungen eine Rolle spielen könnten (z. B. nicht komprimierte Website-Backups).

dotancohen
quelle
Dies ist irreführend, wenn nicht sachlich falsch. Git behält standardmäßig viele Dateiattribute bei, einschließlich Berechtigungen. Ich bin .sshjetzt seit einiger Zeit ohne ein Problem in Git, richtige sichere Berechtigungen bleiben erhalten. In der Basiskonfiguration werden weder Besitzrechte noch Zeitstempel beibehalten. Wenn dies jedoch ein Problem für einen bestimmten Anwendungsfall ist, gibt es Plugins, mit denen die Verarbeitung dieser zusätzlichen Eigenschaften Teil des regulären Workflows ist (siehe Metastore oder Git-Cache-Meta).
Caleb
Auch wenn es sie nicht speichert, wie ist das schlimmer, als nur ein Home-Verzeichnis zu haben, das nicht in vcs ist? git überschreibt mtimes nur dann aktiv, wenn Sie eine Datei ändern möchten.
Poolie
-1

Eine git-basierte Lösung ist besonders nützlich, wenn Sie Ihre Dateien auf verschiedenen Computern bereitstellen müssen, und vor allem, wenn Sie Teile haben, die für alle Computer gelten, und Teile, die für einige Computer spezifisch sind. Sie können mehrere Repositorys erstellen und mit einem Tool wie multigit oder vcsh über dasselbe Verzeichnis (in diesem Fall Ihr Ausgangsverzeichnis) klonen.

capr
quelle
Danke, aber vielleicht haben Sie die Frage verpasst. Ich bin mir der Verwendungszwecke bewusst (daher wollte ich das eigentlich machen), diese Frage bezog sich auf Fallstricke, die jemand, der dies mit git noch nicht gemacht hat (so wie ich es damals tat), möglicherweise nicht kannte . Dies scheint diese Frage überhaupt nicht zu beantworten.
Caleb