Domanda

Mi chiedevo se esiste una buona "quotazione git" " soluzione che crea una copia di un albero senza la directory del repository .git . Esistono almeno tre metodi che conosco:

  1. git clone seguito dalla rimozione della directory del repository .git .
  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 esegue un git clone in una posizione temporanea seguita da rsync --exclude = '. git' nella destinazione finale.

Nessuna di queste soluzioni mi sembra davvero soddisfacente. La più vicina a svn export potrebbe essere l'opzione 1, poiché entrambe richiedono che la directory di destinazione sia vuota per prima. Ma l'opzione 2 sembra ancora migliore, supponendo che riesca a capire cosa significhi leggere un albero nell'indice.

È stato utile?

Soluzione

Probabilmente il modo più semplice per raggiungere questo obiettivo è con git archive . Se hai davvero bisogno solo dell'albero espanso, puoi fare qualcosa del genere.

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

Il più delle volte ho bisogno di 'esportare' qualcosa da Git, voglio comunque un archivio compresso, quindi faccio qualcosa del genere.

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 conterrà la directory .git, conterrà comunque altri file specifici di git nascosti come .gitignore, .gitattributes, ecc. Se non li desideri nell'archivio, assicurati di utilizzare l'attributo export-ignore in un file .gitattributes e commettilo prima di fare il tuo archivio. Leggi di più ...


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

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

(Vedi risposta di Greg per maggiori dettagli)

Altri suggerimenti

Ho scoperto 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, in caso contrario i file saranno in / destinazione con un prefisso "percorso".

Dato che in una situazione normale l'indice contiene i contenuti del repository, non c'è niente di speciale da fare per "leggere l'albero desiderato nell'indice". È già lì.

Il flag -a è necessario per estrarre tutti i file nell'indice (non sono sicuro di cosa significhi omettere questo flag in questa situazione, dal momento che non fa quello che voglio ). Il flag -f forza la sovrascrittura di qualsiasi file esistente nell'output, cosa che normalmente non viene eseguita da questo comando.

Questo sembra essere il tipo di " git export " 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, aggiungere tutti i percorsi desiderati come ultimo argomento da git, ad es .:

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

inserisci qui la descrizione dell'immagine

Una risposta a un caso speciale se l'archivio è ospitato su GitHub.

Usa svn export .

Per quanto ne so, Github non consente archive --remote . Sebbene GitHub sia svn compatibile e hanno tutti i repository git svn accessibile in modo da poter usare svn export come faresti normalmente con alcune modifiche al tuo URL GitHub.

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

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

E puoi 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 Libreria JavaScript jQuery

Il ramo HEAD o master sarà disponibile utilizzando trunk :

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

I rami non HEAD saranno accessibili in / rami / :

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

Tutti i tag in / tags / nello stesso modo:

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

Dal Manuale Git :

Uso di git-checkout-index per " esportare un intero albero "

L'abilità del prefisso in pratica rende banale usare git-checkout-index come "esportazione come albero" funzione. Basta leggere l'albero desiderato nell'indice e fare:

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

Ho scritto un semplice wrapper attorno a 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; rilascia lo script da qualche parte nel tuo PATH e assicurati che sia eseguibile.

Il repository github per git-export

Sembra che questo sia un problema minore con Git rispetto a SVN. Git inserisce solo una cartella .git nella radice 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)

Se non stai escludendo i file con .gitattributes export-ignore allora prova git checkout

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

-f
  Quando si verificano i percorsi dall'indice, non fallire in caso di fusione   inserimenti; invece, le voci non unite vengono ignorate.

e

  

q
  Evita verbose

Inoltre puoi ottenere qualsiasi Branch o Tag o da una specifica Revisione Commit come in SVN semplicemente aggiungendo 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 eliminerà alcun file, ma sovrascriverà i file con lo stesso nome senza alcun preavviso

UPDATE: Per evitare il problema decapitato o per lasciare intatto il repository funzionante quando si utilizza il checkout per l'esportazione 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 HEAD

Esempi:

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

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

Uso ampiamente git-submodules. Questo funziona per me:

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

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

  • Riduce al minimo il traffico verso una posizione del repository remoto non esportando tutte le revisioni
  • Non include meta informazioni nella directory di esportazione
  • L'esportazione di un determinato 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 crea una determinata versione è utile clonare un ramo stabile come ad esempio --branch stable o --branch release / 0.9 .

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

  

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

