Jak zorganizować wiele repozytoriów git, aby wszystkie z nich były archiwizowane razem?

98

Dzięki SVN miałem jedno duże repozytorium, które trzymałem na serwerze i wyewidencjonowałem na kilku maszynach. To był całkiem niezły system tworzenia kopii zapasowych i pozwolił mi z łatwością pracować na dowolnej maszynie. Mógłbym pobrać konkretny projekt, zatwierdzić i zaktualizować projekt „główny” lub pobrać całą rzecz.

Teraz mam kilka repozytoriów git dla różnych projektów, z których kilka jest na githubie. Mam też repozytorium SVN, o którym wspomniałem, zaimportowane za pomocą polecenia git-svn.

Zasadniczo lubię mieć cały mój kod (nie tylko projekty, ale losowe fragmenty i skrypty, niektóre rzeczy, takie jak moje CV, artykuły, które napisałem, strony internetowe, które stworzyłem i tak dalej) w jednym dużym repozytorium, które mogę łatwo sklonować na zdalnym maszyny lub pendrive / dyski twarde jako kopia zapasowa.

Problem polega na tym, że jest to prywatne repozytorium, a git nie pozwala na wyewidencjonowanie określonego folderu (który mógłbym przesłać do github jako oddzielny projekt, ale zmiany pojawiają się zarówno w głównym repozytorium, jak i podrzędnym repozytoria)

I mógł korzystać z systemu git submodule, ale to nie działa jak chcę go zbyt (Submoduły są wskaźnikami do innych repozytoriów, a tak naprawdę nie zawierają rzeczywisty kod, więc jest bezużyteczny do tworzenia kopii zapasowych)

Obecnie mam folder git-repos (na przykład ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /) i po wprowadzeniu zmian w proj1 robię git push github, a następnie kopiuję pliki do ~ / Dokumenty / kod / python / projekty / proj1 / i wykonaj pojedyncze zatwierdzenie (zamiast wielu w poszczególnych repozytoriach). Następnie zrobić git push backupdrive1, git push mymemorysticketc

A więc pytanie: w jaki sposób Twój osobisty kod i projekty z repozytoriami git oraz utrzymywanie ich synchronizacji i tworzenia kopii zapasowych?

dbr
źródło

Odpowiedzi:

74

Chciałbym zdecydowanie odradzam wprowadzenie niepowiązanych danych w danym repozytorium Git. Narzut związany z tworzeniem nowych repozytoriów jest dość niski i jest to funkcja, która umożliwia całkowicie oddzielenie różnych linii.

Walka z tym pomysłem oznacza koniec z niepotrzebnie splątaną historią, co utrudnia administrację i - co ważniejsze - narzędzia „archeologiczne” mniej przydatne z powodu wynikającego z tego rozmycia. Ponadto, jak wspomniałeś, Git zakłada, że ​​„jednostką klonowania” jest repozytorium i praktycznie musi to robić ze względu na jego rozproszony charakter.

Jednym z rozwiązań jest zachowanie każdego projektu / pakietu / itp. jako własnej gołej repozytorium (czyli bez drzewa pracy) pod błogosławionej hierarchii, takich jak:

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

Po ustaleniu kilku konwencji trywialne staje się stosowanie operacji administracyjnych (tworzenie kopii zapasowych, pakowanie, publikowanie w sieci WWW) do pełnej hierarchii, która pełni rolę podobną do „monolitycznych” repozytoriów SVN. Praca z tymi repozytoriami również przypomina nieco obiegi pracy SVN, z tym, że można używać lokalnych zatwierdzeń i gałęzi:

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

Możesz mieć wiele pilotów w każdym działającym klonie, aby ułatwić synchronizację między wieloma stronami:

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

Następnie możesz pobrać / pobrać z każdego ze „źródeł”, pracować i zatwierdzać lokalnie, a następnie wypychać („kopia zapasowa”) do każdego z tych pilotów, gdy jesteś gotowy z czymś w rodzaju (zwróć uwagę, jak to wypycha te same zatwierdzenia i historię do każdy z pilotów!):

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

Najłatwiejszym sposobem przekształcenia istniejącego repozytorium roboczego ~/dev/foo w takie czyste repozytorium jest prawdopodobnie:

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

co jest przeważnie odpowiednikiem -, svn importale nie odrzuca istniejącej, „lokalnej” historii.

Uwaga: moduły podrzędne są mechanizmem włączania współdzielonych pokrewnych linii, więc rzeczywiście nie uważałbym ich za odpowiednie narzędzie do problemu, który próbujesz rozwiązać.

Damien Diederen
źródło
18
Fakt, że wciąż mam wiele oddzielnych repozytoriów i piszę proste skrypty, które pomagają zarządzać nimi wszystkimi, sprawia, że ​​czuję, że czegoś brakuje w git. Po prostu nie mogę dokładnie zdecydować, co to jest i co z tym zrobić.
DonGar
Czy zarządzasz też wieloma oddzielnymi projektami? Relacja jeden do jednego między projektami i repozytoriami wydaje się rozsądna w świecie rozproszonym, ale nadal ułożyłbym czyste repozytoria we wspólnym drzewie katalogów, aby ułatwić tworzenie kopii zapasowych i administrację. (Innymi słowy, Git / Hg / Bzr zmusza cię do oddzielenia administracji od zadań projektowych, podczas gdy większość przepływów pracy SVN łączy te dwa; teraz często zdarza się, że ludzie delegują część administracyjną do GitHub lub innych podobnych dostawców.)
Damien Diederen
2
ten pomysł ma sens tylko wtedy, gdy hostujesz własne projekty i / lub wszystkie są open source. W przeciwnym razie potrzebowałbyś nieograniczonej
liczby
2
Zamiast „for remote in origin github memorystick; do git push $ remote; done”, można również skonfigurować specjalnego pilota do wysyłania za pomocą jednego polecenia do wielu pilotów: stackoverflow.com/questions/36862/… . (W niektórych przypadkach może być wygodniej.)
imz - Ivan Zakharyaschev
2
Myślę, że brakującą rzeczą jest sposób, w jaki git może utrzymywać swoje obiekty oddzielnie przez poddrzewo, tak aby pojedyncze "repozytorium" mogło składać się z oddzielnych zsynchronizowanych, choć rozdzielnych jednostek (pobieranych pojedynczo bez reszty) w taki sposób, że ludzie mogą pracować nad określonymi podzbiory bez wiedzy o pozostałej części.
peterk
28

