git svn mercurial rsync

rsync excluye según.gitignore &.hgignore & svn: ignore como--filter=: C



mercurial (9)

Rsync incluye una opción ingeniosa --cvs-exclude para "ignorar archivos de la misma manera que CVS", pero CVS ha quedado obsoleto durante años. ¿Hay alguna manera de hacer que también excluya archivos que serían ignorados por los modernos sistemas de control de versiones (Git, Mercurial, Subversion)?

Por ejemplo, tengo muchos proyectos de Maven sacados de GitHub. Por lo general, incluyen un listado .gitignore al menos target , el directorio de compilación Maven predeterminado (que puede estar presente en el nivel superior o en submódulos). Dado que el contenido de estos directorios es totalmente desechable, y pueden ser mucho más grandes que el código fuente, me gustaría excluirlos cuando uso rsync para copias de seguridad.

Por supuesto, puedo explícitamente --exclude=target/ pero eso suprimirá accidentalmente directorios no relacionados que simplemente se denominan target y no se deben ignorar.

Y podría proporcionar una lista completa de rutas absolutas para todos los nombres de archivos y patrones mencionados en cualquier .gitignore , .hgignore o svn:ignore en mi disco, pero esta sería una gran lista que tendría que ser producida por algún tipo de secuencia de comandos

Dado que rsync no tiene soporte integrado para las comprobaciones de VCS que no sean CVS, ¿hay algún truco para alimentar sus patrones de ignorar? ¿O algún tipo de sistema de devolución de llamada mediante el cual se puede preguntar al usuario si se debe incluir o no un archivo / directorio determinado?

Actualización : --filter='':- .gitignore'' como lo sugiere LordJavac parece funcionar también para Git como --filter=:C hace para CVS, al menos en los ejemplos que he encontrado, aunque no está claro si la sintaxis es una coincidencia exacta. --filter='':- .hgignore'' no funciona muy bien para Mercurial; por ejemplo, un .hgignore contiene una línea como ^target$ (el equivalente de Mercurial de Git /target/ ) no es reconocido por rsync como una expresión regular. Y nada parece funcionar para Subversion, para lo cual tendría que analizar .svn/dir-prop-base para una copia de trabajo 1.6 o anterior, y levantar sus manos en señal de consternación por una copia de trabajo 1.7 o posterior.


2018 solución confirmed

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

Detalles: --exclude-from es obligatorio en lugar de --exclude porque es probable que el caso que excluye la lista no se analice como un argumento. Excluir requiere un archivo y no puede trabajar con tuberías.

La solución actual guarda el archivo de exclusión dentro de la carpeta .git para asegurar que no afecte el git status mientras se mantiene independiente. Si lo desea, puede utilizar / tmp.


¿ rsync --exclude-from=''path/.gitignore'' --exclude-from=''path/myignore.txt'' source destination ?
Funcionó para mí
Creo que también puedes tener más parámetros de --exclude-from .


Como lo mencionó luksan, puede hacer esto con el interruptor --filter a rsync . Lo --filter='':- .gitignore'' con --filter='':- .gitignore'' (hay un espacio antes de ".gitignore") que le dice a rsync que haga una fusión de directorio con archivos .gitignore y que los excluya por las reglas de git. También es posible que desee agregar su archivo global de ignorar, si tiene uno. Para que sea más fácil de usar, creé un alias para rsync que incluía el filtro.


Consulte la sección REGLAS DEL FILTRO DE FUSIÓN en rsync (1).

Parece que es posible crear una regla rsync --filter que incluirá archivos .gitignore a medida que atraviesa la estructura del directorio.


En lugar de crear filtros de exclusión, puede usar git ls-files para seleccionar cada archivo para 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

Esto funciona a pesar de que git ls-files devuelve rutas separadas por nueva línea. Probablemente no funcionará si tiene archivos versionados con espacios en los nombres de archivo.


Para Mercurial puedes usar

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

para recopilar la lista de archivos que NO están bajo control mercurial debido a restricciones de .hgignore y luego ejecutar

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

para sincronizar todos los archivos, excepto los ignorados. Observe -m marca en rsync que excluirá la sincronización de directorios vacíos porque el estado hg -i solo mostrará los archivos excluidos, no los directorios


Puede usar git ls-files para compilar la lista de archivos excluidos por los archivos .gitignore del repositorio. https://git-scm.com/docs/git-ls-files

Opciones:

  • --exclude-standard Considera todos los archivos .gitignore .
  • -o No ignore los cambios sin grabar.
  • -i Solo salida de archivos ignorados.
  • --directory Solo --directory la ruta del directorio si se ignora todo el directorio.

Lo único que dejé de ignorar fue .git .

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


Según la página del manual de rsync , además de la lista estándar de patrones de archivos:

los archivos que se enumeran en $ HOME / .cvsignore se agregan a la lista y a los archivos enumerados en la variable de entorno CVSIGNORE

Por lo tanto, mi archivo $ HOME / .cvsignore se ve así:

.git/ .sass-cache/

para excluir .git y los archivos generados por Sass .


Tenía varios archivos .gitignore muy grandes y ninguna de las soluciones "rsync puras" funcionaba para mí. Escribí este guión rsync wrapper , respeta .gitignore reglas .gitignore (incluye excepciones de estilo ! .gitignore archivos .gitignore en subdirectorios) y funcionó como un encanto para mí.