シナリオ
git リポジトリの全履歴からいくつかのファイルを削除しようとしています。それらはすべて、いくつかの共通の基準を共有しています。
- ファイル名に「設定」が含まれています。ただし、さまざまな接頭辞と接尾辞がある場合もあります。
- それらは、ファイル ツリーの特定のディレクトリ内の2レベルの深さになります。第 2 レベルのディレクトリの名前はさまざまです。ファイル ツリーの奥には、削除してはならない設定ファイルがあります。
次に、ファイル ツリーの例を示します。
root-directory/
|-> apples/
| |-> bad-settings-alpha.txt
| |-> bad-settings-beta.txt
|
|-> oranges/
| |-> bad-settings-gamma.txt
| |-> bad-settings-delta.txt
| |-> navels/
| |-> good-settings.txt
|
|-> good-settings.txt
bad-settings
ファイルを保持しながら、すべてのファイルを除外する必要がありgood-settings
ます。
私のアプローチ
そこで、GitHub が提供するチュートリアルを git-rmのマンページと組み合わせて使用して、次のコマンドを作成しました (2 行に分割)。
git filter-branch -f --index-filter 'git rm --dry-run --cached \
--ignore-unmatch root-directory/*/*settings*.txt' --prune-empty -- --all
ここで特に注目すべきは、私が使用したファイル グロブですroot-directory/*/*settings*.txt
。そのファイル グロブを で使用するとls
、削除したいファイルのリストが正確に取得されます。それで、うまくいくはずですよね?
どうやらそうではありません。そのグロブでコマンドを実行すると、2 より深いレベルの設定ファイルもすべて削除されます。上記のファイル ツリーの例でroot-directory/oranges/navels/good-settings.php
は、核攻撃を受けることを意味します。
私はこれを自分で解決しようとしました。ファイル グロブのバリエーションを試し、素晴らしい--dry-run
オプションを使用してgit-rm
. 何も機能していないように見えました-どのように行うかを理解できたのは、設定ファイルの削除を開始するファイルツリーの深さを変更することだけでした。
私の問題に非常に関連していると思われることが1つ見つかりました。のマンページにgit-rm
は、次の例があります。
git rm Documentation/\*.txt
Removes all *.txt files from the index that are under the Documentation
directory and any of its subdirectories.
Note that the asterisk * is quoted from the shell in this example; this
lets git, and not the shell, expand the pathnames of files and
subdirectories under the Documentation/ directory.
「...ディレクトリとそのサブディレクトリの下にあるインデックスからすべての...ファイルを削除します」は、実際に起こっていることと一致しています。本当に興味深いのは、引用されたアスタリスクの言及です。git-rm
これにより、ファイル グロブの展開を処理できることを理解していますbash
。わかった。しかし、それには次の疑問が残ります。
- なぜ私はそれをしたいのですか?
- アスタリスクを引用していないので、展開
bash
を行う必要があります。それが本当で、私のファイル グロブが で動作するls
場合、なぜ で動作しないのgit-rm
でしょうか?
上記の例のすぐ下にある例も見ましたが、私がやろうとしていることを実行しているようです。それでも、それは私には起こりません。さもなければ、私はここにいないでしょう。ただし、でファイル展開を行いたいことを確認しているようbash
です。