172 votes

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

Rsync comprend une option très pratique. --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 de faire en sorte qu'il exclue é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. En général, ils comprennent un .gitignore en énumérant au moins target le répertoire de construction Maven par défaut (qui peut être présent au niveau supérieur ou dans les sous-modules). Étant donné que le contenu de ces répertoires est entièrement jetable et qu'il peut être beaucoup plus important que le code source, je voudrais les exclure lorsque j'utilise rsync pour les sauvegardes.

Bien sûr, je peux explicitement --exclude=target/ mais cela supprimera accidentellement des répertoires non liés qui s'appellent simplement 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 les modèles mentionnés dans n'importe quel fichier de la liste. .gitignore , .hgignore ou svn:ignore sur mon disque, mais ce serait une liste énorme qui devrait être produite par une sorte de script.

Puisque rsync n'a pas de support intégré pour les extractions VCS autres que CVS, y a-t-il une bonne astuce pour lui fournir leurs modèles d'ignorance ? Ou une sorte de système de rappel par lequel on peut demander à un utilisateur script 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 le fait pour CVS, du 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 fichier de type .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 vous devriez analyser .svn/dir-prop-base pour une copie de travail 1.6 ou antérieure, et levez les mains en signe de consternation pour une copie de travail 1.7 ou ultérieure.

178voto

LordJavac Points 171

Comme l'a mentionné luksan, vous pouvez le faire avec la fonction --filter passer à rsync . J'y suis parvenu avec --filter=':- .gitignore' (il y a un espace avant ".gitignore") qui indique à rsync pour faire une fusion de répertoire avec .gitignore et les faire exclure selon les règles de git. Vous pouvez également ajouter votre fichier d'ignorances global, si vous en avez un. Pour faciliter son utilisation, j'ai créé un alias à rsync qui comprenait le filtre.

34voto

James Bond Points 708

Après des heures de recherche, j'ai trouvé exactement ce dont j'ai besoin : synchroniser le dossier de destination avec le dossier source (en supprimant aussi les fichiers dans la destination s'ils ont été supprimés dans la source), et ne pas copier dans la destination les fichiers qui sont ignorés par .gitignore , mais aussi de ne pas supprimer ces fichiers dans la destination :

rsync -vhra /source/project/ /destination/project/ --include='**.gitignore' --exclude='/.git' --filter=':- .gitignore' --delete-after

En d'autres termes, cette commande ignore complètement les fichiers de .gitignore, à la fois dans la source et dans la destination. . Vous pouvez omettre --exclude='/.git' si vous voulez copier la partie .git également.

Vous MUST copie .gitignore des fichiers de la source. Si vous utilisez la commande de LordJavac, la commande .gitignore ne sera pas copié. Et si vous créez un fichier dans le dossier de destination, celui-ci devrait être ignoré par .gitignore ce fichier sera supprimé malgré .gitignore . C'est parce que vous n'avez pas .gitignore -dans la destination. Mais si vous disposez de ces fichiers, les fichiers décrits dans le fichier .gitignore ne seront pas supprimés, ils seront ignorés, juste attendus.

18voto

Jared Deckard Points 334

Vous pouvez utiliser git ls-files pour construire la liste des fichiers exclus par l'option d'exclusion du référentiel .gitignore des fichiers. https://git-scm.com/docs/git-ls-files

Options :

  • --exclude-standard Considérez tous .gitignore des fichiers.
  • -o N'ignorez pas les changements non organisés.
  • -i Ne sortir que les fichiers ignorés.
  • --directory N'affiche que le chemin du répertoire si le répertoire entier est ignoré.

La seule chose que je devais ignorer était .git .

rsync -azP --exclude=.git --exclude=`git -C <SRC> ls-files --exclude-standard -oi --directory` <SRC> <DEST>

12voto

sorin Points 23747

Solution 2018 confirmé

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 il est probable que la liste d'exclusion ne soit pas analysée comme un argument. Exclure de nécessite un fichier et ne peut pas fonctionner avec les pipes.

La solution actuelle sauvegarde le fichier d'exclusion à l'intérieur du dossier .git afin de s'assurer qu'il n'affectera pas git status tout en restant autonome. Si vous le souhaitez, vous pouvez utiliser /tmp.

9voto

fuzzybee Points 623

Comment rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination ?
Ça a marché pour moi.
Je crois que vous pouvez avoir plus --exclude-from des paramètres également.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X