Fai un “git export” (come “svn export”)?

Mi sono chiesto se esiste una buona soluzione “git export” che crea una copia di un albero senza la directory .git repository. Ci sono almeno tre metodi che conosco:

  1. git clone seguito dalla rimozione della directory .git repository.
  2. git checkout-index allude a questa funzionalità ma inizia con “Basta leggere l’albero desiderato nell’indice …” che non sono del tutto sicuro di come fare.
  3. git-export è uno script di terze parti che essenzialmente fa un git clone in una posizione temporanea seguito da rsync --exclude='.git' nella destinazione finale.

Nessuna di queste soluzioni mi sembra davvero soddisfacente. Il più vicino a svn export potrebbe essere l’opzione 1, perché entrambi richiedono che la directory di destinazione sia vuota per prima. Ma l’opzione 2 sembra ancora migliore, assumendo che io possa capire cosa significa leggere un albero nell’indice.

Probabilmente il modo più semplice per ottenere questo è con git archive . Se hai davvero bisogno solo dell’albero espanso puoi fare qualcosa di simile.

 git archive master | tar -x -C /somewhere/else 

La maggior parte delle volte che ho bisogno di “esportare” qualcosa da git, voglio comunque un archivio compresso, quindi faccio qualcosa di simile.

 git archive master | bzip2 >source-tree.tar.bz2 

Archivio ZIP:

 git archive --format zip --output /full/path/to/zipfile.zip master 

git help archive per maggiori dettagli, è abbastanza flessibile.


Tieni presente che anche se l’archivio non contiene la directory .git, tuttavia, contiene altri file specifici di git nascosti come .gitignore, .gitattributes, ecc. Se non li vuoi nell’archivio, assicurati di usa l’attributo export-ignore in un file .gitattributes e confermalo prima di fare l’archivio. Leggi di più…


Nota: se sei interessato ad esportare l’indice, il comando è

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

(Vedi la risposta di Greg per maggiori dettagli)

Ho scoperto che cosa significa l’opzione 2. Da un repository, puoi fare:

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

La barra alla fine del percorso è importante, altrimenti i file saranno in / destinazione con un prefisso ‘percorso’.

Poiché in una situazione normale l’indice contiene il contenuto del repository, non c’è nulla di speciale da fare per “leggere l’albero desiderato nell’indice”. È già lì.

Il flag -a è necessario per controllare tutti i file nell’indice (non sono sicuro di cosa voglia dire omettere questo flag in questa situazione, dato che non fa quello che voglio). Il flag -f forza la sovrascrittura di eventuali file esistenti nell’output, cosa che normalmente questo comando non esegue.

Questo sembra essere il tipo di “esportazione di git” che stavo cercando.

git archive funziona anche con repository remoto.

 git archive --format=tar \ --remote=ssh://remote_server/remote_repository master | tar -xf - 

Per esportare un particolare percorso all’interno del repository, aggiungi tutti i percorsi che desideri come ultimo argomento per git, ad esempio:

 git archive --format=tar \ --remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv 

inserisci la descrizione dell'immagine qui

Una risposta caso speciale se il repository è ospitato su GitHub.

Basta usare svn export .

Per quanto ne so, Github non consente l’ archive --remote . Anche se GitHub è compatibile con svn e hanno tutti i git repos svn accessibili in modo che tu possa semplicemente usare svn export come faresti normalmente con qualche aggiustamento al tuo URL di GitHub.

Ad esempio, per esportare un intero repository, notare come il trunk nell’URL sostituisce il master (o qualunque sia il ramo HEAD del progetto impostato su ):

 svn export https://github.com/username/repo-name/trunk/ 

Ed è ansible esportare un singolo file o anche un determinato percorso o cartella:

 svn export https://github.com/username/repo-name/trunk/src/lib/folder 

Esempio con jQuery JavaScript Library

Il ramo HEAD o il ramo master saranno disponibili utilizzando il trunk :

 svn ls https://github.com/jquery/jquery/trunk 

I rami non HEAD saranno accessibili sotto /branches/ :

 svn ls https://github.com/jquery/jquery/branches/2.1-stable 

