浅いサブモジュールを持つことは可能ですか?私はそれぞれ長い歴史を持ついくつかのサブモジュールを持つスーパープロジェクトを持っているので、そのすべての歴史をドラッグすることは不必要に大きくなります。
私が見つけたのは この未回答のスレッド だけです。
git-submoduleをハックする を実装するだけですか?
今後の git1.8.4(2013年7月) の新機能:
「
git submodule update
」は、オプションでサブモジュールリポジトリを浅く複製できます。
(そしてgit 2.10 Q3 2016では、git config -f .gitmodules submodule.<name>.shallow true
で記録できます。
この回答の最後をご覧ください)
commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1f を参照してください:
「git submodule」の追加および更新コマンドに
--depth
オプションを追加し、クローンコマンドに渡されます。これは、サブモジュールが巨大であり、最新のコミット以外に本当に興味がない場合に便利です。テストが追加され、「サブモジュールの更新はpwdのシンボリックリンクを処理できます」のテストファイルの残りの部分に適合するように、インデントの調整が行われました。
サインオフ:Fredrik Gustafsson
<[email protected]>
Acked-by:Jens Lehmann<[email protected]>
これはこれが機能することを意味します:
git submodule add --depth 1 -- repository path
git submodule update --depth -- [<path>...]
と:
--depth::
このオプションは、
add
およびupdate
コマンドに有効です。
指定されたリビジョン数に切り捨てられた履歴を持つ「浅い」クローンを作成します。
私が知る限り、このオプションは
master
を非常に厳密に追跡しないサブモジュールには使用できません。深さ1を設定すると、submodule update
は、目的のサブモジュールコミットが最新のマスターである場合にのみ成功します。 それ以外の場合は、「fatal: reference is not a tree
」を取得します。
それは本当です。
つまり、git 2.8(2016年3月)までです。 2.8では、SHA1がリモートリポジトリHEADの1つから直接到達可能である場合でも、submodule update --depth
が成功する可能性がもう1つあります。
Stefan Beller(stefanbeller
) による commit fb43e312016年2月24日)を参照してください。
ヘルプ: Junio C Hamano(gitster
) 。
( Junio C Hamano-gitster
- in commit 9671a76 、2016年2月26日)
サブモジュール:sha1を直接取得して、必要なsha1を取得しようとする
Gerritのサブモジュールも更新する変更を確認する場合、一般的な確認方法は、パッチをダウンロードしてチェリーピックしてローカルでテストすることです。
ただし、ローカルでテストする場合、サブモジュール内の対応するコミットはまだプロジェクト履歴の一部ではなく、提案された変更であるため、「git submodule update
」は正しいサブモジュールsha1のフェッチに失敗する場合があります。
$sha1
がデフォルトフェッチの一部ではなかった場合、$sha1
を直接フェッチしようとします。ただし、一部のサーバーはsha1による直接フェッチをサポートしていないため、git-fetch
がすぐに失敗します。
まだ見つからないsha1がチェックアウト段階の後半で失敗するため、ここで失敗する可能性があります。
[〜#〜] mvg [〜#〜] が指摘する コメント内の から commit fb43e31 (git 2.9、2016年2月)
commit fb43e31 はSHA1 idで欠落しているコミットを要求しているように思われるので、サーバー上の
uploadpack.allowReachableSHA1InWant
およびuploadpack.allowTipSHA1InWant
設定はおそらくこれが機能するかどうかに影響します。
私は 今日のgitリストへの投稿 を書いて、いくつかのシナリオ、つまりコミットもタグである場合、浅いサブモジュールの使用をよりうまく機能させる方法を指摘しました。
待って見てみましょう。これが、fb43e31がデフォルトのブランチのフェッチ後に特定のSHA1のフェッチをフォールバックにした理由だと思います。
それにもかかわらず、「-depth 1」の場合、早めに中止するのが理にかなっていると思います。リストされたrefのいずれも要求されたrefと一致せず、SHA1による問い合わせがサーバーによってサポートされていないどちらの方法でもサブモジュールの要件を満たすことができないため、何かをフェッチしても意味がありません。
2016年8月更新(3年後)
Git 2.10(Q3 2016)では、次のことができるようになります
git config -f .gitmodules submodule.<name>.shallow true
詳細については、「 余分な重みのないGitサブモジュール 」を参照してください。
Git 2.13(2017年第2四半期) commit 8d3047c (2017年4月19日)によって Sebastian Schuberth(sschuberth
) を追加します。
( Sebastian Schuberth-sschuberth
- in commit 8d3047c 、2017年4月20日)
このサブモジュールのクローンは、浅いクローンとして実行されます(履歴の深さ1)
ただし、 Ciro Santilli は コメントに を追加します(詳細は 彼の回答 )
shallow = true
上の.gitmodules
は、ターゲットコミットがブランチによってポイントされている場合でも、--recurse-submodules
をbranch = mybranch
に配置している場合でも、.gitmodules
を使用する場合、リモートのHEAD 。
Git 2.20(2018年第4四半期)では、サブモジュールのサポートが改善され、HEAD:.gitmodules
ファイルが作業ツリーにない場合に.gitmodules
のblobから読み取るように更新されました。
commit 2b1257e 、 commit 76e9bdc (2018年10月25日)、および commit b5c259f 、 commit 23dd8f5 、 commit b2faad4 を参照してください_、 commit 2502ffc 、 commit 996df4d 、 commit d1b13df 、 commit 45f5ef 、 commit bcbc78 (2018年10月5日)by Antonio Ospite(ao2
) 。
( Junio C Hamano-gitster
- in commit abb4824 、2018年11月13日)
submodule
:作業ツリーにない場合の.gitmodules
の読み取りをサポート
.gitmodules
ファイルが作業ツリーで利用できない場合、インデックスと現在のブランチのコンテンツを使用してみてください。
これは、ファイルがリポジトリの一部であるが、何らかの理由で、たとえばスパースチェックアウトのためにチェックアウトされない場合を対象としています。これにより、少なくとも「
git submodule
」コマンドを使用できるようになります。このコマンドは、作業ツリーに完全に入力することなく、_(readgitmodules
構成ファイルを読み取ります。
.gitmodules
への書き込みでは、ファイルをチェックアウトする必要があるため、config_set_in_gitmodules_file_gently
を呼び出す前にファイルをチェックアウトする必要があります。
git-submodule.sh::cmd_add()
にも同様のチェックを追加して、git submodule add
が安全に書き込み可能でない場合に「.gitmodules
」コマンドが最終的に失敗することを予測します。これにより、コマンドがリポジトリを誤った状態のままにするのを防ぎます(たとえば、サブモジュールリポジトリは複製されましたが、.gitmodules
が失敗したためconfig_set_in_gitmodules_file_gently
は更新されませんでした)。さらに、
config_from_gitmodules()
はグローバルオブジェクトストアにアクセスするため、グローバルオブジェクトストアへの同時アクセスから関数を呼び出すすべてのコードパスを保護する必要があります。
現在、これはbuiltin/grep.c::grep_submodules()
でのみ発生するため、grep_read_lock()
を含むコードを呼び出す前にconfig_from_gitmodules()
を呼び出してください。注:この新しい機能がまだ正しく機能しないまれなケースが1つあります。作業ツリーに
.gitmodules
のないネストされたサブモジュールです。
Git 2.9. サブモジュールの浅いクローンを直接サポートするため、次のように呼び出すことができます:
git clone url://to/source/repository --recursive --shallow-submodules
次の Ryanの答え すべてのサブモジュールを反復処理し、それらを浅く複製するこの単純なスクリプトを思いつくことができました。
#!/bin/bash
git submodule init
for i in $(git submodule | sed -e 's/.* //'); do
spath=$(git config -f .gitmodules --get submodule.$i.path)
surl=$(git config -f .gitmodules --get submodule.$i.url)
git clone --depth 1 $surl $spath
done
git submodule update
Git-submodule "source"を読むと、git submodule add
は、すでにリポジトリが存在するサブモジュールを処理できます。その場合...
$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...
必要なコミットがサブモジュールリポジトリにあることを確認する必要があるため、適切な--depthを設定してください。
編集:複数の手動サブモジュールクローンに続いて1つの更新を行うことができます。
$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update
Git 2.14.1以降のバグのある/予期しない/迷惑な動作の概要
_shallow = true
_の_.gitmodules
_は、リモートサブモジュールのHEAD
が必要なコミットを指している場合、ターゲットコミットがブランチによってポイントされている場合でも、_git clone --recurse-submodules
_にのみ影響します。 _branch = mybranch
_にも_.gitmodules
_を配置した場合。
ローカルテストスクリプト 。 HEAD
がデフォルトのブランチリポジトリ設定によって制御されるGitHub 2017-11での同じ動作:
_git clone --recurse-submodules https://github.com/cirosantilli/test-shallow-submodule-top-branch-shallow
cd test-shallow-submodule-top-branch-shallow/mod
git log
# Multiple commits, not shallow.
_
_git clone --recurse-submodules --shallow-submodules
_は、コミットがブランチまたはメッセージのタグで参照されていない場合に失敗します:_error: Server does not allow request for unadvertised object
_。
ローカルテストスクリプト 。 GitHubでの同じ動作:
_git clone --recurse-submodules --shallow-submodules https://github.com/cirosantilli/test-shallow-submodule-top-sha
# error
_
また、私はメーリングリストで尋ねました: https://marc.info/?l=git&m=151863590026582&w=2 そして返信は:
理論的には、これは簡単なはずです。 :)
残念ながら、実際にはそれほどではありません。これは、クローン作成がブランチの最新のチップ(通常はマスター)を取得するだけだからです。 cloneには、必要なsha1を正確に指定するメカニズムはありません。
ワイヤプロトコルは、正確なsha1を要求することをサポートしているため、これをカバーする必要があります。 (注意:githubがAFAICTを持たないuploadpack.allowReachableSHA1InWantをサーバーオペレーターが有効にしている場合にのみ機能します)
git-fetchは任意のsha1をフェッチできるため、回避策として、「git submodule update」を使用して再帰クローンの後にフェッチを実行できます。初期クローンの後にフェッチを使用するためです。
TODOテスト: _allowReachableSHA1InWant
_ 。
サブモジュールの正規の場所はリモートですか?もしそうなら、一度クローンを作成しても大丈夫ですか?言い換えれば、頻繁にサブモジュール(再)クローンの帯域幅が浪費されているという理由だけで、浅いクローンが必要ですか?
浅いクローンでローカルディスク領域を節約したい場合、Ryan Grahamの答えは良い方法のように思えます。リポジトリが浅くなるように手動でクローンを作成します。役立つと思われる場合は、git submodule
を適応させてサポートしてください。 リスト にメールを送信します(実装のアドバイス、インターフェースに関する提案など)。私の意見では、建設的な方法でGitを強化したい潜在的な貢献者を非常に支持しています。
各サブモジュールの完全なクローンを1つ作成することに問題がない場合(さらに最新の状態に保つために後でフェッチする)、--reference
のgit submodule update
オプションを使用してみてください(Git 1.6.4および後で)ローカルオブジェクトストアを参照する(たとえば、正規のサブモジュールリポジトリの--mirror
クローンを作成し、サブモジュールで--reference
を使用してこれらのローカルクローンを指す)。 git clone --reference
を使用する前に、必ずgit clone --shared
/--reference
について読んでください。ミラーの参照に関する唯一の問題は、非早送りの更新を取得する場合です(ただし、reflogsを有効にして有効期限ウィンドウを拡張し、問題を引き起こす可能性のある放棄されたコミットを保持することができます)。限り問題はないはずです
このようなもので、作業ツリーでローカルサブモジュールコミットを実行する可能性がある場合は、チェックアウトされたサブモジュールによって参照される重要なオブジェクトがそうでないことを確認する自動システムを作成することをお勧めします。ミラーリポジトリにぶら下がっています(見つかった場合は、それらを必要とするリポジトリにコピーします)。
また、git clone
のマンページにあるように、これらの影響を理解していない場合は、--reference
を使用しないでください。
# Full clone (mirror), done once.
git clone --mirror $sub1_url $path_to_mirrors/$sub1_name.git
git clone --mirror $sub2_url $path_to_mirrors/$sub2_name.git
# Reference the full clones any time you initialize a submodule
git clone $super_url super
cd super
git submodule update --init --reference $path_to_mirrors/$sub1_name.git $sub1_path_in_super
git submodule update --init --reference $path_to_mirrors/$sub2_name.git $sub2_path_in_super
# To avoid extra packs in each of the superprojects' submodules,
# update the mirror clones before any pull/merge in super-projects.
for p in $path_to_mirrors/*.git; do GIT_DIR="$p" git fetch; done
cd super
git pull # merges in new versions of submodules
git submodule update # update sub refs, checkout new versions,
# but no download since they reference the updated mirrors
または、--reference
の代わりに、ローカルミラーをサブモジュールのソースとして使用することにより、ミラークローンをgit clone
のデフォルトのハードリンク機能と組み合わせて使用できます。新しいスーパープロジェクトのクローンでは、git submodule init
を実行し、.git/config
のサブモジュールURLを編集してローカルミラーを指すようにしてから、git submodule update
を実行します。ハードリンクを取得するには、既存のチェックアウト済みサブモジュールを複製する必要があります。ミラーに一度ダウンロードするだけで帯域幅を節約し、それらからローカルにチェックアウトされたサブモジュールにフェッチします。ハードリンクはディスク領域を節約します(ただし、フェッチはチェックアウトされたサブモジュールのオブジェクトストアの複数のインスタンス間で蓄積され、複製される傾向があります。ミラーからチェックアウトされたサブモジュールを定期的に再クローンして、ディスク領域の節約を取り戻すことができますハードリンク)。
特定のリビジョン/変更セットでgitリポジトリをクローンする方法 への参照
サブモジュール参照がマスターから離れているときに問題のない単純なスクリプトを作成しました
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch Origin {} && git reset --hard FETCH_HEAD'
このステートメントは、サブモジュールの参照バージョンをフェッチします。
高速ですが、サブモジュールで編集をコミットすることはできません(事前に非浅いフェッチを行う必要があります https://stackoverflow.com/a/17937889/3156509 )
略さずに:
#!/bin/bash
git submodule init
git submodule foreach --recursive 'git rev-parse HEAD | xargs -I {} git fetch Origin {} && git reset --hard FETCH_HEAD'
git submodule update --recursive
サブモジュールの特定のリビジョン/変更セットでスナップショットを作成するため、サブモジュールの浅いクローンは完璧です。 WebサイトからZipをダウンロードするのは簡単なので、スクリプトを試しました。
#!/bin/bash
git submodule deinit --all -f
for value in $(git submodule | Perl -pe 's/.*(\w{40})\s([^\s]+).*/\1:\2/'); do
mysha=${value%:*}
mysub=${value#*:}
myurl=$(grep -A2 -Pi "path = $mysub" .gitmodules | grep -Pio '(?<=url =).*/[^.]+')
mydir=$(dirname $mysub)
wget $myurl/archive/$mysha.Zip
unzip $mysha.Zip -d $mydir
test -d $mysub && rm -rf $mysub
mv $mydir/*-$mysha $mysub
rm $mysha.Zip
done
git submodule init
git submodule deinit --all -f
は、スクリプトを再利用可能にするサブモジュールツリーをクリアします。
git submodule
は、.gitmodules
の同じ文字に対応するパスが後に続く40文字のsha1を取得します。 Perlを使用して、コロンで区切られたこの情報を連結し、変数変換を使用して値をmysha
とmysub
に分離します。
これらは重要なキーです。sha1をダウンロードする必要があり、.gitmodulesのurl
を関連付けるパスが必要だからです。
典型的なサブモジュールエントリが与えられた場合:
[submodule "label"]
path = localpath
url = https://github.com/repository.git
path =
のmyurl
キーは、値を取得するために2行後に見えます。この方法は一貫して機能せず、改良が必要な場合があります。 url grepは、最後の.git
および/
までのすべてと一致することにより、残りの.
型参照を除去します。
mydir
は、mysub
から最後の/name
を差し引いたもので、サブモジュール名に至るまでのディレクトリになります。
次は、ダウンロード可能なZipアーカイブURLの形式のwget
です。これは将来変更される可能性があります。
ファイルをmydir
に解凍します。これは、サブモジュールパスで指定されたサブディレクトリになります。結果のフォルダーは、url
-sha1
の最後の要素になります。
サブモジュールパスで指定されたサブディレクトリが存在するかどうかを確認し、削除して、抽出されたフォルダの名前を変更できるようにします。
mv
は、sha1を含む抽出されたフォルダーの名前を正しいサブモジュールパスに変更します。
ダウンロードしたZipファイルを削除します。
サブモジュールの初期化
これは、ソリューションというよりも、WIPの概念実証です。動作すると、指定されたチェンジセットにあるサブモジュールの浅いクローンが作成されます。
リポジトリがサブモジュールを別のコミットにリホームする場合は、スクリプトを再実行して更新します。
このようなスクリプトが役立つのは、ソースプロジェクトの非共同ローカルビルドの場合だけです。
すべてのプロジェクトが実行するわけではないが、最新のEdgeで実行されていない場合のために、わずかに異なるバージョンを作成しました。標準のサブモジュールの追加は機能せず、上記のスクリプトも機能しませんでした。そこで、タグrefのハッシュルックアップを追加し、ハッシュルックアップがない場合は、完全なクローンにフォールバックします。
#!/bin/bash
git submodule init
git submodule | while read hash name junk; do
spath=$(git config -f .gitmodules --get submodule.$name.path)
surl=$(git config -f .gitmodules --get submodule.$name.url)
sbr=$(git ls-remote --tags $surl | sed -r "/${hash:1}/ s|^.*tags/([^^]+).*\$|\1|p;d")
if [ -z $sbr ]; then
git clone $surl $spath
else
git clone -b $sbr --depth 1 --single-branch $surl $spath
fi
done
git submodule update