web-dev-qa-db-fra.com

Faites un "export git" (comme "svn export")?

Je me demandais s'il existe une bonne solution "d'exportation git" qui crée une copie d'un arbre sans le répertoire de référentiel _.git_. Je connais au moins trois méthodes:

  1. _git clone_ suivi de la suppression du répertoire de référentiel _.git_.
  2. git checkout-index fait allusion à cette fonctionnalité mais commence par "Il suffit de lire l'arbre souhaité dans l'index ...", ce que je ne sais pas trop comment faire.
  3. git-export est un script tiers qui effectue essentiellement un _git clone_ dans un emplacement temporaire, suivi de _rsync --exclude='.git'_ dans la destination finale.

Aucune de ces solutions ne me semble vraiment satisfaisante. Le plus proche de _svn export_ pourrait être l'option 1, car les deux exigent que le répertoire cible soit vide en premier. Mais l'option 2 semble encore meilleure, en supposant que je puisse comprendre ce que signifie lire un arbre dans l'index.

2281
Greg Hewgill

Le moyen le plus simple d'y parvenir est probablement git archive . Si vous avez vraiment besoin de l’arbre développé, vous pouvez faire quelque chose comme ceci.

_git archive master | tar -x -C /somewhere/else
_

La plupart du temps, j'ai besoin d'exporter quelque chose de git, je veux de toute façon une archive compressée, alors je fais quelque chose comme ça.

_git archive master | bzip2 >source-tree.tar.bz2
_

Archive Zip:

_git archive --format Zip --output /full/path/to/zipfile.Zip master 
_

git help archive pour plus de détails, c'est assez flexible.


Sachez que même si l’archive ne contient pas le répertoire .git, elle contiendra d’autres fichiers cachés spécifiques à git, tels que .gitignore, .gitattributes, etc. Si vous ne les voulez pas dans l’archive, assurez-vous utilisez l'attribut export-ignore dans un fichier .gitattributes et validez-le avant de créer votre archive. Lire plus ...


Remarque: Si vous souhaitez exporter l'index, la commande est

_git checkout-index -a -f --prefix=/destination/path/
_

(Voir réponse de Greg pour plus de détails)

2326
CB Bailey

J'ai découvert ce que l'option 2 signifie. A partir d'un référentiel, vous pouvez faire:

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

La barre oblique à la fin du chemin est importante, sinon les fichiers se trouveraient dans/destination avec un préfixe 'chemin'.

Comme dans une situation normale, l'index contient le contenu du référentiel, il n'y a rien de spécial à faire pour "lire l'arborescence souhaitée dans l'index". C'est déjà là.

L’indicateur -a est requis pour extraire tous les fichiers de l’index (je ne sais pas ce que signifie omettre cet indicateur dans cette situation, car il ne fait pas ce que je veux). L'indicateur -f force le remplacement des fichiers existants dans la sortie, ce que cette commande ne fait normalement pas.

Cela semble être le genre d '"exportation géniale" que je cherchais.

314
Greg Hewgill

git archive fonctionne également avec un référentiel distant.

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

Pour exporter un chemin particulier dans le référentiel, ajoutez autant de chemins que vous le souhaitez comme dernier argument de git, par exemple:

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

enter image description here

Un cas particulier à répondre si le référentiel est hébergé sur GitHub.

Il suffit d'utiliser svn export.

Autant que je sache, Github n'autorise pas archive --remote. Bien que GitHub soit svn compatible et qu'ils aient tous les dépôts Git svn accessibles, vous pouvez simplement utiliser svn export comme vous le feriez normalement, avec quelques ajustements à votre URL GitHub.

Par exemple, pour exporter un référentiel entier, notez comment trunk dans l'URL remplace master (ou quelle que soit la la branche du projet HEAD est définie sur ):

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

Et vous pouvez exporter un seul fichier ou même un certain chemin ou dossier:

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

Exemple avec bibliothèque JavaScript jQuery