Tutti i tag sotto /tags/ allo stesso modo:

 svn ls https://github.com/jquery/jquery/tags/2.1.3 

Dal manuale Git :

Usare git-checkout-index per “esportare un intero albero”

L’abilità prefisso rende fondamentalmente semplice usare git-checkout-index come una funzione “esporta come albero”. Basta leggere l’albero desiderato nell’indice e fare:

$ git checkout-index --prefix=git-export-dir/ -a

Ho scritto un semplice wrapper su git-checkout-index che puoi usare in questo modo:

 git export ~/the/destination/dir 

Se la directory di destinazione esiste già, dovrai aggiungere -f o --force .

L’installazione è semplice; basta trascinare lo script da qualche parte nel PATH e assicurarsi che sia eseguibile.

Il repository github per git-export

Sembra che questo sia meno un problema con Git che SVN. Git mette solo una cartella .git nella root del repository, mentre SVN inserisce una cartella .svn in ogni sottodirectory. Quindi “svn export” evita la magia ricorsiva della riga di comando, mentre con Git la ricorsione non è necessaria.

L’equivalente di

 svn export . otherpath 

all’interno di un repository esistente è

 git archive branchname | (cd otherpath; tar x) 

L’equivalente di

 svn export url otherpath 

è

 git archive --remote=url branchname | (cd otherpath; tar x) 

Uso ampiamente i sottomodelli git. Questo funziona per me:

 rsync -a ./FROM/ ./TO --exclude='.*' 

Se non si escludono i file con .gitattributes export-ignore provare con git checkout

 mkdir /path/to/checkout/ git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q 

-f
Durante il controllo dei percorsi dall’indice, non fallire in caso di voci non raggruppate; invece, le voci non raggruppate vengono ignorate.

e

-q
Evitare di verboso

Inoltre è ansible ottenere qualsiasi Branch o Tag o da una Revisione di commit specifica come in SVN aggiungendo semplicemente SHA1 (SHA1 in Git è l’equivalente del numero di revisione in SVN)

 mkdir /path/to/checkout/ git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./ 

Il /path/to/checkout/ deve essere vuoto, Git non cancellerà alcun file, ma sovrascriverà i file con lo stesso nome senza alcun avviso

AGGIORNAMENTO: Per evitare il problema della decapitazione o lasciare intatto il repository funzionante quando si usa il checkout per esportare con tag, rami o SHA1, è necessario aggiungere -- ./ alla fine

Il doppio trattino -- dice a git che tutto ciò che segue i trattini sono percorsi o file, e anche in questo caso dice a git checkout di non cambiare l’ HEAD

Esempi:

Questo comando otterrà solo la directory libs e anche il file readme.txt da quello esattamente commit

 git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt 

Questo creerà (sovrascrivi) my_file_2_behind_HEAD.txt due commit dietro la testa HEAD^2

 git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt 

Per ottenere l’esportazione di un altro ramo

 git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./ 

Si noti che ./ è relativo alla radice del repository

Questo copierà tutti i contenuti, meno i file .dot. Lo uso per esportare i progetti clonati di git nel repository git della mia app web senza i file .git.

cp -R ./path-to-git-repo / path / to / destination /

Plain old bash funziona semplicemente fantastico 🙂

Ho colpito frequentemente questa pagina quando cercavo un modo per esportare un repository git. La mia risposta a questa domanda considera tre proprietà che svn export ha rispetto a git, poiché svn segue un approccio di repository centralizzato:

  • Riduce al minimo il traffico verso un percorso di repository remoto non esportando tutte le revisioni
  • Non include le meta-informazioni nella directory di esportazione
  • L’esportazione di un certo ramo usando svn si ottiene specificando il percorso appropriato

     git clone --depth 1 --branch master git://git.somewhere destination_path rm -rf destination_path/.git 

Quando si costruisce un determinato rilascio è utile clonare un ramo stabile come ad esempio – --branch stable o --branch release/0.9 .

Semplice come clone, quindi elimina la cartella .git:

git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git

