rsync排除根据.gitignore& .hgignore& svn:忽略像--filter =:C

时间:2012-12-04 22:30:17

标签: git svn 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=:C对CVS,至少在我发现的例子中,尽管它是不清楚语法是否完全匹配。 --filter=':- .hgignore'对Mercurial不起作用;例如包含.hgignore之类的行^target$(Git /target/的Mercurial等价物)不会被rsync识别为正则表达式。对于Subversion来说似乎没什么用处,因为你需要为{1.6}或更早的工作副本解析.svn/dir-prop-base,并为1.7或更高版本的工作副本沮丧地举手。

13 个答案:

答案 0 :(得分:94)

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

答案 1 :(得分:8)

您可以使用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>

答案 2 :(得分:5)

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

答案 3 :(得分:4)

2018解决方案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 

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

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

答案 4 :(得分:3)

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

rsync -vhra /source/project/ /destination/project/ --include='**.gitignore' --exclude='/.git' --filter=':- .gitignore' --delete-after

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

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

答案 5 :(得分:2)

对于 mercurial ,您可以使用

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

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

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

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

答案 6 :(得分:2)

尝试一下:

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

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

答案 7 :(得分:1)

我有一些非常大的.gitignore文件,而且没有#34;纯rsync&#34;解决方案对我有用。我写了这个rsync wrapper script,它完全尊重.gitignore规则(包括! - 样式异常和子目录中的.gitignore文件),并且对我来说就像一个魅力。

答案 8 :(得分:0)

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

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

答案 9 :(得分:0)

除了rsync手册页之外,还有标准的文件模式列表:

  $ HOME / .cvsignore中列出的

文件将添加到列表中,并且CVSIGNORE环境变量中列出的所有文件

因此,我的$ HOME / .cvsignore文件如下所示:

.git/
.sass-cache/

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

答案 10 :(得分:0)

您可以使用git ls-files选择每个文件到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

即使git ls-files返回换行符分隔的路径,这仍然有效。如果您在文件名中包含带空格的版本文件,则可能无法工作。

答案 11 :(得分:0)

替代品:

git ls-files -zi --exclude-standard |rsync -0 --exclude-from=- ...

git ls-files -zi --exclude-per-directory=".gitignore" |...

(rsync仅部分理解.gitignore)

答案 12 :(得分:0)

简短回答

@Override
public void onNewIntent (Intent intent) {
    setIntent(intent);
}

@Override
public void onResume() {
    super.onResume();
    Bundle extras = getIntent().getExtras();
    Log.e(APP_TAG, "EXTRAS FROM RESUME: "+extras);

    if (extras != null && extras.getString("accountID") != null) {
        String accountParam = "";
        Log.e(APP_TAG, "AccountID in onResume: "+extras.getString("accountID")); 
        accountParam = "?accountID="+extras.getString("accountID");
        loadUrl("file:///android_asset/www/index.html"+accountParam);
    }
}

参数含义:

rsync -r --info=progress2 --filter=':- .gitignore' SOURCE DEST/ :递归

-r:显示进度

--info=...:排除.gitignore文件上列出的规则