Wie organisieren Sie mehrere Git-Repositorys, sodass alle zusammen gesichert werden?

98

Mit SVN hatte ich ein einziges großes Repository, das ich auf einem Server aufbewahrte und auf einigen Computern auscheckte. Dies war ein ziemlich gutes Backup-System, mit dem ich problemlos an allen Maschinen arbeiten konnte. Ich könnte ein bestimmtes Projekt auschecken, ein Commit durchführen und das 'Master'-Projekt aktualisieren, oder ich könnte das Ganze auschecken.

Jetzt habe ich eine Reihe von Git-Repositories für verschiedene Projekte, von denen sich einige auf Github befinden. Ich habe auch das erwähnte SVN-Repository, das über den Befehl git-svn importiert wurde.

Grundsätzlich mag ich es, meinen gesamten Code (nicht nur Projekte, sondern auch zufällige Schnipsel und Skripte, einige Dinge wie meinen Lebenslauf, Artikel, die ich geschrieben habe, Websites, die ich erstellt habe usw.) in einem großen Repository zu haben, das ich einfach auf Remote klonen kann Maschinen oder Memory Sticks / Festplatten als Backup.

Das Problem ist, da es sich um ein privates Repository handelt und git das Auschecken aus einem bestimmten Ordner nicht zulässt (den ich als separates Projekt an github senden könnte, die Änderungen jedoch sowohl im Master-Repo als auch im Sub-Repo angezeigt werden) repos)

Ich könnte das Git-Submodul-System verwenden, aber es funktioniert nicht so, wie ich es möchte (Submodule sind Zeiger auf andere Repositorys und enthalten nicht wirklich den eigentlichen Code, daher ist es für die Sicherung nutzlos).

Derzeit habe ich einen Ordner mit Git-Repos (z. B. ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /). Nachdem ich Änderungen an proj1 vorgenommen habe, kopiere ich git push githubdie Dateien in ~ / Dokumente / code / python / projects / proj1 / und führen Sie ein einzelnes Commit durch (anstelle der zahlreichen in den einzelnen Repos). Dann tun git push backupdrive1, git push mymemorysticketc

Die Frage lautet also: Wie können Sie Ihren persönlichen Code und Ihre Projekte mit Git-Repositorys synchronisieren und sichern?

dbr
quelle

Antworten:

74

Ich würde dringend davon abraten, nicht verwandte Daten in ein bestimmtes Git-Repository zu stellen. Der Aufwand für das Erstellen neuer Repositorys ist recht gering, und dies ist eine Funktion , die es ermöglicht, verschiedene Linien vollständig getrennt zu halten.

Um diese Idee zu bekämpfen, muss die Geschichte unnötig durcheinander geraten, was die Verwaltung erschwert und - was noch wichtiger ist - "archäologische" Werkzeuge aufgrund der daraus resultierenden Verwässerung weniger nützlich macht. Wie Sie bereits erwähnt haben, geht Git davon aus, dass die "Einheit des Klonens" das Repository ist, und muss dies aufgrund seiner verteilten Natur praktisch tun.

Eine Lösung besteht darin, jedes Projekt / Paket / etc. Zu behalten. als eigenes nacktes Repository (dh ohne Arbeitsbaum) unter einer gesegneten Hierarchie, wie:

/repos/a.git
/repos/b.git
/repos/c.git

Sobald einige Konventionen festgelegt wurden, ist es trivial, Verwaltungsvorgänge (Backup, Packing, Web Publishing) auf die gesamte Hierarchie anzuwenden, die eine Rolle spielt, die "monolithischen" SVN-Repositorys nicht völlig unähnlich ist. Die Arbeit mit diesen Repositories auch SVN - Workflows etwas ähnlich wird, mit dem Zusatz , dass man kann lokale Commits und Zweige verwenden:

svn checkout   --> git clone
svn update     --> git pull
svn commit     --> git push

In jedem Arbeitsklon können mehrere Fernbedienungen vorhanden sein, um die Synchronisierung zwischen mehreren Parteien zu vereinfachen:

$ cd ~/dev
$ git clone /repos/foo.git       # or the one from github, ...
$ cd foo
$ git remote add github ...
$ git remote add memorystick ...