Voglio solo far notare che nel caso in cui lo sei

  1. esportando una sottocartella del repository (è così che usavo la funzione di esportazione SVN)
  2. OK con la copia di tutto da quella cartella alla destinazione di distribuzione
  3. e dal momento che hai già una copia dell’intero repository in atto.

Quindi puoi semplicemente usare cp foo [destination] invece del citato git-archive master foo | -x -C [destination] git-archive master foo | -x -C [destination] .

È ansible archiviare un repository remoto in qualsiasi commit come file zip.

 git archive --format=zip --output=archive.zip [email protected]:PROJECTNAME.git HASHOFGITCOMMIT 

Per gli utenti GitHub, il metodo git archive --remote non funzionerà direttamente, poiché l’URL di esportazione è effimero . Devi chiedere a GitHub l’URL, quindi scaricare l’URL. curl rende così facile:

 curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf - 

Questo ti darà il codice esportato in una directory locale. Esempio:

 $ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf - $ ls jpic-bashworks-34f4441/ break conf docs hack LICENSE mlog module mpd mtests os README.rst remote todo vcs vps wepcrack 

modificare
Se vuoi che il codice venga inserito in una directory specifica, esistente (anziché in quella casuale di github):

 curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \ tar xzC /path/you/want --strip 1 

Sì, questo è un comando pulito e pulito per archiviare il codice senza alcuna inclusione di git nell’archivio ed è utile per passare in rassegna senza preoccuparsi di alcuna cronologia di commit git.

 git archive --format zip --output /full/path/to/zipfile.zip master 

Bash-implementazione di git-export.

Ho segmentato i processi di creazione e rimozione di file .empty sulla propria funzione, con lo scopo di riutilizzarli nell’implementazione di ‘git-archive’ (verrà pubblicato in seguito).

Ho anche aggiunto il file “.gitattributes” al processo per rimuovere i file non desiderati dalla cartella di destinazione. Inclusione della verbosità del processo mentre si rende più efficiente la funzione ‘git-export’.

