GIT: Vai a una cartella specifica


Risposte:


57

Come da "export git" (come "export svn")?

Puoi usarlo git checkout-index, questo è un comando di basso livello, se vuoi esportare tutto, puoi usare -a,

git checkout-index -a -f --prefix=/destination/path/

Per citare le pagine man:

Il "/" [sul prefisso] finale è importante. Il nome esportato ha letteralmente il prefisso con la stringa specificata.

Se vuoi esportare una determinata directory, ci sono alcuni trucchi coinvolti. Il comando accetta solo file, non directory. Per applicarlo alle directory, usa il comando 'trova' e invia l'output a git.

find dirname -print0 | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Anche dalle pagine man:

L'intuitività non è l'obiettivo qui. La ripetibilità è.


Purtroppo questo non funzionerà da un repository git nudo, anche con il set --prefix :-( (testato con git 1.9.1)
apeiros,

1
se vuoi controllare un ramo / commit di un repository bare git, usaGIT_WORK_TREE=../path/to/place git checkout
allicoder

4
git worktree(vedi sotto) imho è la risposta canonica oggi e potrebbe essere aggiunta qui.
geek-merlin,

213

Un'altra soluzione che è un po 'più pulita: basta specificare un diverso albero di lavoro.

Per effettuare il checkout di tutto, dal tuo HEAD (non dall'indice) a una directory di uscita specifica:

git --work-tree=/path/to/outputdir checkout HEAD -- .

Per effettuare il checkout di una sottodirectory o di un file da HEAD in una directory specifica:

git --work-tree=/path/to/outputdir checkout HEAD -- subdirname

4
Nota minore - hai bisogno di un percorso assoluto in quanto non si verifica l'espansione della tilde di shell, ovvero --work-tree=/home/thomasg/okcopypiuttosto che --work-tree=~/okcopy(possibilmente usare un percorso relativo mentre sei seduto nello stesso albero git funziona anche, ma in questo modo risiede la follia e le git statususcite in R'lyehian)
Tom Goodfellow,

10
Funziona come previsto anche con i vecchi commit (ad es. Dare un SHA al posto di HEAD), tuttavia git statusmostra quindi molte mod (presumibilmente perché l'indice ora corrisponde all'altra directory e non all'albero di lavoro normale intatto). git resetè tornato in buono stato.
Tom Goodfellow,

2
Lo stesso qui git statusmostra molte mod e git resetnon aiuta. Ho dovuto git checkout -f HEADripristinare lo stato del mio repository.
DUzun,

11
Cordiali saluti: è necessario creare la directory da soli, altrimenti si ottiene questo errore:fatal: This operation must be run in a work tree
timaschew

13
Ciò modifica in modo disastroso l'indice dell'albero principale di lavoro, che è generalmente negativo. Come suggerisce @TomGoodfellow, è git resetsufficiente ripristinare il principale albero di lavoro in sanità mentale. Per esportare in modo sicuro le sottodirectory del repository in qualsiasi SHA1, ramo o tag senza modificare l'albero di lavoro principale, vedere la famigerata git archivesoluzione di Charles Bailey . Allo stesso modo, per effettuare il checkout in sicurezza di più filiali contemporaneamente, il nuovo git worktree addsottocomando è tuo amico.
Cecil Curry,

25

Per un singolo file:

git show HEAD:abspath/to/file > file.copy

2
+1 e per chiarire il "certo commit precedente" (anziché HEAD): si riferisce a quello SHA1 IDche può essere facilmente trovato tramite gitk. Se avessi solo bisogno di "estrarre" quel file in una posizione temporanea (cioè non ripristinare), allora showgit show 82e54378856215ef96c5db1ff1160a741b5dcd70:MyProj/proguard/mapping.txt > myproj_mapping.txt
userei

19

Le soluzioni di cui sopra non hanno funzionato per me perché dovevo controllare una versione con tag specifica dell'albero. Ecco come cvs exportdovrebbe essere usato, a proposito. git checkout-indexnon accetta l'argomento tag, poiché estrae i file dall'indice. git checkout <tag>cambierebbe l'indice indipendentemente dall'albero di lavoro, quindi avrei bisogno di ripristinare l'albero originale. La soluzione che ha funzionato per me è stata quella di clonare il repository. Il clone condiviso è abbastanza veloce e non occupa molto spazio extra. La .gitdirectory può essere rimossa se lo si desidera.

git clone --shared --no-checkout <repository> <destination>
cd <destination>
git checkout <tag>
rm -rf .git

Le versioni più recenti di git dovrebbero supportare git clone --branch <tag>per verificare automaticamente il tag specificato:

git clone --shared --branch <tag> <repository> <destination>
rm -rf <destination>/.git

3
git --work-tree=/path/to/outputdir checkout <tag> -- .non ha funzionato per te?
Warvariuc,

1
No, non lo fa. Il file effettivo nella directory di lavoro originale rimane invariato, ma la versione gestita viene persa e sostituita con la versione dal tag. È particolarmente negativo se la versione in fasi conteneva una serie di modifiche accuratamente selezionate da impegnare. Non voglio che il comando export tocchi il mio indice, punto.
proski,

19

Se stai lavorando con la tua funzione e non vuoi tornare alla pagina principale, puoi eseguire:

cd ./myrepo

git worktree add ../myrepo_master master

git worktree remove ../myrepo_master

Creerà una ../myrepo_masterdirectory con mastercommit delle filiali, dove puoi continuare a lavorare


1
Risposta migliore: semplice e, a differenza di git --work-tree=/path/to/outputdir checkout HEAD -- .quanto non faccia nulla all'indice, copia semplicemente il ramo selezionato nella posizione specificata (con l'aggiunta di un file .git).
Roger Dueck,

E come annullerei questo cambiamento?
Scott P.

@ ScottP.just rimuovi myrepo_masterdirectory
itsnikolay

1
annullare questo è un sottocomando di worktree:git worktree remove ../myrepo_master
Martijn Dashorst

8

La risposta di Adrian fu "fatale: questa operazione deve essere eseguita su un albero di lavoro". Quello che segue è ciò che ha funzionato per noi.

git worktree add <new-dir> --no-checkout --detach
cd <new-dir>
git checkout <some-ref> -- <existing-dir>

Appunti:

  • --no-checkout Non effettuare il checkout di nulla nel nuovo worktree.
  • --detach Non creare un nuovo ramo per il nuovo worktree.
  • <some-ref>funziona con qualsiasi ref, ad esempio, funziona con HEAD~1.
  • Pulizia con git worktree prune.

+1 per i commenti su come pulire - tutti gli altri sono felici di fare un pasticcio con il repository corrente. solo questo non ha effetti collaterali.
Andrew Hill,

1

Aggiunta alla risposta di @ hasen . Per elencare i file al checkout , potresti voler usare git ls-filesinvece di findcome:

git ls-files -z *.txt | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Grazie per aver usato correttamente -z! È bello fornire script che non sono vulnerabili a determinati tipi di attacchi di iniezione.
ErikE

0

Ho definito un alias git per raggiungere questo obiettivo (prima di trovare questa domanda).

È una breve funzione bash che salva il percorso corrente, passa al repository git, esegue un checkout e torna da dove è iniziato.

git check per sviluppare ~ / my_project_git

Questo ad esempio verificherebbe il ramo di sviluppo nella directory "~ / my_project_git".

Questo è il codice alias all'interno ~/.gitconfig:

[alias]
    checkTo = "!f(){ [ -z \"$1\" ] && echo \"Need to specify branch.\" && \
               exit 1; [ -z \"$2\" ] && echo \"Need to specify target\
               dir\" && exit 2; cDir=\"$(pwd)\"; cd \"$2\"; \
               git checkout \"$1\"; cd \"$cDir\"; };f"

0

Sto usando questo alias per estrarre un ramo in una directory temporanea:

[alias]
    cot = "!TEMP=$(mktemp -d); f() { git worktree prune && git worktree add $TEMP $1 && zsh -c \"cd $TEMP; zsh\";}; f" # checkout branch in temporary directory

Uso:

git cot mybranch

Si viene quindi rilasciati in una nuova shell nella directory temporanea in cui è possibile lavorare sul ramo. Puoi anche usare i comandi git in questa directory.

Al termine, elimina la directory ed esegui:

git worktree prune

Questo viene anche eseguito automaticamente nell'alias, prima di aggiungere un nuovo worktree.


0

Utilizzare git archive branch-index | tar -x -C your-folder-on-PCper clonare un ramo in un'altra cartella. Penso, quindi puoi copiare qualsiasi file di cui hai bisogno

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.