Semplicemente il vecchio bash funziona alla grande :)

Semplice come clone, quindi eliminare la cartella .git:

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

Sì, questo è un comando pulito e ordinato per archiviare il codice senza alcuna inclusione git nell'archivio ed è buono passare senza preoccuparsi di alcuna cronologia di commit git.

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

Voglio solo sottolineare che nel caso in cui tu sia

  1. esportando una sottocartella del repository (è così che utilizzavo la funzione di esportazione SVN)
  2. sono d'accordo con la copia di tutto da quella cartella alla destinazione di distribuzione
  3. e poiché hai già una copia dell'intero repository in atto.

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

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 tale URL. curl semplifica:

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

Modifica
Se vuoi che il codice sia inserito in una specifica directory esistente (piuttosto che quella casuale da github):

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

Puoi archiviare un repository remoto in qualsiasi commit come file zip.

git archive --format=zip --output=archive.zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT

Implementazione bash di git-export.

Ho segmentato i processi di creazione e rimozione di file .empty in base alla loro stessa funzione, con lo scopo di riutilizzarli nell'implementazione di "git-archive" (verrà pubblicato più avanti).

Ho anche aggiunto il file '.gitattributes' al processo per rimuovere i file non desiderati dalla cartella di esportazione di destinazione. È stata inclusa la verbosità del processo rendendo più efficiente la funzione "git-export".

empty_file = " .empty " ;;

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;
  }
  

Output:

     

$ git-export /tmp/rel-1.0.0

     

Aggiunta di file '.empty' a cartelle vuote: ... fatto.

     

Componenti dell'indice di check-out: ... fatto.

     

Ripristino di HEAD e Index: ... fatto.

     

Eliminazione dei componenti specifici di Git: ...

     

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

     

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

     

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

     

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

     

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

     

'/tmp/rel-1.0.0/{*.mno}' file ... fatto. '

     

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

     

'/tmp/rel-1.0.0/{.*~}' file ... fatto. '

     

'/tmp/rel-1.0.0/{*.swp}' file ... fatto. '

     

'/tmp/rel-1.0.0/{*.swo}' file ... fatto. '

     

File '/tmp/rel-1.0.0/{.DS_Store}' ... fatto. '

     

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

     

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

     

fatto.

     

Archiviazione dei componenti estratti: ... fatto.

     

-rw-r - r-- 1 rotella admin 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
# e.g.: 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 di provare.

Nota:

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

Ipotesi:

  • È necessario eseguirlo dalla directory principale di MASTER_DIR (ovvero da MASTER_DIR cd ..)
  • Si presume che DEST_DIR sia stato creato. È abbastanza facile da modificare per includere la creazione di un DEST_DIR se si desidera
  

cd MASTER_DIR & amp; & amp; tar -zcvf ../DEST_DIR/export.tar.gz --exclude = '. git *'   . & Amp; & amp; cd ../DEST_DIR/ & amp; & amp; tar xvfz export.tar.gz & amp; & amp; rm export.tar.gz

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

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

Questo copierà i file in un intervallo di commit (da C a G) in un file tar. Nota: questo consentirà solo il commit dei file. Non l'intero repository. Leggermente modificato da Here

Esempio di commit della cronologia

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

git-diff-tree Pagina del manuale

-r - > ricorrere agli alberi secondari

--no-commit-id - > git diff-tree genera una riga con l'ID commit quando applicabile. Questo flag ha soppresso l'output dell'ID commit.

- solo nome - > 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 - > output in tar

Ne avevo bisogno per uno script deploy e non potevo usare nessuno degli approcci sopra menzionati. Invece ho trovato una soluzione diversa:

