GitHub 上のリポジトリから、特定のディレクトリ以下のファイルをローカルにダウンロードしたい。
リポジトリのアセットをダウンロードしたいだけなのに、クローンして、コピーして、削除するのに苦労してます。
git の標準機能には「無駄なファイルを取得しないよう、特定ディレクトリだけをチェックアウトする(リポジトリからローカルに持ち出す)仕組み」があります。
git clone --filter=blob:none --no-checkout https://github.com/OWNER/REPO.git
cd REPO
git sparse-checkout init --cone
git sparse-checkout set path/to/dir
git checkout
-
--filter=blob:none
→ ファイル内容を必要になるまで取得しないオプション(partial clone) -
sparse-checkout
→ 指定ディレクトリのみ展開するサブコマンド
しかし「特定ディレクトリ以下をダウンロードしたいだけ」なのに、この長さは、いかんせん覚えられないのです。そこで、git のサブコマンドとして登録することにしました。
そんな機能があったことや、サブコマンドを作ってたことすら忘れそうなので、未来の自分のググラビリティ(備忘録)として。
Git External Subcommand
git には、パスの通ったディレクトリに git-<サブコマンド> 形式の実行可能ファイル名を見つけたら、そのまま渡して実行する機能があります。
つまり、git-foo というファイル名で、実行権限付きでパス内に設置しておけば、git foo として実行できるということです。
例えば、git foo --version の場合、実質的に git-foo --version を実行しているのと同じ扱いになります。
これは、git alias のように .gitconfig をいじる必要はなく、コマンドを設置するだけで済みます。
git sparse コマンド
以下は、各種ポカヨケだけでなく、リポジトリ・ルートにあるライセンスも含めてダウンロードする bash スクリプトです。
インストール
- 記事下部のスクリプトを
git-sparseファイルにコピペし、パスの通ったディレクトリに設置- Windows の場合は以下のコラムを参照
- スクリプトに実行権限を与える
chmod +x git-sparse
- 新規シェルで
git-sparse -hでパスが通っているか確認する
Windows の場合は若干注意が必要です。
Windows 環境では git-sparse.sh のように、ファイル名に拡張子が必須になります(Git Bash, Git Bash + WSL2)
Git Bash のみで WSL2 環境を利用していない場合、git-sparse.sh を検知しないことがあります。
その場合は、git-sparse.sh に加え git-sparse.cmd のラッパーが必要です。
@echo off
bash "%~dp0\git-sparse.sh" %*
使い方
以下は、Qiita Markdown の spec ディレクトリをローカルにダウンロードする具体的な例です。空のディレクトリで作業してください。
シンプル
git sparse https://github.com/increments/qiita-markdown.git qiita-markdown/spec ./foo
ブランチ指定
git sparse https://github.com/increments/qiita-markdown.git https://github.com/increments/qiita-markdown/tree/0-stable/spec ./foo
スクリプト本体 @ Gist