Sie können dann von jeder der "Quellen" abrufen / ziehen, lokal arbeiten und festschreiben und dann auf jede dieser Fernbedienungen drücken ("sichern"), wenn Sie mit etwas wie fertig sind (beachten Sie, wie dies die gleichen Festschreibungen und den gleichen Verlauf überträgt) jede der Fernbedienungen!):

$ for remote in origin github memorystick; do git push $remote; done

Der einfachste Weg, ein vorhandenes funktionierendes Repository ~/dev/foo in ein solches nacktes Repository umzuwandeln, ist wahrscheinlich:

$ cd ~/dev
$ git clone --bare foo /repos/foo.git
$ mv foo foo.old
$ git clone /repos/foo.git

Das ist meistens gleichbedeutend mit einem svn import- aber wirft die bestehende "lokale" Geschichte nicht weg.

Hinweis: Submodule sind ein Mechanismus, um gemeinsam genutzte verwandte Linien einzuschließen. Daher würde ich sie in der Tat nicht als geeignetes Werkzeug für das Problem betrachten, das Sie lösen möchten.

Damien Diederen
quelle
18
Die Tatsache, dass ich immer wieder viele separate Repositorys habe und einfache Skripte schreibe, um sie alle zu verwalten, gibt mir das Gefühl, dass etwas in Git fehlt. Ich kann mich einfach nicht genau entscheiden, was es ist oder was ich dagegen tun soll.
DonGar
Verwalten Sie auch viele separate Projekte? Eine Eins-zu-Eins-Beziehung zwischen Projekten und Repositorys fühlt sich in einer verteilten Welt vernünftig an, aber ich würde dennoch nackte Repositorys in einem gemeinsamen Verzeichnisbaum anordnen, um das Sichern und Verwalten zu vereinfachen. (Mit anderen Worten, Git / Hg / Bzr zwingt Sie, die Verwaltung von den Projektaufgaben zu trennen, während die meisten SVN-Workflows die beiden zusammenführen. Es ist heutzutage üblich, dass Personen den administrativen Teil an GitHub oder andere solche Anbieter delegieren.)
Damien Diederen
2
Diese Idee ist nur sinnvoll, wenn Sie Ihre eigenen Projekte hosten und / oder alle Open Source sind. Andernfalls würden Sie auf Github unbegrenzte private Projekte benötigen, die teuer werden könnten
Dkinzer
2
Anstelle von "für Remote-Github-Memorystick; do git push $ remote; done" kann auch eine spezielle Fernbedienung konfiguriert werden, die mit einem einzigen Befehl an viele Fernbedienungen gesendet werden kann : stackoverflow.com/questions/36862/… . (
Könnte
2
Ich denke, das Fehlende ist eine Möglichkeit, mit der Git seine Objekte nach Teilbäumen getrennt halten kann, sodass ein einzelnes "Repository" aus separaten synchronisierten, aber trennbaren Einheiten (einzeln ohne den Rest heruntergeladen) bestehen kann, so dass die Leute an bestimmten arbeiten können Teilmengen, ohne über den Rest Bescheid zu wissen.
Peterk
28

Ich möchte Damiens Antwort hinzufügen, wo er empfiehlt:

$ for remote in origin github memorystick; do git push $remote; done

Sie können eine spezielle Fernbedienung einrichten, um mit einem Befehl auf alle einzelnen realen Fernbedienungen zuzugreifen. Ich fand es unter http://marc.info/?l=git&m=116231242118202&w=2 :

Für "git push" (wo es sinnvoll ist, dieselben Zweige mehrmals zu pushen) können Sie also tatsächlich das tun, was ich tue:

  • .git / config enthält:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • und jetzt git push all masterwird der "Master" -Zweig zu diesen beiden
    Remote-Repositorys verschoben.

Sie können sich auch sparen, indem Sie die URLs zweimal eingeben, indem Sie die folgende Konstruktion verwenden:

[url "<actual url base>"]
    insteadOf = <other url base>
imz - Ivan Zakharyaschev
quelle
3

Ich bin auch neugierig auf vorgeschlagene Möglichkeiten, um damit umzugehen, und werde das aktuelle Setup beschreiben, das ich verwende (mit SVN). Ich habe im Grunde ein Repository erstellt, das eine Mini-Dateisystemhierarchie enthält, einschließlich eigener bin- und lib-Verzeichnisse. Im Stammverzeichnis dieses Baums befindet sich ein Skript, mit dem Ihre Umgebung so eingerichtet wird, dass diese bin, lib usw. andere Verzeichnisse zu den richtigen Umgebungsvariablen hinzugefügt werden. Das Stammverzeichnis sieht also im Wesentlichen so aus:

./bin/            # prepended to $PATH
./lib/            # prepended to $LD_LIBRARY_PATH
./lib/python/     # prepended to $PYTHONPATH
./setup_env.bash  # sets up the environment

In / bin und / lib befinden sich nun mehrere Projekte und die entsprechenden Bibliotheken. Ich weiß, dass dies kein Standardprojekt ist, aber es ist für andere in meiner Gruppe sehr einfach, das Repo auszuchecken, das Skript 'setup_env.bash' auszuführen und die aktuellsten Versionen aller Projekte lokal in ihrem zu haben Auschecken. Sie müssen sich nicht um die Installation / Aktualisierung von / usr / bin oder / usr / lib kümmern, und es ist einfach, mehrere Checkout-Vorgänge und eine sehr lokalisierte Umgebung pro Checkout durchzuführen. Jemand kann auch nur das gesamte Repository verwalten und sich keine Gedanken über die Deinstallation von Programmen machen.

Das funktioniert gut für uns und ich bin mir nicht sicher, ob wir es ändern werden. Das Problem dabei ist, dass sich in diesem einen großen Repository viele Projekte befinden. Gibt es eine git / Hg / bzr-Standardmethode, um eine solche Umgebung zu erstellen und die Projekte in ihre eigenen Repositories aufzuteilen?

Danny G.
quelle
3

Ich habe noch nicht versucht, Git-Repositorys zu verschachteln, weil ich nicht in eine Situation geraten bin, in der ich muss. Wie ich auf dem # Git- Kanal gelesen habe, scheint Git durch das Verschachteln der Repositorys verwirrt zu werden, dh Sie versuchen, Git-Init in einem Git-Repository zu erstellen. Die einzige Möglichkeit, eine verschachtelte Git-Struktur zu verwalten, besteht darin, git-submoduledas repoDienstprogramm von Android zu verwenden .

Was die Sicherungsverantwortung betrifft, die Sie beschreiben, sage ich, delegieren Sie sie ... Für mich stelle ich normalerweise das "Ursprungs" -Repository für jedes Projekt auf einem Netzwerklaufwerk in Betrieb, das regelmäßig von den IT-Technikern durch ihre Sicherungsstrategie von gesichert wird Wahl. Es ist einfach und ich muss mir keine Sorgen machen. ;)

