O Rsync inclui uma opção bacana --cvs-exclude
para “ignorar os arquivos da mesma forma que o CVS”, mas o CVS está obsoleto há anos. Existe alguma maneira de fazer com que ele também exclua arquivos que seriam ignorados pelos sistemas de controle de versão modernos (Git, Mercurial, Subversion)?
Por exemplo, eu tenho muitos projetos Maven retirados do GitHub. Normalmente, eles incluem uma .gitignore
lista, pelo menos target
, o diretório padrão de construção do Maven (que pode estar presente no nível superior ou em submódulos). Como o conteúdo desses diretórios é totalmente descartável e podem ser muito maiores do que o código-fonte, gostaria de excluí-los ao usar o rsync para backups.
Claro que posso explicitamente, --exclude=target/
mas isso suprimirá acidentalmente diretórios não relacionados que apenas foram nomeados target
e não devem ser ignorados.
E eu poderia fornecer uma lista completa de caminhos absolutos para todos os nomes de arquivos e padrões mencionados em qualquer .gitignore
, .hgignore
ou svn:ignore
propriedade no meu disco, mas isso seria uma lista enorme que teria de ser produzida por algum tipo de script.
Visto que o rsync não tem suporte embutido para checkouts VCS além do CVS, existe algum bom truque para alimentá-lo com seus padrões de ignorar? Ou algum tipo de sistema de retorno de chamada por meio do qual um script de usuário pode ser perguntado se um determinado arquivo / diretório deve ser incluído ou não?
Atualização : --filter=':- .gitignore'
como sugerido por LordJavac, parece funcionar tão bem para Git quanto --filter=:C
para CVS, pelo menos nos exemplos que encontrei, embora não esteja claro se a sintaxe é uma correspondência exata. --filter=':- .hgignore'
não funciona muito bem para o Mercurial; por exemplo, um .hgignore
contendo uma linha como ^target$
(o Mercurial equivalente do Git /target/
) não é reconhecido pelo rsync como uma expressão regular. E nada parece funcionar para o Subversion, para o qual você teria que analisar .svn/dir-prop-base
para uma cópia de trabalho 1.6 ou anterior, e desanimar para uma cópia de trabalho 1.7 ou posterior.
:-
significa exatamente? O que significa o cólon? Qual é o traço?check-ignore
subcomando que pode lidar com o trabalho duro de analisar os vários arquivos "ignorar", se você quiser ir com a opção "gerar uma lista de todos os arquivos não ignorados". Minha resposta aqui dá detalhes de como fazer isso.Respostas:
Conforme mencionado por luksan, você pode fazer isso com a
--filter
chave pararsync
. Eu consegui isso com--filter=':- .gitignore'
(há um espaço antes de ".gitignore") que dizrsync
para fazer uma fusão de diretório com.gitignore
arquivos e excluí-los de acordo com as regras do git. Você também pode adicionar seu arquivo global para ignorar, se tiver um. Para facilitar o uso, criei um aliasrsync
que incluía o filtro.fonte
--exclude='/.git' --filter="dir-merge,- .gitignore"
rsync -rvv --exclude='.git*' --exclude='/rsync-to-dev.sh' --filter='dir-merge,-n /.gitignore' $DIR/ development.foobar.com:~/test/
.. mas embora diga[sender] hiding file .gitignore because of pattern .git*
, o arquivo ainda é enviado para a desintização--delete
opção, aqui é a linha de comando de trabalho:rsync --delete-after --filter=":e- .gitignore" --filter "- .git/" -v -a ...
. Isso me levou um tempo ...e
no filtro e--delete-after
são importantes. Eu sugiro ler o capítulo "REGRAS POR DIRETÓRIO E EXCLUIR" darsync
página de manual.--delete-after
a versão do comando de @VasiliNovikov. (Isso parece equivalente à versão do comando de @ dboliton, exceto que @db usa: e que eu acho que exclui os arquivos .gitignore de serem copiados, o que não é o que eu queria.)Você pode usar
git ls-files
para construir a lista de arquivos excluídos pelos arquivos do repositório.gitignore
. https://git-scm.com/docs/git-ls-filesOpções:
--exclude-standard
Considere todos os.gitignore
arquivos.-o
Não ignore as mudanças não planejadas.-i
Produzir apenas arquivos ignorados.--directory
Somente imprima o caminho do diretório se todo o diretório for ignorado.A única coisa que deixei para ignorar foi
.git
.fonte
rsync -azP --exclude-from="$(git -C SRC ls-files --exclude-standard -oi --directory > /tmp/excludes; echo /tmp/excludes)" SRC DEST
.gitignore
(ou seja, linhas que começam com!
). Ele também sincroniza os arquivos que você--force
adicionou ao repo, o que geralmente é uma coisa boa.que tal
rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination
?Funcionou para mim
Eu acredito que você pode ter mais
--exclude-from
parâmetros também.fonte
.gitignore
arquivos usem uma sintaxe compatível comrsync
.Solução 2018 confirmada
Detalhes:
--exclude-from
é obrigatório em vez de --exclude porque o caso provável dessa lista de exclusões não seria analisado como um argumento. Excluir de requer um arquivo e não pode funcionar com tubos.A solução atual salva o arquivo de exclusão dentro da pasta .git para garantir que ele não afetará
git status
, mantendo-o independente. Se você quiser, pode usar / tmp.fonte
SRC
aqui, mas não para o problema original que afirmei, que é um diretório extenso com milhares de repositórios Git como subdiretórios em várias profundidades, muitos dos quais têm idiossincrático.gitignore
s.--exclude-from=<(git -C SRC ls-files --exclude-standard -oi --directory)
Para mercurial, você pode usar
para coletar a lista de arquivos que NÃO estão sob controle mercurial por causa das restrições .hgignore e, em seguida, execute
para sincronizar todos os arquivos, exceto os ignorados. Observe -m sinalizador em rsync que excluirá diretórios vazios da sincronização porque hg status -i listaria apenas arquivos excluídos, não dirs
fonte
Experimente isto:
rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>
Ele pode copiar todos os arquivos para um diretório remoto, excluindo arquivos em '.gitignore', e excluir arquivos que não estejam em seu diretório atual.
fonte
De acordo com a
rsync
página do manual, além da lista padrão de padrões de arquivo:Então, meu arquivo $ HOME / .cvsignore se parece com isto:
para excluir .git e os arquivos gerados pelo Sass .
fonte
.git/
diretórios, talvez ainda mais fortemente do que a cópia de trabalho. O que eu quero excluir são produtos de construção.rsync
página de manual citada nesta resposta descreve a--cvs-exclude
opção, portanto, você deve usá-la explicitamente. 2 / Você pode criar.cvsignore
arquivos em qualquer diretório para ignorar específicos do projeto, eles também são lidos. 3 /.git
já é ignorado quando você usa--cvs-exclude
, de acordo com o manual, então tê-lo$HOME/.cvsignore
ativado parece redundante.Eu tinha vários
.gitignore
arquivos muito grandes e nenhuma das soluções de "rsync puro" funcionou para mim. Eu escrevi este script de wrapper rsync , ele respeita totalmente as.gitignore
regras (!
exceções de estilo de inclusão e.gitignore
arquivos em subdiretórios) e tem funcionado perfeitamente para mim.fonte
locate -0e .gitignore | (while read -d '' x; do process_git_ignore "$x"; done)
, mas tem muitos problemas. Os arquivos no mesmo diretório.gitignore
não foram separados corretamente do nome do diretório com/
. Linhas em branco e comentários mal interpretados. Bloqueia em.gitignore
arquivos em caminhos com espaços (não importa o diabólico/opt/vagrant/embedded/gems/gems/rb-fsevent-0.9.4/spec/fixtures/custom 'path/.gitignore
dovagrant
pacote para Ubuntu). Talvez seja melhor executado como um script Perl.rsync
, pelo motivo específico de que lidar com citações / espaços em branco é uma dor. Se você tiver um exemplo de umagsync
linha de comando que está falhando e os.gitignore
arquivos associados a ela, ficaria feliz em dar uma olhada mais de perto.rsync
um sistema de arquivos inteiro, com vários repositórios Git espalhados por ele. Talvez seu script funcione bem no caso de sincronização de um único repositório.Verifique a seção MERGE-FILES FILTER RULES em rsync (1).
Parece que é possível criar uma regra rsync --filter que incluirá arquivos .gitignore conforme atravessa a estrutura de diretório.
fonte
Em vez de criar filtros de exclusão, você pode usar
git ls-files
para selecionar cada arquivo para rsync:Isso funciona mesmo que
git ls-files
retorne caminhos separados por nova linha. Provavelmente não funcionará se você tiver arquivos versionados com espaços nos nomes dos arquivos.fonte
Alternativas:
git ls-files -zi --exclude-standard |rsync -0 --exclude-from=- ...
git ls-files -zi --exclude-per-directory=".gitignore" |...
(o rsync entende apenas parcialmente .gitignore)
fonte
Resposta curta
Significado dos parâmetros:
-r
: recursivo--info=...
: mostrar progresso--filter=...
: exclui pelas regras listadas no arquivo .gitignorefonte