2010-04-06 16 views
66

E 'possibile clonare un solo ramo (o da una data commit) in Git e Mercurial? Voglio dire, voglio clonare un repo centrale, ma dal momento che è enorme mi piacerebbe ottenere solo una parte di esso e di essere ancora in grado di contribuire indietro i miei cambiamenti. È possibile? Come, voglio solo dal Tag 130 in poi o qualcosa del genere?clone parziale con Git e Mercurial

Se sì, come?

risposta

67

In terra Git si parla di tre diversi tipi di cloni parziali:

  • cloni poco profonde: voglio storia dalla revisione punto X in poi.

    Utilizzare git clone --depth <n> <url> per quello, ma per favore ricorda che i cloni superficiali sono un po 'limitati nell'interagire con altri repository. Sarai in grado di generare patch e inviarle via email.

  • clone parziale filepath: voglio tutta la storia cronologia delle revisioni in una directory /path.

    Non possibile in Git. Con Git moderno anche se è possibile avere sparse cassa, vale a dire di avere la storia intera, ma è il check-out (avere nella zona di lavoro) solo sottoinsieme di tutti i file.

  • clonazione selezionata solo ramo: voglio clonare un solo ramo (o un sottoinsieme selezionato di filiali).

    Possibile, e

    prima di git 1.7.10 non è semplice: si avrebbe bisogno di fare quello che fa clonare manualmente, cioè git init [<directory>], poi git remote add origin <url>, modificare .git/config sostituendo * in remote.origin.fetch per ramo richiesto (probabilmente 'master '), quindi git fetch.

    as of git 1.7.10git clone offre l'opzione --single-branch che sembra essere stata aggiunta solo per questo scopo e sembra piuttosto semplice.

    Si noti tuttavia che poiché i rami di solito condividono la maggior parte della loro cronologia, il guadagno derivante dalla clonazione di un solo sottoinsieme di rami potrebbe essere inferiore a quello che si pensa.

È anche possibile eseguire un clone superficiale di solo sottoinsieme selezionato di rami.

Se sai come la gente vuole rompere le cose dalla percorsofile (progetti multipli nello stesso repository) è possibile utilizzare sottomoduli (un po 'come svn: esterni) per pre-split il repo in porzioni separatamente clonabile.

+0

Quindi, se cloniamo il ramo "XX", otterremo tutti i comandi principali da "master", giusto? O solo il singolo commit che ho fatto su quel ramo? – pablo

+1

Se clonate (prendete) solo il ramo "XX", otterrete tutti i suoi commit, compresi quelli che il ramo "XX" ha in comune con il ramo "master". In Git commits non "* appartiene *" a un ramo. –

+0

Ok, allora non è un clone parziale comunque da quando hai tutti i genitori e quindi l'intero repository (ok, la parte più grande che è sul master) – pablo

41

In terra Mercurial si sta parlando di tre diversi tipi di cloni parziali:

  • cloni poco profonde: Voglio la storia dalla revisione punto X in poi utilizzare i remotefilelog extension
  • cloni parziali filepath: Voglio tutta la cronologia delle revisioni in directory/percorso con sperimentale narrowhg extension o voglio solo i file nella directory/percorso nella mia directory di lavoro con estensione sparse sperimentale (spedito dalla versione 4.3, vedere hg help sparse).
  • cloni parziali per ramo: Voglio che tutti la cronologia di revisione sul ramo Y: uso clone -r

Se sai come la gente vuole rompere le cose dalla percorsofile (più progetti nello stesso repo (vergogna su di te)) è possibile utilizzare i sottoregisti (un po 'come svn esterni) per pre-dividere il repository in porzioni separate clonabili

Inoltre, per quanto riguarda "così enorme mi piacerebbe solo ottenere una parte di esso" : Devi solo farlo una volta sola. Basta clonarlo mentre pranzi, e poi lo hai sempre per sempre. Successivamente è possibile pull e ottenere delta in modo efficiente per il futuro. E se vuoi un altro clone, clona il tuo primo clone. Dove hai un clone non ha importanza (e cloni locali non prendono spazio su disco aggiuntivo, dato che sono gli hard link sotto le coperte).

+1

anche i tag non sono gli stessi di rami a differenza di alcuni VCS, quindi questo è sotto il primo punto –

+0

Ci sono la cronologia di ritaglio (http://mercurial.selenic.com/wiki/TrimmingHistory) e il clone superficiale (http://mercurial.selenic.com/wiki/ShallowClone) plugin per mercurial. Non so quanto siano bravi, però. – panzi

+8

Entrambe sono proposte rifiutate senza implementazioni. –

-1

in Mercurial, si dovrebbe essere in grado di così alcune di queste utilizzando:

hg convert --banchmap FILE SOURCEDEST REVMAP 

Si consiglia inoltre di:

--config convert.hg.startrev=REV 

La fonte può essere git, mercuriale, o una varietà di altri sistemi.

Non l'ho provato, ma convert è piuttosto ricco.

+3

L'estensione di conversione riscrive gli hash quindi non è parziale clone del repository esistente ma piuttosto nuovo. Significa che sarà un deposito separato che non può tirare o spingere da quello originale. – Priit

5

questo metodo crea un archivio sotto controllo di versione senza subrepositories:

hg clone -U ssh://machine//directory/path/to/repo/project projecttemp 

cd projecttemp 

hg archive -r tip ../project-no-subrepos 

Il codice sorgente sotto controllo di versione senza le subrepositoies è nella directory del progetto-no-subrepos

2

Per quanto riguarda Git che potrebbe essere di un significato storico che Linus Torvalds ha risposto a questa domanda dal punto di vista concettuale nel 2007 in un discorso che è stato registrato ed è disponibile online.

La domanda è se è possibile estrarre solo alcuni file da un repository Git.

Tech Talk: Linus Torvalds on git t=43:10

In sintesi, ha detto che una delle decisioni di progettazione di Git che lo distingue da altri sistemi di gestione di origine (si cita BitKeeper e SVN) è che Git gestisce i contenuti, non i file. Le implicazioni sono che per es. un diff di un sottoinsieme di file in due revisioni viene calcolato prendendo innanzitutto l'intero diff e quindi potendolo solo ai file che sono stati richiesti. Un altro è che devi controllare l'intera storia; in un modo tutto o niente. Per questo motivo, suggerisce di suddividere i componenti liberamente correlati tra più repository e menziona uno sforzo in corso per implementare un'interfaccia utente per la gestione di un repository strutturato come un super-progetto con archivi più piccoli.

Per quanto ne so, questa decisione fondamentale sul design è ancora valida oggi. La cosa del super-progetto è probabilmente diventata ciò che ora è submodules.

+1

Conosco il post ... Inizialmente l'ho inviato a slashdot: P – pablo

6

La risposta selezionata offre una buona panoramica, ma manca un esempio completo.

Ridurre al minimo il download e nella verifica impronta (a), (b):

git clone --no-checkout --depth 1 --single-branch --branch (name) (repo) (folder) 
cd (folder) 
git config core.sparseCheckout true 
echo "target/path/1" >>.git/info/sparse-checkout 
echo "target/path/2" >>.git/info/sparse-checkout 
git checkout 

periodicamente ottimizzare le emissioni di anidride repository locale (c) (opzionale, utilizzare con cautela):

git clean --dry-run # consider and tweak results then switch to --force 
git gc 
git repack -Ad 
git prune 

Vedi anche : How to handle big repositories with git

+0

Ottimo esempio/best practice. +1 – VonC