2010-02-25 12 views
64

Con il nuovo sparse checkout feature in Git 1.7.0, è possibile ottenere solo il contenuto di una sottodirectory come in SVN? Ho trovato this example, ma conserva la struttura completa della directory. Immagina di volere solo il contenuto della directory 'perl', senza una directory effettiva chiamata 'perl'.Checkout sparsi in Git 1.7.0?

- EDIT -

Esempio:

mio repository git contiene i seguenti percorsi

repo/.git/ 
repo/perl/ 
repo/perl/script1.pl 
repo/perl/script2.pl 
repo/images/ 
repo/images/image1.jpg 
repo/images/image2.jpg 
repo/doc/ 
repo/doc/readme.txt 
repo/doc/help.txt 

Quello che voglio è quello di essere in grado di produrre dal repository questo layout sopra :

repo/.git/ 
repo/script1.pl 
repo/script2.pl 

Tuttavia wi th l'attuale funzionalità di check-out sparse, sembra che sia possibile ottenere solo

che NON è quello che voglio.

+4

hanno finalmente implementato! freddo! –

+0

Perché? Qual è il problema? E perché vuoi avere una struttura di directory diversa nel repository e diversa localmente? Non ha molto senso a prima vista. –

+2

@Jiri: Ho un'applicazione Web con codice actionscript (lato client) e PHP (lato server). I file sono strettamente correlati, quindi voglio metterli in un unico repository/filiale. Tuttavia non voglio i file di origine actionscript sul server, solo i file PHP. – davr

risposta

23

Hai ancora bisogno di clonare l'intero repository, che avrà tutti i file. È possibile utilizzare il flag --depth per recuperare solo una quantità limitata di cronologia.

Una volta clonato il repository, il trucco di read-tree limita la "visualizzazione" del repository solo ai file o alle directory presenti nel file .git/info/sparse-checkout.

ho scritto un breve script per aiutare a gestire la scarsità, dato che al momento è un po 'ostile:

#!/bin/sh 
echo > .git/info/sparse-checkout 
for i in "[email protected]" 
do 
    echo "$i" >> .git/info/sparse-checkout 
done 
git read-tree -m -u HEAD 

Se si salva questo script come git-sparse.sh nel percorso riportato chiamando git --exec-path, allora si può eseguire git sparse foo/ bar/ solo per "checkout" le directory foo e bar o git sparse '*' per ottenere di nuovo tutto.

+0

Grazie per l'aiuto, ma questo non sembra rispondere alla mia domanda. Vedi la mia domanda aggiornata per chiarimenti. – davr

+3

Sì, sparse è solo un modo per filtrare l'albero attuale, non può spostare file in giro. Quindi non puoi fare quello che vuoi ... – richq

16

La risposta breve è no. Git vede tutti i file come una singola unità.

Quello che consiglio è di suddividere i repository in blocchi logici. Uno separato per perl, immagini e documenti. Se è anche necessario mantenere lo stile di repository di Uber, è possibile creare un repository composto da Submodules.

5

Ora senza immergersi nei dettagli sul motivo per cui si desidera eseguire questa operazione, il problema può essere (probabilmente) facilmente risolto da un collegamento simbolico/collegamento.

Per rispondere alla domanda: no, e con una motivazione significativa. L'intera cronologia del repository viene scaricata anche con un "check-out sparse". Per chiarire perché è necessario, altrimenti il ​​rintracciare i file rinominati sarebbe un dolore al collo. Immagina di spostare il file /repo_root/asd/file1.cpp in /repo_root/fgh/file1.cpp - ora se hai scaricato solo i prefissi /repo_root/fgh, non saprai su file1.cpp. Questo significa che devi scaricare tutti i delta. Ma poi hai un repository completo; non solo una cartella tagliata, quindi solo la cartella /rero_root/fgh non è un repository stesso. Questo potrebbe non sembrare importante quando fai il checkout, ma quando ti impegni, git potrebbe non sapere abbastanza per lavorare bene.

Soluzione: Se davvero si vuole, è possibile creare uno script che chiama git-checkout in modo tale (per la shell sh, in lotti per le finestre non dovrebbe essere difficile da produrre):

!/bin/sh 
curDir=`pwd` 
cd $2 
git-checkout $1 
cp -R $3/* $4 
cd $curDir 

Qui il primo argomento è il ramo da verificare, il secondo - la cartella in cui il repository è attualmente presente, il terzo - il sotto-indirizzo che si vuole veramente usare, e il quarto - il luogo in cui si desidera copiarlo.

Attenzione: le mie capacità di shell sono quasi inesistenti, quindi usalo dopo il test. Non dovrebbe essere difficile ricreare il contrario di questo script, che copia le cose, in modo che possa essere impegnato nel repository.

+0

Avere l'intera cronologia del repository non è un problema, non è un grande repository e abbiamo un sacco di spazio su disco. Immagino che il nostro caso d'uso particolare non sia così comune, quindi gli sviluppatori di git non hanno mai pensato di aggiungerlo. È una delle pochissime cose che SVN ha funzionato meglio per noi (git fa meglio altre 99 cose, motivo per cui siamo passati, ma ancora) – davr

+0

i collegamenti simbolici su Windows sono un incubo - questo non è trattabile. –

+0

lulz al ragazzo di windows – nottinhill

3

git filter-branch --subdirectory-filter è quello che ti serve, vedi Detach (move) subdirectory into separate Git repository.

Ecco un piccolo script bash per farlo.

Questo farà prima una copia di lavoro del repository originale, quindi filtra il filtro usando il filtro di sottodirectory per ottenere quello che vuoi.

#!/bin/bash 
# 
# git-subdir.sh 
# 
git clone --no-hardlinks $1 $2 

cd $2 

git filter-branch --subdirectory-filter $2 --prune-empty --tag-name-filter cat HEAD -- --all 

git reset --hard 

git remote rm origin 

refbak=$(git for-each-ref --format="%(refname)" refs/original/) 

if [ -n "$refbak" ];then 
    echo -n $refbak | xargs -n 1 git update-ref -d 
fi 

git reflog expire --expire=now --all 

git repack -ad 

git gc --aggressive --prune=now 

Usa per l'esempio nella questione, git-subdir.sh repo perl funzionerebbe.

0

Sembra che ciò che si sta tentando di fare è rinominare l'albero delle directory in modo tale che i file finiscano in un posto diverso. Mi sembra che quello che chiedi di fare sia un anti-template per la gestione di codice/progetto su due fronti: categorizzazione dei moduli (bit java sotto nodo java, perl sotto nodo perl) e un progetto con file in posizioni diverse da dove lo sviluppatore li visualizza. Dato che git mantiene gli hash dei contenuti della directory per vedere cosa è cambiato, questo interrompe anche git in quanto tale.

Daemeon Reiydelle