La branche HEAD ou la branche principale sera disponible à l'aide de trunk:

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

Les branches non -HEAD seront accessibles sous /branches/:

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

Toutes les balises sous /tags/ de la même manière:

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

De la Manuel Git :

Utiliser git-checkout-index pour "exporter un arbre entier"

La capacité prefix rend fondamentalement trivial l’utilisation de git-checkout-index en tant que fonction "export as tree". Il suffit de lire l’arbre souhaité dans l’index et de faire:

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

40
jperras

J'ai écrit un simple wrapper autour de git-checkout-index que vous pouvez utiliser comme ceci:

git export ~/the/destination/dir

Si le répertoire de destination existe déjà, vous devrez ajouter -f ou --force.

L'installation est simple. déposez simplement le script quelque part dans votre PATH et assurez-vous qu'il est exécutable.

Le dépôt github pour git-export

38
Daniel Schierbeck

Il semble que ce soit moins un problème avec Git que SVN. Git ne place qu'un dossier .git à la racine du référentiel, alors que SVN place un dossier .svn dans chaque sous-répertoire. Donc, "svn export" évite la magie récursive en ligne de commande, alors qu'avec Git, la récursivité n'est pas nécessaire.

36
kostmo

L'équivalent de

svn export . otherpath

dans un dépôt existant est

git archive branchname | (cd otherpath; tar x)

L'équivalent de

svn export url otherpath

est

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

Si vous n'excluez pas de fichiers avec .gitattributesexport-ignore, essayez alors git checkout

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

-F
Lorsque vous extrayez des chemins de l'index, n'échouez pas sur les entrées non fusionnées; au lieu de cela, les entrées non fusionnées sont ignorées.

et

-q
Évitez les commentaires

De plus, vous pouvez obtenir n'importe quelle branche ou balise ou une révision de validation spécifique, comme dans SVN, en ajoutant simplement SHA1 (SHA1 dans Git est l'équivalent du numéro de révision dans SVN).

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

Le /path/to/checkout/ doit être vide, Git ne supprimera aucun fichier, mais écrasera les fichiers portant le même nom sans aucun avertissement.

UPDATE: pour éviter le problème décapité ou pour laisser intact le référentiel de travail lors de l'utilisation de la commande pour l'exportation avec des balises, des branches ou SHA1, vous devez ajouter -- ./ à la fin.

Le double tiret -- indique à git que tout ce qui suit les tirets sont des chemins ou des fichiers et, dans ce cas également, indique à git checkout de ne pas modifier le HEAD.

Exemples:

Cette commande obtiendra uniquement le répertoire libs et également le fichier readme.txt de ce dernier exactement

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

Cela créera (écrasera) my_file_2_behind_HEAD.txt deux commits derrière la tête 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

Pour exporter une autre branche

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

Notez que ./ est relatif à la racine du référentiel

22
user5286776117878

J'utilise beaucoup les sous-modules git. Celui-ci fonctionne pour moi:

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

J'ai fréquemment consulté cette page lorsque je cherchais un moyen d'exporter un référentiel git. Ma réponse à cette question considère trois propriétés que svn export a par conception par rapport à git, puisque svn suit une approche de référentiel centralisé:

  • Il minimise le trafic vers un emplacement de référentiel distant en n'exportant pas toutes les révisions.
  • Il n'inclut pas de méta-information dans le répertoire d'exportation
  • L’exportation d’une branche donnée à l’aide de svn est réalisée en spécifiant le chemin approprié

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

Lors de la création d'une version donnée, il est utile de cloner une branche stable, comme par exemple --branch stable ou --branch release/0.9.

19
Lars Schillingmann

Cela va copier tout le contenu, moins les fichiers .dot. J'utilise cela pour exporter des projets clonés git dans le dépôt git de mon application Web sans les éléments .git.

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

Plain Old Bash fonctionne tout simplement génial :)

16
Harmon

Aussi simple que clone, supprimez le dossier .git:

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

13
teleme.io

