git rsync 根据 .gitignore & .hgignore & svn:ignore 排除,如 --filter=:C

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13713101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 15:02:25  来源:igfitidea点击:

rsync exclude according to .gitignore & .hgignore & svn:ignore like --filter=:C

gitsvnmercurialrsync

提问by Jesse Glick

Rsync includes a nifty option --cvs-excludeto “ignore files in the same way CVS does”, but CVS has been obsolete for years. Is there any way to make it also exclude files which would be ignored by modern version control systems (Git, Mercurial, Subversion)?

Rsync 包含一个漂亮的选项,--cvs-exclude可以“以与 CVS 相同的方式忽略文件”,但 CVS 已经过时多年。有没有办法让它也排除现代版本控制系统(Git、Mercurial、Subversion)会忽略的文件?

For example, I have lots of Maven projects checked out from GitHub. Typically they include a .gitignorelisting at least target, the default Maven build directory (which may be present at top level or in submodules). Since the contents of these directories are entirely disposable, and they can be far larger than source code, I would like to exclude them when using rsync for backups.

例如,我有很多从 GitHub 检出的 Maven 项目。通常,它们.gitignore至少包含一个列表target,即默认的 Maven 构建目录(可能存在于顶层或子模块中)。由于这些目录的内容完全是一次性的,而且它们可能比源代码大得多,我想在使用 rsync 进行备份时排除它们。

Of course I can explicitly --exclude=target/but that will accidentally suppress unrelated directories that just happen to be named targetand are not supposed to be ignored.

当然,我可以明确地--exclude=target/但这会意外地抑制恰好被命名target并且不应被忽略的不相关目录。

And I could supply a complete list of absolute paths for all file names and patterns mentioned in any .gitignore, .hgignore, or svn:ignoreproperty on my disk, but this would be a huge list that would have to be produced by some sort of script.

我可以为磁盘上的任何.gitignore.hgignoresvn:ignore属性中提到的所有文件名和模式提供完整的绝对路径列表,但这将是一个巨大的列表,必须由某种脚本生成。

Since rsync has no built-in support for VCS checkouts other than CVS, is there any good trick for feeding it their ignore patterns? Or some kind of callback system whereby a user script can be asked whether a given file/directory should be included or not?

由于 rsync 没有对 CVS 以外的 VCS 检出的内置支持,是否有什么好的技巧可以为其提供忽略模式?或者某种回调系统可以询问用户脚本是否应该包含给定的文件/目录?

Update: --filter=':- .gitignore'as suggested by LordJavac seems to work as well for Git as --filter=:Cdoes for CVS, at least on the examples I have found, though it is unclear if the syntax is an exact match. --filter=':- .hgignore'does not work very well for Mercurial; e.g. an .hgignorecontaining a line like ^target$(the Mercurial equivalent of Git /target/) is not recognized by rsync as a regular expression. And nothing seems to work for Subversion, for which you would have to parse .svn/dir-prop-basefor a 1.6 or earlier working copy, and throw up your hands in dismay for a 1.7 or later working copy.

更新--filter=':- .gitignore'正如 LordJavac 所建议的,似乎对 Git 和--filter=:CCVS 都有效,至少在我发现的示例中如此,尽管尚不清楚语法是否完全匹配。--filter=':- .hgignore'不适用于 Mercurial;例如,.hgignore包含像^target$(Git 的 Mercurial 等价物/target/)这样的行不被 rsync 识别为正则表达式。并且似乎对 Subversion 没有任何作用,为此您必须解析.svn/dir-prop-base1.6 或更早版本的工作副本,并为 1.7 或更高版本的工作副本感到沮丧。

回答by LordJavac