“Vuoto” empty_file =;

 function create_empty () { ## Processing path (target-dir): TRG_PATH="${1}"; ## Component(s): EXCLUDE_DIR=".git"; echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ..."; find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \; #echo "done."; ## Purging SRC/TRG_DIRs variable(s): unset TRG_PATH EMPTY_FILE EXCLUDE_DIR; return 0; } declare -a GIT_EXCLUDE; function load_exclude () { SRC_PATH="${1}"; ITEMS=0; while read LINE; do # echo -e "Line [${ITEMS}]: '${LINE%%\ *}'"; GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *}; done < ${SRC_PATH}/.gitattributes; GIT_EXCLUDE[${ITEMS}]="${EMPTY_FILE}"; ## Purging variable(s): unset SRC_PATH ITEMS; return 0; } function purge_empty () { ## Processing path (Source/Target-dir): SRC_PATH="${1}"; TRG_PATH="${2}"; echo -e "\nPurging Git-Specific component(s): ... "; find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \; for xRULE in ${GIT_EXCLUDE[@]}; do echo -en " '${TRG_PATH}/{${xRULE}}' files ... "; find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \; echo "done.'"; done; echo -e "done.\n" ## Purging SRC/TRG_PATHs variable(s): unset SRC_PATH; unset TRG_PATH; return 0; } function git-export () { TRG_DIR="${1}"; SRC_DIR="${2}"; if [ -z "${SRC_DIR}" ]; then SRC_DIR="${PWD}"; fi load_exclude "${SRC_DIR}"; ## Dynamically added '.empty' files to the Git-Structure: create_empty "${SRC_DIR}"; GIT_COMMIT="Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}"; git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}"; if [ "${?}" -eq 0 ]; then echo " done."; fi /bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}"; echo -en "\nChecking-Out Index component(s): ... "; git checkout-index --prefix=${TRG_DIR}/ -q -f -a ## Reset: --mixed = reset HEAD and index: if [ "${?}" -eq 0 ]; then echo "done."; echo -en "Resetting HEAD and Index: ... "; git reset --soft HEAD^; if [ "${?}" -eq 0 ]; then echo "done."; ## Purging Git-specific components and '.empty' files from Target-Dir: purge_empty "${SRC_DIR}" "${TRG_DIR}" else echo "failed."; fi ## Archiving exported-content: echo -en "Archiving Checked-Out component(s): ... "; if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR} echo "done."; ## Listing *.tgz file attributes: ## Warning: Un-TAR this file to a specific directory: ls -al ${TRG_DIR}.tgz else echo "failed."; fi ## Purgin all references to Un-Staged File(s): git reset HEAD; ## Purging SRC/TRG_DIRs variable(s): unset SRC_DIR; unset TRG_DIR; echo ""; return 0; } 

Produzione:

$ git-export /tmp/rel-1.0.0

Aggiunta di file ".empty" alle cartelle vuote: ... fatto.

Componente (i) dell'indice di controllo: ... fatto.

Reimpostazione di HEAD e Index: ... done.

Purging Component (s) specifico Git: ...

'/tmp/rel-1.0.0/{.buildpath}' files ... done. '

'/tmp/rel-1.0.0/{.project}' files ... done. '

'/tmp/rel-1.0.0/{.gitignore}' file ... fatto. '

'/tmp/rel-1.0.0/{.git}' files ... done. '

'/tmp/rel-1.0.0/{.gitattributes}' files ... done. '

'/tmp/rel-1.0.0/{*.mno}' files ... done. '

'/tmp/rel-1.0.0/{*~}' files ... done. '

'/tmp/rel-1.0.0/{.*~}' files ... done. '

'/tmp/rel-1.0.0/{*.swp}' files ... done. '

'/tmp/rel-1.0.0/{*.swo}' files ... done. '

'/tmp/rel-1.0.0/{.DS_Store}' files ... done. '

'/tmp/rel-1.0.0/{.settings}' files ... done. '

'/tmp/rel-1.0.0/{.empty}' files ... done. '

fatto.

Componente (i) archiviato (i) archiviato: ... fatto.

-rw-r - r-- 1 admin wheel 25445901 3 nov 12:57 /tmp/rel-1.0.0.tgz

Ora ho incorporato la funzionalità 'git archive' in un singolo processo che utilizza la funzione 'create_empty' e altre funzionalità.

 function git-archive () { PREFIX="${1}"; ## sudo mkdir -p ${PREFIX} REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`"; RELEASE="`echo "${2}"|awk -F: '{print $2}'`"; USER_PATH="${PWD}"; echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH"; ## Dynamically added '.empty' files to the Git-Structure: cd "${REPO_PATH}"; populate_empty .; echo -en "\n"; # git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0 # eg: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode OUTPUT_FILE="${USER_PATH}/${RELEASE}.tar.gz"; git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE} cd "${USER_PATH}"; if [[ "${3}" =~ [--explode] ]]; then if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE} fi ## Purging SRC/TRG_DIRs variable(s): unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE; return 0; } 

Se vuoi qualcosa che funzioni con i sottomoduli, questo potrebbe valere la pena.

Nota:

  • MASTER_DIR = checkout anche con i tuoi sottomoduli
  • DEST_DIR = dove finirà questa esportazione
  • Se hai rsync, penso che saresti in grado di fare la stessa cosa con un mal di palla ancora minore.

ipotesi:

  • È necessario eseguire questo dalla directory padre di MASTER_DIR (cioè da MASTER_DIR cd ..)
  • Si presume che DEST_DIR sia stato creato. Questo è piuttosto facile da modificare per includere la creazione di un DEST_DIR se lo si desidera

cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz –exclude = ‘. git *’. && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz

Questo copierà i file in un intervallo di commit (da C a G) in un file tar. Nota: questo otterrà solo i file commessi. Non l’intero repository. Leggermente modificato da Qui

Esempio Commit History

A -> B -> C -> D -> E -> F -> G -> H -> I

 git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar 

Pagina manuale di git-diff-tree

-r -> recurse in sub-trees

–no-commit-id -> git diff-tree restituisce una riga con l’ID di commit quando applicabile. Questo flag ha soppresso l’output dell’ID commit.

–name-only -> Mostra solo i nomi dei file modificati.

–diff-filter = ACMRT -> Seleziona solo questi file. Vedi qui per l’elenco completo dei file

C..G -> File in questo intervallo di commit

C ~ -> Includi file da Commit C. Non solo file da Commit C.

| xargs tar -rf myTarFile -> restituisce a tar

La mia preferenza sarebbe in realtà di avere un target dist nel tuo Makefile (o altro sistema di build) che esporta un archivio distribuibile del tuo codice (.tar.bz2, .zip, .jar, o qualunque cosa sia appropriata). Se si utilizza GNU autotools o sistemi MakeMaker di Perl, penso che questo esista automaticamente. In caso contrario, consiglio vivamente di aggiungerlo.

ETA (2012-09-06): Wow, duri downvotes. Credo ancora che sia meglio build le tue distribuzioni con i tuoi strumenti di compilazione piuttosto che con il tuo strumento di controllo del codice sorgente. Credo nella creazione di artefatti con strumenti di costruzione. Nel mio attuale lavoro, il nostro prodotto principale è costruito con un objective di formica. Siamo nel bel mezzo di cambiare i sistemi di controllo del codice sorgente e la presenza di questo objective di formica implica una seccatura nella migrazione.

Avevo bisogno di questo per uno script di implementazione e non potevo utilizzare nessuno degli approcci sopra citati. Invece ho trovato una soluzione diversa:

 #!/bin/sh [ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1 REPOSITORY=$1 DESTINATION=$2 TMPNAME="/tmp/$(basename $REPOSITORY).$$" git clone $REPOSITORY $TMPNAME rm -rf $TMPNAME/.git mkdir -p $DESTINATION cp -r $TMPNAME/* $DESTINATION rm -rf $TMPNAME 

Facendolo nel modo più semplice, questa è una funzione per .bash_profile, decomprime direttamente l’archivio sulla posizione corrente, configura innanzitutto il tuo solito [url: path]. NOTA: con questa funzione si evita l’operazione di clonazione, si ottiene direttamente dal repository remoto.

 gitss() { URL=[url:path] TMPFILE="`/bin/tempfile`" if [ "$1" = "" ]; then echo -e "Use: gitss repo [tree/commit]\n" return fi if [ "$2" = "" ]; then TREEISH="HEAD" else TREEISH="$2" fi echo "Getting $1/$TREEISH..." git archive --format=zip --remote=$URL/$1 $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n" rm $TMPFILE } 

Alias for .gitconfig, same configuration required (TAKE CARE executing the command inside .git projects, it ALWAYS jumps to the base dir previously as said here , until this is fixed I personally prefer the function

 ss = !env GIT_TMPFILE="`/bin/tempfile`" sh -c 'git archive --format=zip --remote=[url:path]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' - 

I think @Aredridel ‘s post was closest, but there’s a bit more to that – so I will add this here; the thing is, in svn , if you’re in a subfolder of a repo, and you do:

 /media/disk/repo_svn/subdir$ svn export . /media/disk2/repo_svn_B/subdir 

then svn will export all files that are under revision control (they could have also freshly Added; or Modified status) – and if you have other “junk” in that directory (and I’m not counting .svn subfolders here, but visible stuff like .o files), it will not be exported; only those files registered by the SVN repo will be exported. For me, one nice thing is that this export also includes files with local changes that have not been committed yet; and another nice thing is that the timestamps of the exported files are the same as the original ones. Or, as svn help export puts it:

  1. Exports a clean directory tree from the working copy specified by PATH1, at revision REV if it is given, otherwise at WORKING, into PATH2. … If REV is not specified, all local changes will be preserved. Files not under version control will not be copied.

To realize that git will not preserve the timestamps, compare the output of these commands (in a subfolder of a git repo of your choice):

 /media/disk/git_svn/subdir$ ls -la . 

… and:

 /media/disk/git_svn/subdir$ git archive --format=tar --prefix=junk/ HEAD | (tar -t -v --full-time -f -) 

… and I, in any case, notice that git archive causes all the timestamps of the archived file to be the same! git help archive says:

git archive behaves differently when given a tree ID versus when given a commit ID or tag ID. In the first case the current time is used as the modification time of each file in the archive. In the latter case the commit time as recorded in the referenced commit object is used instead.

… but apparently both cases set the “modification time of each file”; thereby not preserving the actual timestamps of those files!

So, in order to also preserve the timestamps, here is a bash script, which is actually a “one-liner”, albeit somewhat complicated – so below it is posted in multiple lines:

 /media/disk/git_svn/subdir$ git archive --format=tar master | (tar tf -) | (\ DEST="/media/diskC/tmp/subdirB"; \ CWD="$PWD"; \ while read line; do \ DN=$(dirname "$line"); BN=$(basename "$line"); \ SRD="$CWD"; TGD="$DEST"; \ if [ "$DN" != "." ]; then \ SRD="$SRD/$DN" ; TGD="$TGD/$DN" ; \ if [ ! -d "$TGD" ] ; then \ CMD="mkdir \"$TGD\"; touch -r \"$SRD\" \"$TGD\""; \ echo "$CMD"; \ eval "$CMD"; \ fi; \ fi; \ CMD="cp -a \"$SRD/$BN\" \"$TGD/\""; \ echo "$CMD"; \ eval "$CMD"; \ done \ ) 

Note that it is assumed that you’re exporting the contents in “current” directory (above, /media/disk/git_svn/subdir ) – and the destination you’re exporting into is somewhat inconveniently placed, but it is in DEST environment variable. Note that with this script; you must create the DEST directory manually yourself, before running the above script.

After the script is ran, you should be able to compare:

 ls -la /media/disk/git_svn/subdir ls -la /media/diskC/tmp/subdirB # DEST 

… and hopefully see the same timestamps (for those files that were under version control).

Hope this helps someone,
Saluti!

By far the easiest way i’ve seen to do it (and works on windows as well) is git bundle :

git bundle create /some/bundle/path.bundle --all

See this answer for more details: How can I copy my git repository from my windows machine to a linux machine via usb drive?

If you need submodules as well, this should do the trick: https://github.com/meitar/git-archive-all.sh/wiki

i have the following utility function in my .bashrc file: it creates an archive of the current branch in a git repository.

 function garchive() { if [[ "x$1" == "xh" || "x$1" == "x" ]]; then cat < create zip archive of the current branch into  EOF else local oname=$1 set -x local bname=$(git branch | grep -F "*" | sed -e 's#^*##') git archive --format zip --output ${oname} ${bname} set +x fi } 

The option 1 sounds not too efficient. What if there is no space in the client to do a clone and then remove the .git folder?

Today I found myself trying to do this, where the client is a Raspberry Pi with almost no space left. Furthermore, I also want to exclude some heavy folder from the repository.

Option 2 and others answers here do not help in this scenario. Neither git archive (because require to commit a .gitattributes file, and I don’t want to save this exclusion in the repository).

Here I share my solution, similar to option 3, but without the need of git clone :

 tmp=`mktemp` git ls-tree --name-only -r HEAD > $tmp rsync -avz --files-from=$tmp --exclude='fonts/*' . raspberry: 

Changing the rsync line for an equivalent line for compress will also work as a git archive but with a sort of exclusion option (as is asked here ).

I have another solution that works fine if you have a local copy of the repository on the machine where you would like to create the export. In this case move to this repository directory, and enter this command:

GIT_WORK_TREE=outputdirectory git checkout -f

This is particularly useful if you manage a website with a git repository and would like to checkout a clean version in /var/www/ . In this case, add thiscommand in a .git/hooks/post-receive script ( hooks/post-receive on a bare repository, which is more suitable in this situation)

As I understand the question, it it more about downloading just certain state from the server, without history, and without data of other branches, rather than extracting a state from a local repository (as many anwsers here do).

That can be done like this:

 git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \ && rm -rf repo/.git/ 
  • --single-branch is available since Git 1.7.10 (April 2012).
  • --depth is (was?) reportedly faulty, but for the case of an export, the mentioned issues should not matter.