Rsyncには、「CVSと同じ方法でファイルを無視する」ための気の利いたオプション--cvs-exclude
が含まれていますが、CVSは長年廃止されています。最新のバージョン管理システム(Git、Mercurial、Subversion)で無視されるファイルも除外する方法はありますか?
たとえば、GitHubから多数のMavenプロジェクトをチェックアウトしています。通常、少なくともtarget
をリストする.gitignore
、デフォルトのMavenビルドディレクトリ(トップレベルまたはサブモジュールに存在する場合があります)が含まれます。これらのディレクトリの内容は完全に使い捨てであり、ソースコードよりもはるかに大きくなる可能性があるため、バックアップにrsyncを使用する場合は除外します。
もちろん、明示的に--exclude=target/
することもできますが、それは偶然target
という名前で、無視されるはずのない無関係なディレクトリを誤って抑制します。
そして、ディスク上の.gitignore
、.hgignore
、またはsvn:ignore
プロパティで言及されているすべてのファイル名とパターンの絶対パスの完全なリストを提供することもできますが、これは巨大なリストです何らかのスクリプトで作成する必要があります。
RsyncにはCVS以外のVCSチェックアウトのサポートが組み込まれていないため、無視パターンを入力するための良いトリックはありますか?または、特定のファイル/ディレクトリを含めるかどうかをユーザースクリプトに問い合わせることができる、何らかのコールバックシステムですか?
更新:LordJavacが示唆する--filter=':- .gitignore'
は、少なくとも私が見つけた例では、--filter=:C
がCVSに対して行うように、Gitに対しても同様に機能するようです。構文は完全一致です。 --filter=':- .hgignore'
は、Mercurialではあまり機能しません。例えば.hgignore
(Git ^target$
に相当するMercurialのような行を含む/target/
は、rsyncによって正規表現として認識されません。また、Subversionでは何も機能しないようです。この場合、1.6以前の作業コピーでは.svn/dir-prop-base
を解析し、1.7以降の作業コピーではがっかりして手を放さなければなりません。
Luksanが述べたように、--filter
をrsync
に切り替えることでこれを行うことができます。 --filter=':- .gitignore'
( ".gitignore"の前にスペースがあります)でこれを達成しました。これはrsync
に.gitignore
ファイルとディレクトリマージを行い、gitのルールごとに除外するよう指示します。グローバル無視ファイルがある場合は、追加することもできます。使いやすくするために、フィルターを含むrsync
のエイリアスを作成しました。
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>
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の代わりに--exclude-from
が必須です。これは、除外リストが引数として解析されない可能性が高いためです。 Exclude fromにはファイルが必要であり、パイプでは機能しません。
現在のソリューションでは、除外ファイルを.gitフォルダー内に保存して、git status
に影響を与えないようにします。必要な場合は、/ tmpを使用してください。
rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination
?
それは私のために働いた。
もっと多くの--exclude-from
パラメータも。
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します。注意:hg status -iは除外されたファイルのみをリストするため、空のディレクトリを同期から除外するrsyncのフラグ-mダース
これを試して:
rsync -azP --delete --filter=":- .gitignore" <SRC> <DEST>
「.gitignore」のファイルを除くすべてのファイルをリモートディレクトリにコピーし、現在のディレクトリにないファイルを削除できます。
非常に大きな.gitignore
ファイルと「純粋なrsync」ソリューションのどれも私のために働いた。これを書きました rsync wrapper script 、.gitignore
ルール(include !
スタイルの例外と.gitignore
ファイルがサブディレクトリにあります)、私にとっては魅力的な働きをしました。
ファイルパターンの標準リストに加えて、rsync
のマニュアルページごと:
$ HOME/.cvsignoreにリストされているファイルはリストに追加され、CVSIGNORE環境変数にリストされているすべてのファイル
したがって、私の$ HOME/.cvsignoreファイルは次のようになります。
.git/
.sass-cache/
.gitと Sass によって生成されたファイルを除外します。
Rsync(1)のMERGE-FILES FILTER RULESセクションを確認してください。
ディレクトリ構造を走査するときに.gitignoreファイルを含むrsync --filterルールを作成できるようです。
除外フィルターを作成する代わりに、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
は、改行で区切られたパスを返します。ファイル名にスペースを含むバージョン管理されたファイルがある場合、おそらく動作しません。
代替案:
git ls-files -zi --exclude-standard |rsync -0 --exclude-from=- ...
git ls-files -zi --exclude-per-directory=".gitignore" |...
(rsyncは.gitignoreを部分的にしか理解しません)