As mentioned by luksan, you can do this with the --filterswitch to rsync. I achieved this with --filter=':- .gitignore'(there's a space before ".gitignore") which tells rsyncto do a directory merge with .gitignorefiles and have them exclude per git's rules. You may also want to add your global ignore file, if you have one. To make it easier to use, I created an alias to rsyncwhich included the filter.

正如 luksan 所提到的,您可以通过--filter切换到rsync. 我通过--filter=':- .gitignore'(“.gitignore”之前有一个空格)实现了这一点,它告诉rsync.gitignore文件进行目录合并,并根据 git 的规则将它们排除在外。您可能还想添加全局忽略文件(如果有)。为了更易于使用,我创建了一个rsync包含过滤器的别名。

回答by Jared Deckard

You can use git ls-filesto build the list of files excluded by the repository's .gitignorefiles. https://git-scm.com/docs/git-ls-files

您可以使用git ls-files来构建存储库文件排除的.gitignore文件列表。 https://git-scm.com/docs/git-ls-files

Options:

选项:

  • --exclude-standardConsider all .gitignorefiles.
  • -oDon't ignore unstaged changes.
  • -iOnly output ignored files.
  • --directoryOnly output the directory path if the entire directory is ignored.
  • --exclude-standard考虑所有.gitignore文件。
  • -o不要忽略未分阶段的更改。
  • -i只输出忽略的文件。
  • --directory如果忽略整个目录,则仅输出目录路径。

The only thing I left to ignore was .git.

我唯一要忽略的是.git.

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

回答by ericn

how about rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination?
It worked for me.
I believe you can have more --exclude-fromparameters too.

怎么样rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination
它对我有用。
我相信你也可以有更多的--exclude-from参数。

回答by sorin

2018 solution confirmed

2018年解决方案确认

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 

Details: --exclude-fromis mandatory instead of --exclude because likely case that exclude list would not be parsed as an argument. Exclude from requires a file and cannot work with pipes.

详细信息:--exclude-from是强制性的而不是 --exclude 因为排除列表的可能情况不会被解析为参数。排除需要一个文件并且不能使用管道。

Current solution saves the exclude file inside the .git folder in order to assure it will not affect git statuswhile keeping it self contained. If you want you are welcome to use /tmp.

当前的解决方案将排除文件保存在 .git 文件夹中,以确保它git status在保持自包含的同时不会受到影响。如果您愿意,欢迎使用 /tmp。

回答by ffeast

For mercurialyou might use

对于mercurial,您可能会使用

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

to collect the list of files which are NOT under mercurial control because of .hgignorerestrictions and then run

收集由于.hgignore限制而不受mercurial 控制的文件列表,然后运行

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

to rsync all files except the ignored ones. Notice -mflag in rsync that will exclude empty directories from syncing because hg status -iwould only list excluded files, not dirs

rsync 所有文件,除了被忽略的文件。注意rsync 中的-m标志,它将从同步中排除空目录,因为hg status -i只会列出排除的文件,而不是目录

回答by Shawn Wang

Try this:

尝试这个:

rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>

rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>

It can copy all files to remote directory excluding files in '.gitignore', and delete files not in your current directory.

它可以将除“.gitignore”中的文件之外的所有文件复制到远程目录,并删除不在当前目录中的文件。

回答by Doug Harris

Per the rsyncman page, in addition to the standard list of file patterns:

根据rsync手册页,除了文件模式的标准列表:

files listed in a $HOME/.cvsignore are added to the list and any files listed in the CVSIGNORE environment variable

$HOME/.cvsignore 中列出的文件被添加到列表中,CVSIGNORE 环境变量中列出的任何文件

So, my $HOME/.cvsignore file looks like this:

所以,我的 $HOME/.cvsignore 文件看起来像这样:

.git/
.sass-cache/

to exclude .git and the files generated by Sass.

排除 .git 和Sass生成的文件。

回答by cobbzilla

I had a number of very large .gitignorefiles and none of the "pure rsync" solutions worked for me. I wrote this rsync wrapper script, it fully respects .gitignorerules (include !-style exceptions and .gitignorefiles in subdirectories) and has worked like a charm for me.

我有许多非常大的.gitignore文件,但没有一个“纯 rsync”解决方案对我有用。我写了这个rsync 包装器脚本,它完全遵守.gitignore规则(包括子目录中的!样式异常和.gitignore文件)并且对我来说就像一个魅力。

回答by luksan

Check out the MERGE-FILES FILTER RULES section in rsync(1).

查看 rsync(1) 中的 MERGE-FILES FILTER RULES 部分。

It looks like it's possible to create a rsync --filter rule that will include .gitignore files as traverses the directory structure.

看起来可以创建一个 rsync --filter 规则,该规则将在遍历目录结构时包含 .gitignore 文件。

回答by luksan

Instead of creating exclude filters, you can use git ls-filesto select each file to rsync:

您可以使用git ls-filesrsync 选择每个文件,而不是创建排除过滤器:

#!/usr/bin/env bash

if [[ ! $# -eq 2 ]] ; then
    echo "Usage: $(basename ##代码##) <local source> <rsync destination>"
    exit 1
fi

cd 
versioned=$(git ls-files --exclude-standard)
rsync --verbose --links --times --relative --protect-args ${versioned} 

This works even though git ls-filesreturns newline separated paths. Probably won't work if you have versioned files with spaces in the filenames.

即使git ls-files返回换行符分隔的路径,这也有效。如果您的文件名中带有空格的版本化文件可能不起作用。