#!/bin/sh
[ $# -eq 2 ] || echo "USAGE <*> 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 in modo semplice, questa è una funzione per .bash_profile, decomprime direttamente l'archivio nella posizione corrente, configura prima il tuo solito [url: percorso]. 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 ??per .gitconfig, stessa configurazione richiesta (PRENDI CURA eseguendo il comando all'interno di progetti .git, salta SEMPRE alla directory di base precedentemente come detto qui , fino a quando questo non viene risolto preferisco personalmente la funzione

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' -

Quando capisco la domanda, si tratta più di scaricare solo un certo stato dal server, senza cronologia e senza dati di altri rami, piuttosto che estrarre uno stato da un repository locale (come fanno molte risposte qui).

Questo può essere fatto in questo modo:

git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
  • --single-branch è disponibile da Git 1.7.10 (aprile 2012).
  • --depth è (era?) secondo quanto riferito difettoso, ma per il caso di un'esportazione, le questioni menzionate non dovrebbero avere importanza.

Penso che il post di @Aredridel fosse il più vicino, ma c'è un po 'di più in questo - quindi aggiungerò questo Qui; il fatto è, in svn , se ti trovi in ??una sottocartella di un repository, e lo fai:

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

quindi svn esporterà tutti i file che sono sotto controllo di revisione (avrebbero potuto anche essere aggiunti di recente; o stato modificato) - e se hai altri " junk " in quella directory (e non sto contando le sottocartelle .svn qui, ma cose visibili come i file .o ), non sarà esportato ; verranno esportati solo i file registrati dal repository SVN. Per me, una cosa bella è che questa esportazione include anche file con modifiche locali che non sono ancora state impegnate per non ; e un'altra cosa carina è che i timestamp dei file esportati sono gli stessi di quelli originali. Oppure, come dice svn help export :

  
      
  1. Esporta un albero di directory pulito dalla copia di lavoro specificata da   PERCORSO1, alla revisione REV se viene fornito, altrimenti in WORKING, in   PATH2. ... Se non viene specificato REV, tutto locale   le modifiche verranno conservate. I file non sotto controllo della versione lo faranno   non essere copiato.
  2.   

Per capire che git non manterrà i timestamp, confronta l'output di questi comandi (in una sottocartella di un repository git di tua scelta):

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

... e:

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

... e, in ogni caso, noto che git archive fa sì che tutti i timestamp del file archiviato siano gli stessi! git help archive dice:

  

git archive si comporta diversamente quando viene assegnato un ID albero rispetto a quando viene assegnato un ID commit o ID tag. Nel primo caso il   l'ora corrente viene utilizzata come ora di modifica di ciascun file nell'archivio. In quest'ultimo caso, il tempo di commit è stato registrato   nell'oggetto commit di riferimento viene invece utilizzato.

... ma apparentemente entrambi i casi impostano il tempo di modifica di ogni file " ;; quindi non preservando i timestamp effettivi di quei file!

Quindi, al fine di preservare anche i timestamp, ecco uno script bash , che in realtà è uno script "one-liner", sebbene un po 'complicato - quindi sotto è pubblicato in più righe:

/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 \
)

Tieni presente che si presume che tu stia esportando i contenuti in " corrente " directory (sopra, / media / disk / git_svn / subdir ) - e la destinazione in cui stai esportando è posizionata in qualche modo in modo inopportuno, ma è nella variabile di ambiente DEST . Si noti che con questo script; è necessario creare manualmente la directory DEST prima di eseguire lo script precedente.

Dopo aver eseguito lo script, dovresti essere in grado di confrontare:

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

... e speriamo di vedere gli stessi timestamp (per quei file che erano sotto il controllo della versione).

Spero che questo aiuti qualcuno,
Cheers!

Di gran lunga il modo più semplice che ho visto per farlo (e funziona anche su Windows) è git bundle :

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

Vedi questa risposta per maggiori dettagli: Come posso copiare il mio repository git dal mio computer Windows su un computer Linux tramite unità USB?

Ho un'altra soluzione che funziona benissimo se hai una copia locale del repository sul computer in cui desideri creare l'esportazione. In questo caso, passare a questa directory del repository e immettere questo comando:

GIT_WORK_TREE = check-out git checkout -f

Ciò è particolarmente utile se gestisci un sito Web con un repository git e desideri effettuare il checkout di una versione pulita in / var / www / . In questo caso, aggiungi questo comando in uno script .git / hooks / post-recezione ( ganci / post-ricezione su un repository nudo, che è più adatto in questa situazione)

un'esportazione git in un archivio zip durante l'aggiunta di un prefisso (ad esempio il nome della directory):

git archive master --prefix=directoryWithinZip/  --format=zip -o out.zip

Se hai bisogno anche di sottomoduli, questo dovrebbe fare il trucco: https: / /github.com/meitar/git-archive-all.sh/wiki

Ho la seguente funzione di utilità nel mio file .bashrc: crea un archivio del ramo corrente in un repository git.

function garchive()
{
  if [[ "x$1" == "x-h" || "x$1" == "x" ]]; then
    cat <<EOF
Usage: garchive <archive-name>
create zip archive of the current branch into <archive-name>
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
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top