Spoike
quelle
2

Was ist mit mr für die gleichzeitige Verwaltung mehrerer Git-Repos:

Der Befehl mr (1) kann eine Reihe von Repositorys auschecken, aktualisieren oder andere Aktionen ausführen, als wären sie ein kombiniertes Repository. Es unterstützt jede Kombination von Subversion-, Git-, CVS-, Mercurial-, BZR-, Darcs-, CVS-, VCSH-, Fossil- und Wahrhaftigkeits-Repositorys, und die Unterstützung für andere Revisionskontrollsysteme kann problemlos hinzugefügt werden. [...]

Es ist extrem einfach über einfaches Shell-Scripting konfigurierbar. Einige Beispiele für Dinge, die es tun kann, sind:

[...]

  • Ziehen Sie beim Aktualisieren eines Git-Repositorys aus zwei verschiedenen Upstreams und führen Sie die beiden zusammen.
  • Führen Sie mehrere Repository-Updates parallel aus, wodurch der Update-Prozess erheblich beschleunigt wird.
  • Erinnern Sie sich an Aktionen, die fehlgeschlagen sind, weil ein Laptop offline ist, damit sie wiederholt werden können, wenn er wieder online ist.
imz - Ivan Zakharyaschev
quelle
1

Es gibt eine andere Methode, um verschachtelte Git-Repos zu haben, aber sie löst nicht das Problem, nach dem Sie suchen. Für andere, die nach einer Lösung suchen, war ich dennoch:

Im Git-Repo der obersten Ebene verstecken Sie einfach den Ordner in .gitignore, der das verschachtelte Git-Repo enthält. Dies macht es einfach, zwei separate (aber verschachtelte!) Git-Repos zu haben.

arxpoetica
quelle