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