Come si organizzano più repository Git, in modo che venga eseguito il backup di tutti insieme?


98

Con SVN, avevo un unico grande repository che tenevo su un server e che controllavo su alcune macchine. Questo è stato un buon sistema di backup e mi ha permesso di lavorare facilmente su qualsiasi macchina. Potrei effettuare il checkout di un progetto specifico, eseguire il commit e ha aggiornato il progetto 'master', oppure potrei controllare l'intero file.

Ora, ho un sacco di repository git, per vari progetti, molti dei quali sono su GitHub. Ho anche il repository SVN che ho citato, importato tramite il comando git-svn ..

Fondamentalmente, mi piace avere tutto il mio codice (non solo progetti, ma frammenti e script casuali, alcune cose come il mio CV, articoli che ho scritto, siti Web che ho creato e così via) in un grande repository che posso facilmente clonare su remoto macchine o memory stick / hard disk come backup.

Il problema è che, dal momento che si tratta di un repository privato, e git non consente il check-out da una cartella specifica (che potrei inviare a github come progetto separato, ma fare in modo che le modifiche appaiano sia nel repository principale che nel sub- pronti contro termine)

Ho potuto utilizzare il sistema git modulo, ma non agisce come lo voglio troppo (sottomoduli sono puntatori ad altri repository, e in realtà non contengono il codice vero e proprio, quindi è inutile per il backup)

Attualmente ho una cartella di git-repos (ad esempio, ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /) e dopo aver apportato modifiche a proj1 lo faccio git push github, quindi copio i file in ~ / Documents / code / python / projects / proj1 / ed eseguire un singolo commit (invece dei numerosi nei singoli repository). Allora fai git push backupdrive1, git push mymemorystickecc

Quindi, la domanda: come funzionano il tuo codice personale e progetti con i repository git e mantenerli sincronizzati e sottoposti a backup?

Risposte:


74

Vorrei fortemente sconsigliare mettendo i dati non correlati in un dato repository Git. Il sovraccarico della creazione di nuovi repository è piuttosto basso e questa è una caratteristica che consente di mantenere diverse linee completamente separate.

Combattere questa idea significa finire con una storia inutilmente intricata, che rende l'amministrazione più difficile e - cosa più importante - gli strumenti di "archeologia" meno utili a causa della diluizione che ne deriva. Inoltre, come hai detto, Git presume che "l'unità di clonazione" sia il repository, e praticamente lo deve fare a causa della sua natura distribuita.

Una soluzione è mantenere ogni progetto / pacchetto / ecc. come il proprio archivio nudo (cioè senza albero funzionante) sotto una gerarchia benedetta, come:

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

Una volta stabilite alcune convenzioni, diventa banale applicare le operazioni amministrative (backup, impacchettamento, pubblicazione sul web) alla gerarchia completa, che svolge un ruolo non del tutto dissimile dai repository SVN "monolitici". Anche lavorare con questi repository diventa in qualche modo simile ai flussi di lavoro SVN, con l'aggiunta che si possono utilizzare commit e branch locali:

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

Puoi avere più telecomandi in ogni clone funzionante, per la facilità di sincronizzazione tra più parti:

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

Puoi quindi recuperare / estrarre da ciascuna delle "fonti", lavorare e eseguire il commit a livello locale, quindi eseguire il push ("backup") su ciascuno di questi telecomandi quando sei pronto con qualcosa di simile (nota come questo spinge gli stessi commit e cronologia a ciascuno dei telecomandi!):

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

Il modo più semplice per trasformare un repository funzionante esistente ~/dev/foo in un repository così spoglio è probabilmente:

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

che è per lo più equivalente a svn import- ma non elimina la storia "locale" esistente.

Nota: i sottomoduli sono un meccanismo per includere lignaggi correlati condivisi , quindi non li considererei uno strumento appropriato per il problema che stai cercando di risolvere.


18
Il fatto che continuo a finire con molti repository separati e scrivere semplici script per aiutarli a gestirli tutti mi fa sentire che manca qualcosa in git. Non riesco a decidere esattamente cosa sia o cosa fare al riguardo.
DonGar

Bene, gestisci anche molti progetti separati? Una relazione uno-a-uno tra progetti e repository sembra ragionevole in un mondo distribuito, ma vorrei comunque organizzare i repository spogli in un albero di directory comune per facilitare il backup e l'amministrazione. (In altre parole, Git / Hg / Bzr ti obbliga a separare l'amministrazione dalle attività del progetto, mentre la maggior parte dei flussi di lavoro SVN confonde i due; ora è comune vedere persone delegare la parte amministrativa a GitHub o ad altri fornitori simili.)
Damien Diederen

