Gitで出来るだけ無駄なくリモートリポジトリの特定のファイルをダウンロードする
目的
Gitのリモートリポジトリ内の特定のファイルをダウンロードしたいのですが、普通にgit clone
するとリポジトリ全体を落として来ちゃうのでできるだけ無駄なくできないかと調べました
ブラウザからダウンロードしたりwgetなどで直接URLを叩く方法もありそうですが、今回は認証をgitコマンド任せにして処理はプログラムで書くようにしたかったのでgit clone
でどうにかするようにしました
コマンド
git clone --filter=tree:0 --no-tags --no-checkout --sparse <url> <dir>
cd <dir>
git sparse-checkout set --no-cone <file_path>
git checkout <commit>
いろいろ調べた結果、こんな感じになりました
環境
Windows 11 23H2
git version 2.47.1.windows.2
git clone
できるだけ無駄なデータを取得せずにクローンします
git clone --filter=tree:0 --no-tags --no-checkout --sparse <url> <dir>
--filter=tree:0
ツリーレスクローンにすることで履歴データの大部分を取得しないようしています
こちらの記事がわかりやすかったです
--no-tags
タグ情報をダウンロードしないようにしています
--no-checkout
この時点ではまだチェックアウトを行わないようにしています
--sparse
後述のsparse-checkoutの機能を有効化しています
git sparse-checkout
リポジトリから必要なファイルのみをチェックアウトして作業ツリーを最適化するためのコマンドです
目的のファイルのパスを登録します
git sparse-checkout set --no-cone <file_path>
--no-cone
sparse-checkoutにはコーンモードと非コーンモードがあり、
コーンモードではルート直下とパス上の兄弟ファイルもチェックアウトする挙動になります
if you specified the directory Documentation/technical/ then your sparse checkout would contain:
- all files in the toplevel-directory
- all files immediately under Documentation/
- all files at any depth under Documentation/technical/
https://git-scm.com/docs/git-sparse-checkout#_internalscone_mode_handling
コーンモードの方が新しい方式でパフォーマンスも良さそうなのですが、今回は対象のファイルをダウンロードしたいだけなので無駄なファイルをダウンロードしない非コーンモード--no-cone
を指定します
git checkout
git checkout <commit>
最後にチェックアウトするとsparse-checkoutで指定したファイルのみが作業ディレクトリに生成されます
このタイミングで必要なデータがリモートリポジトリからダウンロードされます
ちなみにgit clone
に--no-checkout
のオプションをつけていないとsparse-checkout設定前のクローン時にチェックアウトが走り不要なファイルまでダウンロードしてしまいます
ダメだった方法
git archive
git archive --remote=<repo>
がまさに今回のような用途の機能っぽいのですがGitHubでは非対応みたいです[1]
今回はGitHubも対象にしたいので他の方法にしました
参照
Discussion