Oui, this est une commande propre et ordonnée pour archiver votre code sans aucune inclusion de git dans l'archive et il est bon de le faire circuler sans se soucier de l'historique de ses validations.

git archive --format Zip --output /full/path/to/zipfile.Zip master 
11
zeeawan

Je veux juste souligner que dans le cas où vous êtes

  1. exporter un sous-dossier du référentiel (c'est ainsi que j'avais l'habitude d'utiliser la fonctionnalité d'exportation SVN)
  2. accepte de tout copier de ce dossier vers la destination de déploiement
  3. et puisque vous avez déjà une copie de tout le référentiel en place.

Ensuite, vous pouvez simplement utiliser cp foo [destination] à la place du git-archive master foo | -x -C [destination] mentionné.

10
dkinzer

Pour les utilisateurs de GitHub, la méthode git archive --remote ne fonctionnera pas directement, car l'URL d'exportation est éphémère . Vous devez demander l'URL à GitHub, puis télécharger cette URL. curl facilite les choses:

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

Cela vous donnera le code exporté dans un répertoire local. Exemple:

$ 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

Modifier
Si vous souhaitez que le code soit placé dans un répertoire spécifique existant (plutôt que dans le répertoire aléatoire de github):

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

Vous pouvez archiver un dépôt distant à n'importe quel commit sous forme de fichier Zip.

git archive --format=Zip --output=archive.Zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT
9
orkoden

Si vous voulez quelque chose qui fonctionne avec des sous-modules, cela peut valoir le coup.

Remarque:

  • MASTER_DIR = une commande avec vos sous-modules empruntés également
  • DEST_DIR = où cette exportation aboutira
  • Si vous avez rsync, je pense que vous seriez capable de faire la même chose avec encore moins de mal de balle.

Hypothèses:

  • Vous devez l'exécuter à partir du répertoire parent de MASTER_DIR (c'est-à-dire à partir de MASTER_DIR cd ..).
  • DEST_DIR est supposé avoir été créé. C'est assez facile à modifier pour inclure la création d'un DEST_DIR si vous vouliez

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

8
Rob Jensen

Bash-implémentation de git-export.

J'ai segmenté les processus de création et de suppression de fichiers .empty sur leur propre fonction, dans le but de les réutiliser dans l'implémentation 'git-archive' (sera publié ultérieurement).

J'ai également ajouté le fichier '.gitattributes' au processus afin de supprimer les fichiers inutiles du dossier d'exportation cible. Inclusion de verbosité dans le processus tout en rendant la fonction 'git-export' plus efficace.

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

Sortie:

$ git-export /tmp/rel-1.0.0

Ajout de fichiers '.empty' dans un ou plusieurs dossiers vides: ... terminé.

Composant (s) d'index de check-out: ... terminé.

Réinitialisation de HEAD et index: ... done.

Purging Git-Specific composant (s): ...

'/tmp/rel-1.0.0/{.buildpath}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{.project}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{.gitignore}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{.git}' fichiers ... terminé. '

'/tmp/rel-1.0.0/{.gitattributes}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{*.mno}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{*~}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{.*~}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{*.swp}' fichiers ... terminé. '

'/tmp/rel-1.0.0/{*.swo}' fichiers ... terminé. '

'/tmp/rel-1.0.0/{.DS_Store}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{.settings}' fichiers ... réalisés. '

'/tmp/rel-1.0.0/{.empty}' fichiers ... réalisés. '

terminé.

Archivage du (des) composant (s) extrait (s): ... terminé.

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

J'ai maintenant intégré la fonctionnalité 'git archive' dans un processus unique utilisant la fonction 'create_empty' et d'autres fonctionnalités.

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

Ma préférence serait en fait d'avoir une cible dist dans votre Makefile (ou un autre système de construction) qui exporte une archive distribuable de votre code (.tar.bz2, .Zip, .jar ou ce qui est approprié ). Si vous utilisez GNU autotools ou les systèmes MakeMaker de Perl, je pense que cela existe pour vous automatiquement. Sinon, je recommande fortement de l'ajouter.