2
questa idea ha senso solo se ospiti i tuoi progetti e / o sono tutti open source. Altrimenti avresti bisogno su GitHub di progetti privati ​​illimitati che potrebbero diventare costosi
dkinzer

2
Invece di "per remote in origine github memorystick; do git push $ remote; done", si può anche configurare un telecomando speciale per inviare con un singolo comando a molti telecomandi: stackoverflow.com/questions/36862/… . (Potrebbe essere più conveniente in alcuni casi.)
imz - Ivan Zakharyaschev

2
Penso che la cosa mancante sia un modo in cui git può mantenere i suoi oggetti separati per sottostruttura in modo che un singolo "repository" possa essere composto da unità separate sincronizzate sebbene separabili (scaricate individualmente senza il resto) in modo tale che le persone possano lavorare su specifiche sottoinsiemi senza conoscere il resto.
Peterk

28

Voglio aggiungere alla risposta di Damien dove consiglia:

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

È possibile impostare un telecomando speciale per spingere a tutti i singoli telecomandi reali con 1 comando; L'ho trovato su http://marc.info/?l=git&m=116231242118202&w=2 :

Quindi per "git push" (dove ha senso spingere gli stessi rami più volte), puoi effettivamente fare quello che faccio io:

  • .git / config contiene:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • e ora git push all masterinvierà il ramo "master" a entrambi
    i repository remoti.

Puoi anche risparmiare digitando due volte gli URL utilizzando la costruzione:

[url "<actual url base>"]
    insteadOf = <other url base>

3

Sono anche curioso dei modi suggeriti per gestirlo e descriverò la configurazione corrente che uso (con SVN). Fondamentalmente ho creato un repository che contiene una gerarchia di mini-filesystem comprese le proprie directory bin e lib. C'è uno script nella radice di questo albero che configurerà il tuo ambiente per aggiungere queste directory bin, lib, ecc ... alle variabili di ambiente appropriate. Quindi la directory principale si presenta essenzialmente come:

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

Ora dentro / bin e / lib ci sono i progetti multipli e le loro librerie corrispondenti. So che questo non è un progetto standard, ma è molto facile per qualcun altro nel mio gruppo controllare il repository, eseguire lo script 'setup_env.bash' e avere le versioni più aggiornate di tutti i progetti localmente nel loro check-out. Non devono preoccuparsi di installare / aggiornare / usr / bin o / usr / lib e rende semplice avere più checkout e un ambiente molto localizzato per checkout. Qualcuno può anche solo rm l'intero repository e non preoccuparsi di disinstallare alcun programma.

Funziona bene per noi e non sono sicuro che lo cambieremo. Il problema con questo è che ci sono molti progetti in questo grande repository. Esiste un modo standard git / Hg / bzr per creare un ambiente come questo e suddividere i progetti nei propri repository?


3

, Non ho ancora provato a nidificare i repository git perché non mi sono imbattuto in una situazione in cui ne ho bisogno. Come ho letto sul canale #git, git sembra essere confuso annidando i repository, cioè stai cercando di git-init all'interno di un repository git. L'unico modo per gestire una struttura git nidificata è utilizzare git-submoduleo l' repoutilità di Android .

Per quanto riguarda la responsabilità di backup che stai descrivendo, dico delegala ... Per me di solito metto il repository "origin" per ogni progetto su un'unità di rete al lavoro che viene regolarmente sottoposta a backup dai tecnici IT con la loro strategia di backup di scelta. È semplice e non devo preoccuparmene. ;)


2

Che ne dici di usare mr per gestire più repository Git contemporaneamente:

Il comando mr (1) può effettuare il checkout, aggiornare o eseguire altre azioni su un set di repository come se fossero un unico repository combinato. Supporta qualsiasi combinazione di repository subversion, git, cvs, mercurial, bzr, darcs, cvs, vcsh, fossil e veracity e può essere facilmente aggiunto il supporto per altri sistemi di controllo delle revisioni. [...]

È estremamente configurabile tramite semplici script di shell. Alcuni esempi di cose che può fare includono:

[...]

  • Quando si aggiorna un repository git, eseguire il pull da due diversi upstream e unire i due insieme.
  • Esegui diversi aggiornamenti del repository in parallelo, accelerando notevolmente il processo di aggiornamento.
  • Ricorda le azioni che non sono riuscite a causa di un laptop offline, in modo che possano essere ritentate quando torna online.

1

C'è un altro metodo per avere repository git annidati, ma non risolve il problema che stai cercando. Tuttavia, per altri che stanno cercando la soluzione ero:

Nel repository git di livello superiore basta nascondere la cartella in .gitignore contenente il repository git nidificato. Ciò rende facile avere due repository git separati (ma annidati!).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.