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
rsync exclude according to .gitignore & .hgignore & svn:ignore like --filter=:C
提问by Jesse Glick
Rsync includes a nifty option --cvs-exclude
to “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 .gitignore
listing 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 target
and 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:ignore
property on my disk, but this would be a huge list that would have to be produced by some sort of script.
我可以为磁盘上的任何.gitignore
、.hgignore
或svn: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=:C
does 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 .hgignore
containing 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-base
for 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=:C
CVS 都有效,至少在我发现的示例中如此,尽管尚不清楚语法是否完全匹配。--filter=':- .hgignore'
不适用于 Mercurial;例如,.hgignore
包含像^target$
(Git 的 Mercurial 等价物/target/
)这样的行不被 rsync 识别为正则表达式。并且似乎对 Subversion 没有任何作用,为此您必须解析.svn/dir-prop-base
1.6 或更早版本的工作副本,并为 1.7 或更高版本的工作副本感到沮丧。
回答by LordJavac
As mentioned by luksan, you can do this with the --filter
switch to rsync
. I achieved this with --filter=':- .gitignore'
(there's a space before ".gitignore") which tells rsync
to do a directory merge with .gitignore
files 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 rsync
which included the filter.
正如 luksan 所提到的,您可以通过--filter
切换到rsync
. 我通过--filter=':- .gitignore'
(“.gitignore”之前有一个空格)实现了这一点,它告诉rsync
对.gitignore
文件进行目录合并,并根据 git 的规则将它们排除在外。您可能还想添加全局忽略文件(如果有)。为了更易于使用,我创建了一个rsync
包含过滤器的别名。
回答by Jared Deckard
You can use git ls-files
to build the list of files excluded by the repository's .gitignore
files.
https://git-scm.com/docs/git-ls-files
您可以使用git ls-files
来构建存储库文件排除的.gitignore
文件列表。
https://git-scm.com/docs/git-ls-files
Options:
选项:
--exclude-standard
Consider all.gitignore
files.-o
Don't ignore unstaged changes.-i
Only output ignored files.--directory
Only 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-from
parameters 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-from
is 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 status
while 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 rsync
man 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 .gitignore
files and none of the "pure rsync" solutions worked for me. I wrote this rsync wrapper script, it fully respects .gitignore
rules (include !
-style exceptions and .gitignore
files 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-files
to select each file to rsync:
您可以使用git ls-files
rsync 选择每个文件,而不是创建排除过滤器:
#!/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-files
returns newline separated paths. Probably won't work if you have versioned files with spaces in the filenames.
即使git ls-files
返回换行符分隔的路径,这也有效。如果您的文件名中带有空格的版本化文件可能不起作用。