ETA (2012-09-06): Ouah, critiques négatives. Je crois toujours qu'il est préférable de construire vos distributions avec vos outils de construction plutôt qu'avec votre outil de contrôle de code source. Je crois en la construction d'artefacts avec des outils de construction. Dans mon travail actuel, notre produit principal est construit avec une cible de fourmi. Nous sommes en train de basculer les systèmes de contrôle du code source, et la présence de cette cible ant signifie une migration de moins en cas de problème.

6
skiphoppy

Cela copiera les fichiers dans une plage de commits (C à G) dans un fichier tar. Remarque: seuls les fichiers validés seront récupérés. Pas le référentiel entier. Légèrement modifié à partir de ici

Exemple d'historique de validation

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

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

Page de manuel de git-diff-tree

-r -> recurse en sous-arbres

--no-commit-id -> git diff-tree génère une ligne avec l'ID de validation, le cas échéant. Cet indicateur a supprimé la sortie de l'ID de validation.

--name-only -> Affiche uniquement les noms des fichiers modifiés.

--diff-filter = ACMRT -> Sélectionnez uniquement ces fichiers. Voir ici pour la liste complète des fichiers

C..G -> Fichiers dans cette gamme de commits

C ~ -> Inclure les fichiers de Commit C. Pas seulement les fichiers depuis Commit C.

| xargs tar -rf myTarFile -> sorties vers tar

6
Fuyu Persimmon

J'avais besoin de cela pour un script de déploiement et je ne pouvais utiliser aucune des approches mentionnées ci-dessus. Au lieu de cela, j'ai trouvé une solution différente:

#!/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
4
troelskn

Si je comprends bien la question, il s’agit plus de télécharger un certain état du serveur, sans historique, et sans les données d’autres branches, plutôt que d’extraire un état d’un référentiel local (comme beaucoup de réponses le font ici).

Cela peut être fait comme ça:

git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
  • --single-branch est disponible depuis Git 1.7.10 (avril 2012).
  • --depth est (était?) apparemment défectueux, mais dans le cas d'une exportation, les problèmes mentionnés ne devraient pas avoir d'importance.
4
Ondra Žižka

