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

Jes*_*ick 100 svn git mercurial rsync

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

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

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

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

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

更新:--filter=':- .gitignore'正如LordJavac所建议的那样,Git和--filter=:CCVS 一样好,至少在我发现的例子中,尽管不清楚语法是否完全匹配.--filter=':- .hgignore'对Mercurial不起作用; 例如,rsync不能将.hgignore包含类似^target$(Git的Mercurial等价物/target/)的行视为正则表达式.对于Subversion来说似乎没什么用,因为你需要.svn/dir-prop-base为1.6或更早的工作副本解析,并且为1.7或更高版本的工作副本沮丧地举手.

小智 107

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

  • 一个更详细的版本,也不包括.git文件:`--exclude ='/.git'--filter ="dir-merge, - .gitignore" (20认同)
  • 我现在有类似的东西:`rsync -rvv --exclude ='.git*' - exclude ='/ rsync-to-dev.sh'--filter ='dir-merge,-n /.gitignore'$ DIR/development.foobar.com:〜/ test /`..但是虽然它说`[sender]因为模式.git*`而隐藏文件.gitignore,但该文件仍被发送到desintation (2认同)
  • 如果您还想使用`--delete`选项,则可以使用以下命令行:`rsync --delete-after --filter =“:e- .gitignore” --filter“-.git /” -v-一个...`。这花了我一段时间...过滤器中的“ e”和“ --delete-after”都很重要。我建议阅读`rsync`手册页的“ PER-DIRECTORY RULES AND DELETE”一章。 (2认同)
  • 这是否假设从包含“.gitignore”的目录运行“rsync”?或者它是否从同步目录中提取 ot?我想我必须输入 .gitignore 的完整路径才能保存? (2认同)

Jar*_*ard 9

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

选项:

  • --exclude-standard考虑所有.gitignore文件.
  • -o 不要忽略未分级的更改.
  • -i 仅输出忽略的文件.
  • --directory 仅在忽略整个目录时才输出目录路径.

我唯一要忽略的是.git.

rsync -azP --exclude=.git --exclude=`git -C <SRC> ls-files --exclude-standard -oi --directory` <SRC> <DEST>
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用.它从git子命令中排除第一个文件,然后将其余部分视为SRC列表的一部分.这工作:`rsync -azP --exclude-from ="$(git -C SRC ls-files --exclude-standard -oi --directory>/tmp/excludes; echo/tmp/exclude)"SRC DEST` (4认同)
  • 如果您在`.gitignore`中同时包含*和*行(即以`!`开头的行),则这是唯一可行的方法。它也可以同步您--force添加到仓库中的文件,这通常是一件好事。 (2认同)

Jam*_*ond 9

经过数小时的研究,我找到了我所需要的:将目标文件夹与源文件夹同步(如果源文件夹中的文件被删除,也会删除目标文件夹中的文件),而不是将被忽略的文件复制到目标文件夹.gitignore,但也不要删除目标中的这些文件

rsync -vhra /source/project/ /destination/project/ --include='**.gitignore' --exclude='/.git' --filter=':- .gitignore' --delete-after
Run Code Online (Sandbox Code Playgroud)

换句话说,此命令完全忽略来自 .gitignore 的文件,包括源文件和目标文件--exclude='/.git'如果也想复制.git文件夹,您可以省略部分。

您必须从源复制 .gitignore 文件。如果您将使用 LordJavac 的命令,则不会复制 .gitignore。如果您在目标文件夹中创建一个文件,该文件应该被 .gitignore 忽略,尽管 .gitignore 将删除该文件。这是因为目标中没有 .gitignore 文件。但是如果你有这个文件,.gitignore 中描述的文件不会被删除,它们会被忽略,只是预期的。

  • 由于它不明显,可能值得注意的是“':- .gitignore”意味着dir-merge(“:”),从文件“.gitignore”中排除模式(“-”)。“dir-merge”是“per-directory merge”的缩写,这意味着“rsync 将扫描它遍历的每个目录以查找指定文件,当文件存在到当前继承规则列表中时将其内容合并。” 就我而言,我只有一个`.gitignore`,并且它位于父目录中,所以对我来说正确的选项是:`--filter='.- ../.gitignore'`,这是一个“单-实例”(`.`) 合并。 (3认同)

sor*_*rin 6

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 
Run Code Online (Sandbox Code Playgroud)

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

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

  • 如果您有一个要同步的_particular_ Git存储库(此处为“ SRC”),但似乎并非我所说的原始问题,它是一个庞大的目录,具有成千上万个Git存储库作为深度不同的子目录,这看起来好像可以工作。其中有特有的`.gitignore`s。 (3认同)
  • 如果您使用的 shell 支持进程替换(bash、zsh 等),您可以使用 `--exclude-from=&lt;(git -C SRC ls-files --exclude-standard -oi --directory)` (2认同)

eri*_*icn 5

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

  • 只要您的`.gitignore`文件碰巧使用与`rsync`兼容的语法,这就可以正常工作. (3认同)
  • @JesseGlick 是对的,rsync 无法解析 .gitignore 文件,请参阅 /sf/answers/3504172521/ 解决方法。 (2认同)

小智 1

查看 rsync(1) 中的合并文件过滤规则部分。

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