rsync exclure selon .gitignore & .hgignore & svn: ignore comme –filter =: C

Rsync inclut une option astucieuse --cvs-exclude pour «ignorer les fichiers de la même manière que CVS», mais CVS est obsolète depuis des années. Y a-t-il un moyen de l’exclure également des fichiers qui seraient ignorés par les systèmes de contrôle de version modernes (Git, Mercurial, Subversion)?

Par exemple, de nombreux projets Maven sont extraits de GitHub. Ils incluent généralement une liste .gitignore au moins target , le répertoire de construction Maven par défaut (qui peut être présent au niveau supérieur ou dans des sous-modules). Étant donné que le contenu de ces répertoires est entièrement jetable, et qu’ils peuvent être beaucoup plus volumineux que le code source, je voudrais les exclure lorsque vous utilisez rsync pour les sauvegardes.

Bien sûr, je peux explicitement --exclude=target/ mais cela va supprimer accidentellement les répertoires non liés qui sont juste nommés target et qui ne sont pas supposés être ignorés.

Et je pourrais fournir une liste complète des chemins absolus pour tous les noms de fichiers et modèles mentionnés dans une .gitignore , .hgignore ou svn:ignore sur mon disque, mais ce serait une énorme liste qui devrait être produite par quelque sorte de script

Étant donné que rsync ne prend pas en charge les extractions VCS autres que CVS, existe-t-il un bon truc pour les alimenter avec leurs modèles d’ignorance? Ou une sorte de système de rappel par lequel un script utilisateur peut être demandé si un fichier / répertoire donné doit être inclus ou non?

Mise à jour : --filter=':- .gitignore' comme suggéré par LordJavac semble fonctionner aussi bien pour Git que --filter=:C fait pour CVS, au moins sur les exemples que j’ai trouvés, même si on ne sait pas si la syntaxe est une correspondance exacte. --filter=':- .hgignore' ne fonctionne pas très bien pour Mercurial. Par exemple, rsync ne reconnaît pas une expression régulière comme un .hgignore contenant une ligne comme ^target$ (l’équivalent de Mercurial de Git /target/ ). Et rien ne semble fonctionner pour Subversion, pour lequel vous devez parsingr .svn/dir-prop-base pour une copie de travail 1.6 ou antérieure, et lever la tête pour une copie de travail 1.7 ou ultérieure.

Comme mentionné par luksan, vous pouvez le faire avec le commutateur --filter sur rsync . J’ai réalisé ceci avec --filter=':- .gitignore' (il y a un espace avant “.gitignore”) qui dit à rsync de faire une fusion de répertoire avec les fichiers .gitignore et de leur faire exclure les règles par git. Vous pouvez également append votre fichier global d’ignorance, si vous en avez un. Pour le rendre plus facile à utiliser, j’ai créé un alias pour rsync qui incluait le filtre.

Vous pouvez utiliser git ls-files pour créer la liste des fichiers exclus par les fichiers .gitignore du référentiel. https://git-scm.com/docs/git-ls-files

Options:

  • --exclude-standard Considérez tous les fichiers .gitignore .
  • -o Ne pas ignorer les modifications non mises en scène.
  • -i Seulement la sortie des fichiers ignorés.
  • --directory uniquement le chemin du répertoire si le répertoire entier est ignoré.

La seule chose que j’ai laissée pour ignorer était .git .

 rsync -azP --exclude=.git --exclude=`git -C  ls-files --exclude-standard -oi --directory`   

rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination ?
Cela a fonctionné pour moi.
Je crois que vous pouvez avoir plus --exclude-from parameters aussi.

2018 solution confirmée

 rsync -ah --delete --include .git --exclude-from="$(git -C SRC ls-files \ --exclude-standard -oi --directory >.git/ignores.tmp && \ echo .git/ignores.tmp')" \ SRC DST 

Détails: --exclude-from est obligatoire à la place de –exclude, car le cas probable où cette liste d’exclusion ne serait pas analysé en tant qu’argument. Exclure de requirejs un fichier et ne peut pas fonctionner avec des tuyaux.

La solution actuelle enregistre le fichier d’exclusion dans le dossier .git afin de s’assurer qu’il n’affectera pas le git status tout en le maintenant autonome. Si vous le souhaitez, vous pouvez utiliser / tmp.

J’avais un certain nombre de très gros fichiers .gitignore et aucune des solutions “pure rsync” ne fonctionnait pour moi. J’ai écrit ce script wrapper rsync , il respecte .gitignore règles .gitignore (inclure les exceptions ! .gitignore et les fichiers .gitignore dans les sous-répertoires) et a fonctionné comme un charme pour moi.

Pour mercurial vous pourriez utiliser

 hg status -i | sed 's/^I //' > /tmp/tmpfile.txt 

pour collecter la liste des fichiers qui ne sont PAS sous contrôle mercuriel à cause des ressortingctions .hgignore et ensuite exécutés

 rsync -avm --exclude-from=/tmp/tmpfile.txt --delete source_dir/ target_dir/ 

rsync tous les fichiers sauf ceux ignorés. Notez l’ option -m dans rsync qui exclura les répertoires vides de la synchronisation car hg status -i ne listera que les fichiers exclus, pas les répertoires

Consultez la section RÈGLES DE FILTRAGE DE MERGE-FILES dans rsync (1).

Il semble possible de créer une règle rsync –filter qui inclura les fichiers .gitignore dans la structure des répertoires.

Par la page de manuel rsync , en plus de la liste standard des modèles de fichiers:

les fichiers listés dans $ HOME / .cvsignore sont ajoutés à la liste et à tous les fichiers répertoriés dans la variable d’environnement CVSIGNORE

Donc, mon fichier $ HOME / .cvsignore ressemble à ceci:

 .git/ .sass-cache/ 

pour exclure .git et les fichiers générés par Sass .

Au lieu de créer des filtres d’exclusion, vous pouvez utiliser git ls-files pour sélectionner chaque fichier à rsync:

 #!/usr/bin/env bash if [[ ! $# -eq 2 ]] ; then echo "Usage: $(basename $0)  " exit 1 fi cd $1 versioned=$(git ls-files --exclude-standard) rsync --verbose --links --times --relative --protect-args ${versioned} $2 

Cela fonctionne même si git ls-files retourne des chemins séparés par une nouvelle ligne. Ne fonctionnera probablement pas si vous avez des fichiers versionnés avec des espaces dans les noms de fichiers.

Essaye ça:

rsync -azP --delete --filter=":- .gitignore"

Il peut copier tous les fichiers dans le répertoire distant, à l’exception des fichiers dans «.gitignore», et supprimer les fichiers qui ne figurent pas dans votre répertoire actuel.