Pour le faire facilement, il s’agit d’une fonction pour .bash_profile, elle décompresse directement l’archive sur l’emplacement actuel, configurez d’abord votre [url: chemin] habituel. REMARQUE: Avec cette fonction, vous évitez les opérations de clonage, elles sont directement obtenues du référentiel distant.

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 ​​pour .gitconfig, même configuration requise (TAKE CARE exécutant la commande dans les projets .git, il saute TOUJOURS au répertoire de base précédemment comme indiqué ici , jusqu'à ce que ce soit corrigé, je préfère personnellement la fonction

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

Je pense que le message de @ Aredridel était le plus proche, mais il y a un peu plus que cela - je vais donc l'ajouter ici; la chose est, dans svn, si vous êtes dans un sous-dossier d'un dépôt, et vous faites:

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

alors svn exportera tous les fichiers sous contrôle de révision (ils pourraient également avoir un statut récemment ajouté; ou modifié) - et si vous avez d'autres "fichiers indésirables" dans ce répertoire (et je ne compte pas en faire partie .svn sous-dossiers ici, mais des éléments visibles tels que .o fichiers), il ne sera pas exporté; seuls les fichiers enregistrés par le référentiel SVN seront exportés. Pour moi, une bonne chose est que cette exportation inclut également les fichiers avec des modifications locales qui n'ont pas encore été ; et une autre bonne chose est que les horodatages des fichiers exportés sont les mêmes que ceux d'origine. Ou, comme le dit svn help export:

  1. Exporte une arborescence de répertoire vierge de la copie de travail spécifiée par PATH1, à la révision REV si elle est fournie, sinon à WORKING, dans PATH2. ... Si REV n'est pas spécifié, toutes les modifications locales seront préservées. Les fichiers non sous contrôle de version ne seront pas copiés.

Pour réaliser que git ne conservera pas les horodatages, comparez le résultat de ces commandes (dans un sous-dossier d'un repo git de votre choix):

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

... et:

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

... et dans tous les cas, je remarque que git archive fait en sorte que tous les horodatages du fichier archivé soient identiques! git help archive dit:

git archive se comporte différemment lorsqu'un identifiant d'arbre est attribué à un identifiant de validation ou un identifiant de balise. Dans le premier cas, l'heure actuelle est utilisée comme heure de modification de chaque fichier de l'archive. Dans ce dernier cas, l'heure de validation telle qu'elle est enregistrée dans l'objet de validation référencé est utilisée à la place.

... mais apparemment les deux cas définissent "l'heure de modification de chaque fichier "; Ainsi pas en préservant les horodatages réels de ces fichiers!

Donc, afin de préserver également les horodatages, voici un script bash, qui est en réalité un "one-liner", bien qu'un peu compliqué - il est affiché en dessous sur plusieurs lignes:

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

Notez qu'il est supposé que vous exportez le contenu dans le répertoire "courant" (ci-dessus, /media/disk/git_svn/subdir) - et que la destination dans laquelle vous exportez est placée de manière peu commode, mais dans l'environnement DEST variable. Notez cela avec ce script; vous devez créer vous-même le répertoire DEST manuellement avant d'exécuter le script ci-dessus.

Une fois le script exécuté, vous devriez pouvoir comparer:

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

... et, espérons-le, voir les mêmes horodatages (pour les fichiers sous contrôle de version).

J'espère que ça aide quelqu'un,
À votre santé!

3
sdaau

De loin le moyen le plus simple que j'ai vu de le faire (et fonctionne aussi sur Windows) est git bundle:

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

Voir cette réponse pour plus de détails: Comment puis-je copier mon référentiel git de ma machine Windows sur une machine Linux via un lecteur USB?

3
B T

J'ai une autre solution qui fonctionne bien si vous avez une copie locale du référentiel sur la machine sur laquelle vous souhaitez créer l'exportation. Dans ce cas, déplacez-vous vers ce répertoire de référentiel et entrez la commande suivante:

GIT_WORK_TREE=outputdirectory git checkout -f

Ceci est particulièrement utile si vous gérez un site Web avec un référentiel git et souhaitez extraire une version propre dans /var/www/. Dans ce cas, ajoutez cette commande dans un script .git/hooks/post-receive (hooks/post-receive sur un référentiel nu, ce qui est plus approprié dans cette situation).

3
Tom

une exportation git vers une archive Zip tout en ajoutant un préfixe (par exemple, un nom de répertoire):

git archive master --prefix=directoryWithinZip/  --format=Zip -o out.Zip
3
DomTomCat

Si vous avez également besoin de sous-modules, cela devrait faire l'affaire: https://github.com/meitar/git-archive-all.sh/wiki

2
Brandon

j'ai la fonction d'utilitaire suivante dans mon fichier .bashrc: il crée une archive de la branche actuelle dans un référentiel 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
}
1
MichaelMoser

L'option 1 ne semble pas trop efficace. Que se passe-t-il s'il n'y a pas d'espace dans le client pour faire un clone et , puis supprimer le dossier .git?

Aujourd'hui, je me suis retrouvé à essayer de le faire, le client étant un Raspberry Pi avec presque aucun espace. De plus, je souhaite également exclure certains dossiers lourds du référentiel.

L'option 2 et les autres réponses apportées ici n'aident en rien ce scénario. Ni git archive (car il est nécessaire de valider un fichier .gitattributes et je ne souhaite pas enregistrer cette exclusion dans le référentiel).

Ici, je partage ma solution, similaire à l'option 3, mais sans la nécessité de git clone:

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

Changer la ligne rsync pour une ligne équivalente à compresser fonctionnera également comme un git archive mais avec une sorte d’option d’exclusion (comme demandé ici ).

1
alexis