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. Existe-t-il un moyen d'exclure également les fichiers qui seraient ignorés par les systèmes de contrôle de version modernes (Git, Mercurial, Subversion)?
Par exemple, j'ai beaucoup de projets Maven extraits de GitHub. Ils incluent généralement un .gitignore
listant au moins target
, le répertoire de construction par défaut de Maven (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'il peut être bien plus volumineux que le code source, je voudrais les exclure lors de l'utilisation de rsync pour les sauvegardes.
Bien sûr, je peux explicitement --exclude=target/
mais cela supprimera accidentellement les répertoires non liés qui se trouvent être nommés target
et ne sont pas censé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 n'importe quel .gitignore
, .hgignore
, ou svn:ignore
propriété sur mon disque, mais ce serait une énorme liste qui devrait être produite par une sorte de script.
Étant donné que rsync n'a pas de prise en charge intégrée pour les extractions VCS autres que CVS, existe-t-il une bonne astuce pour l'alimenter en modèles ignorés? Ou une sorte de système de rappel permettant de demander à un script utilisateur si un fichier/répertoire donné doit être inclus ou non?
Mise à jour: --filter=':- .gitignore'
comme l'a suggéré LordJavac semble fonctionner aussi bien pour Git que --filter=:C
fait pour CVS, au moins sur les exemples que j'ai trouvés, bien qu'il ne soit pas clair si la syntaxe est une correspondance exacte. --filter=':- .hgignore'
ne fonctionne pas très bien pour Mercurial; par exemple. un .hgignore
contenant une ligne comme ^target$
(l'équivalent Mercurial de Git /target/
) n'est pas reconnu par rsync comme une expression régulière. Et rien ne semble fonctionner pour Subversion, pour lequel il faudrait analyser .svn/dir-prop-base
pour une copie de travail 1.6 ou antérieure, et jetez un œil consterné pour une copie de travail 1.7 ou ultérieure.
Comme mentionné par luksan, vous pouvez le faire avec le --filter
basculez sur rsync
. J'ai réussi avec --filter=':- .gitignore'
(il y a un espace avant ".gitignore") qui indique à rsync
de fusionner un répertoire avec .gitignore
fichiers et les faire exclure selon les règles de git. Vous pouvez également ajouter votre fichier d'ignorance global, 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 construire la liste des fichiers exclus par le référentiel .gitignore
des dossiers. https://git-scm.com/docs/git-ls-files
Options:
--exclude-standard
Considérez tout .gitignore
des dossiers.-o
N'ignorez pas les modifications non programmées.-i
Uniquement les fichiers ignorés en sortie.--directory
N'afficher le chemin du répertoire que si le répertoire entier est ignoré.La seule chose que j'ai laissé ignorer était .git
.
rsync -azP --exclude=.git --exclude=`git -C <SRC> ls-files --exclude-standard -oi --directory` <SRC> <DEST>
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 au lieu de --exclude car le cas probable où cette liste d'exclusion ne serait pas analysée comme argument. Exclure de requiert un fichier et ne peut pas fonctionner avec les canaux.
La solution actuelle enregistre le fichier d'exclusion dans le dossier .git afin de garantir qu'il n'affectera pas git status
tout en restant autonome. Si vous le souhaitez, vous pouvez utiliser/tmp.
que diriez-vous rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination
?
Cela a fonctionné pour moi.
Je pense que vous pouvez en avoir plus --exclude-from
paramètres aussi.
Pour Mercurial vous pouvez utiliser
hg status -i | sed 's/^I //' > /tmp/tmpfile.txt
pour collecter la liste des fichiers qui ne sont PAS sous contrôle Mercurial en raison des restrictions . hgignore , puis exécutez
rsync -avm --exclude-from=/tmp/tmpfile.txt --delete source_dir/ target_dir/
pour rsync tous les fichiers sauf ceux ignorés. Remarque - m indicateur dans rsync qui exclura les répertoires vides de la synchronisation car hg status -i ne listerait que les fichiers exclus, pas dirs
Essaye ça:
rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>
Il peut copier tous les fichiers dans un répertoire distant, à l'exception des fichiers dans '.gitignore', et supprimer des fichiers qui ne se trouvent pas dans votre répertoire actuel.
J'ai eu un certain nombre de très gros .gitignore
fichiers et aucune des solutions "pure rsync" n'a fonctionné pour moi. J'ai écrit ceci script wrapper rsync , il respecte pleinement .gitignore
règles (inclure !
- exceptions de style et .gitignore
fichiers dans les sous-répertoires) et a fonctionné comme un charme pour moi.
Par la page de manuel rsync
, en plus de la liste standard des modèles de fichiers:
les fichiers répertoriés dans un $ HOME/.cvsignore sont ajoutés à la liste et tous les fichiers répertoriés dans la variable d'environnement CVSIGNORE
Ainsi, mon fichier $ HOME/.cvsignore ressemble à ceci:
.git/
.sass-cache/
pour exclure .git et les fichiers générés par Sass .
Consultez la section RÈGLES DE FILTRE MERGE-FILES dans rsync (1).
Il semble qu'il soit possible de créer une règle rsync --filter qui inclura les fichiers .gitignore lors de la traversée de la structure du répertoire.
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) <local source> <rsync destination>"
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
renvoie des chemins séparés par des sauts de ligne. Ne fonctionnera probablement pas si vous avez des fichiers versionnés avec des espaces dans les noms de fichiers.
Alternatives:
git ls-files -zi --exclude-standard |rsync -0 --exclude-from=- ...
git ls-files -zi --exclude-per-directory=".gitignore" |...
(rsync ne comprend que partiellement .gitignore)