Chcę dodać do odpowiedzi Damiena, w której zaleca:

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

Możesz skonfigurować specjalnego pilota do wysyłania do wszystkich indywidualnych rzeczywistych pilotów za pomocą 1 polecenia; Znalazłem go pod adresem http://marc.info/?l=git&m=116231242118202&w=2 :

Więc w przypadku „git push” (gdzie sensowne jest wielokrotne wciskanie tych samych gałęzi), możesz właściwie zrobić to, co ja:

  • .git / config zawiera:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • a teraz git push all masterprzeniesie gałąź „master” do obu
    tych zdalnych repozytoriów.

Możesz także zaoszczędzić sobie przy dwukrotnym wpisywaniu adresów URL, korzystając z konstrukcji:

[url "<actual url base>"]
    insteadOf = <other url base>
imz - Ivan Zakharyaschev
źródło
3

Jestem również ciekawy sugerowanych sposobów radzenia sobie z tym i opiszę obecną konfigurację, której używam (z SVN). Zasadniczo utworzyłem repozytorium, które zawiera hierarchię mini-systemów plików, w tym własne katalogi bin i lib. W katalogu głównym tego drzewa znajduje się skrypt, który skonfiguruje twoje środowisko, aby dodać te katalogi bin, lib, etc ... inne katalogi do odpowiednich zmiennych środowiskowych. Tak więc katalog główny zasadniczo wygląda następująco:

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

Teraz wewnątrz / bin i / lib znajduje się wiele projektów i odpowiadające im biblioteki. Wiem, że to nie jest standardowy projekt, ale komuś z mojej grupy bardzo łatwo jest sprawdzić repozytorium, uruchomić skrypt „setup_env.bash” i mieć najbardziej aktualne wersje wszystkich projektów lokalnie w swoim sprawdzić. Nie muszą martwić się instalacją / aktualizacją / usr / bin lub / usr / lib, a dzięki temu łatwo jest mieć wiele kas i bardzo zlokalizowane środowisko na każdą kasę. Ktoś może też po prostu skomponować całe repozytorium i nie martwić się o odinstalowanie jakichkolwiek programów.

To działa dobrze dla nas i nie jestem pewien, czy to zmienimy. Problem polega na tym, że w tym jednym dużym repozytorium jest wiele projektów. Czy istnieje standardowy sposób git / Hg / bzr tworzenia takiego środowiska i dzielenia projektów na ich własne repozytoria?

Danny G.
źródło
3

, Nie próbowałem jeszcze zagnieżdżać repozytoriów git, ponieważ nie napotkałem sytuacji, w której muszę. Jak czytałem na kanale #git, git wydaje się być zdezorientowany przez zagnieżdżanie repozytoriów, tj. Próbujesz git-init wewnątrz repozytorium git. Jedynym sposobem zarządzania zagnieżdżoną strukturą git jest użycie git-submodulelub systemu Androidrepo narzędzia .

Jeśli chodzi o tę odpowiedzialność za tworzenie kopii zapasowych, którą opisujesz, mówię deleguj ją ... Dla mnie zwykle umieszczam repozytorium „pochodzenia” dla każdego projektu na dysku sieciowym w pracy, który jest regularnie archiwizowany przez techników IT przez ich strategię tworzenia kopii zapasowych wybór. To proste i nie muszę się tym martwić. ;)

Spoike
źródło
2

A co z używaniem MR do zarządzania wieloma repozytoriami Git jednocześnie:

Polecenie mr (1) może pobierać, aktualizować lub wykonywać inne czynności na zestawie repozytoriów, tak jakby były jednym połączonym repozytorium. Obsługuje dowolną kombinację repozytoriów subversion, git, cvs, mercurial, bzr, darcs, cvs, vcsh, fossil i veracity, a także można łatwo dodać obsługę innych systemów kontroli wersji. […]

Jest niezwykle konfigurowalny poprzez proste skrypty powłoki. Oto kilka przykładów tego, co może zrobić:

[…]

  • Podczas aktualizowania repozytorium git pobierz z dwóch różnych strumieni i połącz je ze sobą.
  • Uruchom równolegle kilka aktualizacji repozytorium, znacznie przyspieszając proces aktualizacji.
  • Zapamiętaj działania, które zakończyły się niepowodzeniem z powodu braku połączenia z laptopem, aby można było je ponowić, gdy wróci do trybu online.
imz - Ivan Zakharyaschev
źródło
1

Istnieje inna metoda zagnieżdżania repozytoriów git, ale nie rozwiązuje ona problemu, którego szukasz. Jednak dla innych szukających rozwiązania byłem:

W repozytorium git najwyższego poziomu po prostu ukryj folder w .gitignore zawierający zagnieżdżone repozytorium git. Ułatwia to posiadanie dwóch oddzielnych (ale zagnieżdżonych!) Repozytoriów git.

arxpoetica
źródło