Come posso fare il checkout di un solo file da un repository git?
Come posso fare il checkout di un solo file da un repository git?
Risposte:
In origine, ho detto nel 2012 git archive
(vedi Jared Forsyth 's risposta e Robert Knight ' s risposta ), dal momento che git1.7.9.5 (marzo 2012) , Paul Brannan 's risposta :
git archive --format=tar --remote=origin HEAD:path/to/directory -- filename | tar -O -xf -
Ma: nel 2013, questo non era più possibile per gli URL https://github.com remoti .
Vedi la vecchia pagina " Posso archiviare un repository? "
L'attuale pagina (2018) " Informazioni sull'archiviazione di contenuti e dati su GitHub " raccomanda di utilizzare servizi di terze parti come GHTorrent o GH Archive .
Quindi puoi anche gestire copie / cloni locali:
In alternativa, è possibile effettuare le seguenti operazioni se si dispone di una copia locale del repository nudo come indicato in questa risposta ,
git --no-pager --git-dir /path/to/bar/repo.git show branch:path/to/file >file
Oppure devi prima clonare il repository, nel senso che ottieni la cronologia completa: - nel repository .git - nell'albero di lavoro.
git config core.sparsecheckout true
).git/info/sparse-checkout
filePer rileggere l'albero di lavoro:
$ git read-tree -m -u HEAD
In questo modo, si finisce con un albero di lavoro che include esattamente ciò che si desidera (anche se si tratta di un solo file)
Richard Gomes punta ( nei commenti ) a " Come posso clonare, recuperare o eseguire il checkout di una singola directory o un elenco di directory dal repository git? "
Una funzione bash che evita il download della cronologia, che recupera un singolo ramo e che recupera un elenco di file o directory necessari.
git archive
ora.
Prima clona il repository con l'opzione -n, che elimina il checkout predefinito di tutti i file e l'opzione --depth 1, il che significa che ottiene solo la revisione più recente di ogni file
git clone -n git://path/to/the_repo.git --depth 1
Quindi controlla solo il file che desideri in questo modo:
cd the_repo
git checkout HEAD name_of_file
-n
funzioni: l'albero di lavoro e l'indice finiscono in sincronia. Cioè, tutto il contenuto viene visualizzato come eliminato. Devi o git reset HEAD
o git checkout HEAD file
. A questo punto è anche molto difficile lavorare con il repository a meno che tu non capisca davvero come funziona git.
rm -rf .git
alla sceneggiatura di NickMoore possa ripulire tutte le tracce del repository clonato e forse dissipare la preoccupazione di Jefromi di avere un repository difficile da usare. Mi rende molto utile per diverse applicazioni, come la mia sfida di oggi per creare un hook post-ricezione per aggiornare automaticamente la versione di un altro hook post-ricezione.
git
non è la migliore per questo tipo di lavoro). Questa risposta è valida anche per questa domanda , o per questa altra popolare , e molte altre: cambia name_of_file
in name_of_folder
. Git in oggigiorno (2014) offre sottomoduli al proprietario del repo offrendo un po 'amichevole per gli utenti repo.
Se hai già una copia del repository git, puoi sempre fare il checkout di una versione di un file usando a git log
per scoprire l'hash-id (ad esempio 3cdc61015724f9965575ba954c8cd4232c8b42e4) e quindi digita semplicemente:
git checkout hash-id path-to-file
Ecco un esempio reale:
git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 /var/www/css/page.css
path-to-file
è una directory e corrente HEAD
contiene un certo file mentre target
non lo fa (o viceversa), questo non aggiornerà correttamente il file. C'è un modo per gestire?
Normalmente non è possibile scaricare un solo file git
senza scaricare l'intero repository come suggerito nella prima risposta. È perché Git non memorizza i file come pensi (come fanno CVS / SVN), ma li genera in base all'intera cronologia del progetto.
Ma ci sono alcune soluzioni alternative per casi specifici. Esempi di seguito con segnaposti per user
, project
, branch
, filename
.
GitHub
wget https://raw.githubusercontent.com/user/project/branch/filename
GitLab
wget https://gitlab.com/user/project/raw/branch/filename
gitweb
Se stai usando Git sul server - GitWeb , puoi provare ad esempio (cambiarlo nel percorso giusto):
wget "http://example.com/gitweb/?p=example;a=blob_plain;f=README.txt;hb=HEAD"
GitWeb su drupalcode.org
Esempio:
wget "http://drupalcode.org/project/ads.git/blob_plain/refs/heads/master:/README.md"
googlesource.com
Esiste una funzione non documentata che consente di scaricare versioni di file raw con codifica base64:
curl "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT" | base64 --decode
In altri casi controlla se il tuo repository Git sta usando interfacce web.
Se non utilizza alcuna interfaccia web, puoi considerare di inviare il tuo codice a servizi esterni come GitHub , Bitbucket , ecc . e usalo come specchio.
Se non hai wget
installato, prova in curl -O (url)
alternativa.
wget
risposta brillante e la semplicità ritorna, insieme alla felicità. Grazie uomo.
git checkout branch_or_version - percorso / file
esempio: git checkout HEAD -- main.c
git checkout -- <filename>
Rif: https://git-scm.com/docs/git-checkout
Dup: Annulla le modifiche della copia di lavoro di un file in Git?
git-checkout
.
Adesso possiamo! Dato che questo è il primo risultato su Google, ho pensato di aggiornarlo all'ultima posizione. Con l'avvento di git 1.7.9.5, abbiamo il git archive
comando che ti permetterà di recuperare un singolo file da un host remoto.
git archive --remote=git://git.foo.com/project.git HEAD:path/in/repo filename | tar -x
Vedi la risposta completa qui https://stackoverflow.com/a/5324532/290784
github.com
HEAD
o master
no HEAD:directory
.
git archive --remote=git@bitbucket.org:user/repo branch:path/to file | tar -x
Lavorare in GIT 1.7.2.2
Ad esempio, hai unremotoremoto con rami branch1 , branch32
quindi per fare il checkout di un file specifico chiamate questi comandi:
git checkout remote/branch path/to/file
ad esempio sarà qualcosa di simile
git checkout some_remote/branch32 conf/en/myscript.conf
git checkout some_remote/branch1 conf/fr/load.wav
Questo comando di checkout copia l'intera struttura del file conf / en e conf / fr nella directory corrente in cui chiamate questi comandi (ovviamente suppongo che abbiate eseguito git init ad un certo punto prima)
git fetch some_remote
prima, vero?
Molto semplice:
git checkout from-branch-name -- path/to/the/file/you/want
Questo non verificherà il from-branch-name
ramo. Rimarrai su qualsiasi ramo in cui ti trovi e solo quel singolo file verrà estratto dal ramo specificato.
Ecco la parte rilevante della manpage per git-checkout
git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>...
When <paths> or --patch are given, git checkout does not switch
branches. It updates the named paths in the working tree from the
index file or from a named <tree-ish> (most often a commit). In
this case, the -b and --track options are meaningless and giving
either of them results in an error. The <tree-ish> argument can be
used to specify a specific tree-ish (i.e. commit, tag or tree) to
update the index for the given paths before updating the working
tree.
Punta di cappello ad Ariejan de Vroom che mi ha insegnato questo da questo post sul blog .
git clone --filter
da Git 2.19
Questa opzione salterà effettivamente il recupero della maggior parte degli oggetti non necessari dal server:
git clone --depth 1 --no-checkout --filter=blob:none \
"file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mydir/myfile
Il server deve essere configurato con:
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
Non esiste alcun supporto server dalla v2.19.0, ma può già essere testato localmente.
TODO: --filter=blob:none
salta tutti i BLOB, ma recupera comunque tutti gli oggetti dell'albero. Ma su un normale repository, questo dovrebbe essere minuscolo rispetto ai file stessi, quindi questo è già abbastanza buono. Alla domanda: https://www.spinics.net/lists/git/msg342006.html Gli sviluppatori hanno risposto che --filter=tree:0
è in lavorazione per farlo.
Ricorda che ciò --depth 1
implica già --single-branch
, vedi anche: Come posso clonare un singolo ramo in Git?
file://$(path)
è necessario per superare il git clone
protocollo shenanigans: come clonare in modo superficiale un repository git locale con un percorso relativo?
Il formato di --filter
è documentato su man git-rev-list
.
È stata creata un'estensione al protocollo remoto Git per supportare questa funzione.
Documenti sull'albero Git:
Provalo
#!/usr/bin/env bash
set -eu
list-objects() (
git rev-list --all --objects
echo "master commit SHA: $(git log -1 --format="%H")"
echo "mybranch commit SHA: $(git log -1 --format="%H")"
git ls-tree master
git ls-tree mybranch | grep mybranch
git ls-tree master~ | grep root
)
# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'
rm -rf server_repo local_repo
mkdir server_repo
cd server_repo
# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet
# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet
# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet
echo "# List and identify all objects"
list-objects
echo
# Restore master.
git checkout --quiet master
cd ..
# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo
# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo
echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo
echo "# Git checkout fetches the missing file from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/a
echo
echo "# Missing objects after checking out d1/a"
git rev-list --all --quiet --objects --missing=print
Uscita in Git v2.19.0:
# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root
# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63
# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
# Missing objects after checking out d1
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
Conclusioni: d1/a
mancano tutti i BLOB tranne quelli. Ad esempio f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
, che è d1/b
, non è lì dopo il check out d1/
.
Si noti che root/root
e mybranch/mybranch
mancano anche, ma lo --depth 1
nasconde dall'elenco dei file mancanti. Se rimuovi --depth 1
, verranno visualizzati nell'elenco dei file mancanti.
Puoi farlo da
git archive --format=tar --remote=origin HEAD | tar xf -
git archive --format=tar --remote=origin HEAD <file> | tar xf -
Due varianti su ciò che è già stato dato:
git archive --format=tar --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | tar -O -xf -
e:
git archive --format=zip --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | funzip
Questi scrivono il file nell'output standard.
In git non esegui il "checkout" dei file prima di aggiornarli - sembra che questo sia ciò che stai cercando.
Molti sistemi come clearcase, csv e così via richiedono il "checkout" di un file prima di poter apportare modifiche. Git non lo richiede. Clonare un repository e quindi apportare modifiche nella copia locale del repository.
Dopo aver aggiornato i file puoi fare:
git status
Per vedere quali file sono stati modificati. Aggiungete quelli con cui volete impegnarvi per index
primi ( index
è come un elenco da archiviare):
git add .
o
git add blah.c
Quindi git status
ti mostrerà quali file sono stati modificati e quali sono index
pronti per essere salvati o archiviati.
Per eseguire il commit dei file nella copia del repository, procedere come segue:
git commit -a -m "commit message here"
Vedere il git
sito Web per i collegamenti a manuali e guide.
git format-patch
per creare una patch per l'invio ( git format-patch -1
creerà una patch solo per il tuo ultimo commit).
Ecco la soluzione completa per estrarre e spingere solo un determinato file all'interno del repository git:
git clone --no-checkout <git url>
git reset
git checkout origin/master <path to file>
git add <path to file>
git commit -m <message text>
git push
Vedi anche un link per alcune informazioni aggiuntive.
Sembra che tu stia cercando di trasferire un'idea dal controllo centralizzato della versione, che git per natura non lo è - è distribuito. Se vuoi lavorare con un repository git, lo cloni. Quindi hai tutto il contenuto dell'albero di lavoro e tutta la cronologia (beh, almeno tutto ciò che porta alla punta del ramo corrente), non solo un singolo file o un'istantanea da un singolo commit.
git clone /path/to/repo
git clone git://url/of/repo
git clone http://url/of/repo
Se è necessario un file specifico da un ramo specifico da un repository Git remoto, il comando è:
git archive --remote=git://git.example.com/project.git refs/heads/mybranch path/to/myfile |tar xf -
Il resto può essere derivato dalla risposta di @ VonC:
Se hai bisogno di un file specifico dal ramo principale è:
git archive --remote=git://git.example.com/project.git HEAD path/to/myfile |tar xf -
Se hai bisogno di un file specifico da un tag è:
git archive --remote=git://git.example.com/project.git mytag path/to/myfile |tar xf -
Non vedo ciò che ha funzionato per me elencato qui, quindi includerò se qualcuno dovesse trovarsi nella mia situazione.
La mia situazione, ho un repository remoto di forse 10.000 file e ho bisogno di creare un file RPM per il mio sistema Linux. La build dell'RPM include un clone git di tutto. Tutto ciò di cui ho bisogno è un file per avviare la build RPM. Posso clonare l'intero albero dei sorgenti che fa quello di cui ho bisogno ma ci vogliono altri due minuti per scaricare tutti quei file quando tutto ciò di cui ho bisogno è uno. Ho provato a usare l'opzione di archivio git discussa e ho ottenuto "fatale: operazione non supportata dal protocollo". Sembra che devo abilitare una sorta di opzione di archiviazione sul server e il mio server è gestito da criminali burocratici che sembrano divertirsi a rendere difficile il completamento delle attività.
Quello che finalmente ho fatto è stato andare nell'interfaccia web per bitbucket e visualizzare il file di cui avevo bisogno. Ho fatto clic con il pulsante destro del mouse sul link per scaricare una copia non elaborata del file e selezionato "Copia collegamento" dal popup risultante. Non potevo semplicemente scaricare il file raw perché avevo bisogno di automatizzare le cose e non ho un'interfaccia del browser sul mio server Linux.
Per motivi di discussione, ciò ha portato all'URL:
https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest
Non ho potuto scaricare direttamente questo file dal repository bitbucket perché prima dovevo accedere. Dopo un po 'di ricerche, ho scoperto che funzionava: Su Linux:
echo "myUser:myPass123"| base64
bXlVc2VyOm15UGFzczEyMwo=
curl -H 'Authorization: Basic bXlVc2VyOm15UGFzczEyMwo=' 'https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest' > bar.spec
Questa combinazione mi ha permesso di scaricare l'unico file necessario per creare tutto il resto.
Sto aggiungendo questa risposta come alternativa al checkout formale o ad un'operazione locale simile. Supponendo che tu abbia accesso all'interfaccia web del tuo provider Git, potresti essere in grado di visualizzare direttamente qualsiasi file a un determinato commit desiderato. Ad esempio, su GitHub puoi usare qualcosa come:
https://github.com/hubotio/hubot/blob/ed25584f/src/adapter.coffee
Ecco ed25584f
i primi 8 caratteri dell'hash SHA-1 del commit di interesse, seguito dal percorso del file di origine.
Allo stesso modo, su Bitbucket possiamo provare:
https://bitbucket.org/cofarrell/stash-browse-code-plugin/src/06befe08
In questo caso, posizioniamo l'hash di commit alla fine dell'URL di origine.
Se devi solo scaricare il file, non è necessario effettuare il check-out con Git.
GitHub Mate è molto più semplice, è un'estensione di Chrome, ti consente di fare clic sull'icona del file per scaricarlo. anche open source
git
! =github
Se hai modificato una versione locale di un file e desideri ripristinare la versione originale mantenuta sul server centrale, questo può essere facilmente ottenuto usando Git Extensions .
Facile!