170

浅いサブモジュールを持つことは可能ですか? それぞれが長い歴史を持ついくつかのサブモジュールを含むスーパープロジェクトがあるため、そのすべての歴史を引きずって不必要に大きくなります。

私が見つけたのは、この未回答のスレッドだけです。

これを実装するにはgit-submodule をハックするだけでいいですか?

4

10 に答える 10

169

次のgit1.8.4 (2013 年 7 月)の新機能:

" git submodule update" は、サブモジュール リポジトリを浅く複製することもできます。

(そして git 2.10 Q3 2016 では、それを で記録できますgit config -f .gitmodules submodule.<name>.shallow true
この回答の最後を参照してください)

コミット 275cd184d52b5b81cb89e4ec33e540fb2ae61c1fを参照してください。

--depth「git submodule」の add コマンドと update コマンドにオプションを追加し、それを clone コマンドに渡します。これは、サブモジュールが巨大で、最新のコミット以外にはあまり関心がない場合に便利です。

テストが追加され、「サブモジュールの更新で pwd のシンボリック リンクを処理できる」というテストファイルの残りの部分に準拠するために、いくつかのインデント調整が行われました。

署名者: Fredrik Gustafsson<iveqy@iveqy.com>
承認者: Jens Lehmann<Jens.Lehmann@web.de>

つまり、これは機能します:

# add shallow submodule
git submodule add --depth 1 <repo-url> <path>
git config -f .gitmodules submodule.<path>.shallow true

# later unshallow
git config -f .gitmodules submodule.<path>.shallow false
git submodule update <path>

コマンドは任意の順序で実行できます。このgit submoduleコマンドは、実際のクローンを実行します (今回は深さ 1 を使用)。そして、git configコマンドは、後で再帰的にレポを複製する他の人のためにオプションを永続的にします。

例として、レポがあり、レポ at にサブモジュールとしてhttps://github.com/foo/bar追加したいとします。コマンドは次のようになります。https://github.com/lorem/ipsumpath/to/submodule

git submodule add --depth 1 git@github.com:lorem/ipsum.git path/to/submodule
git config -f .gitmodules submodule.path/to/submodule.shallow true

次の結果も同じです (逆の順序)。

git config -f .gitmodules submodule.path/to/submodule.shallow true
git submodule add --depth 1 git@github.com:lorem/ipsum.git path/to/submodule

次に誰かが を実行git clone --recursive git@github.com:foo/bar.gitすると、 の履歴全体https://github.com/foo/barが取り込まれますが、期待どおりにサブモジュールの浅いクローンしか作成されません。

と:

--depth

addこのオプションはおよびupdateコマンドに有効です。
指定されたリビジョン数に切り捨てられた履歴を持つ「浅い」クローンを作成します。


atwymanはコメントに次のように追加します。

私が知る限り、このオプションは、master非常に厳密に追跡しないサブモジュールには使用できません。深さ 1 を設定submodule updateすると、必要なサブモジュールのコミットが最新のマスターである場合にのみ成功します。 それ以外の場合は " fatal: reference is not a tree"になります。

それは本当です。
つまり、git 2.8 (2016 年 3 月) までです。2.8 では、submodule update --depthリモート リポジトリ HEAD の 1 つから SHA1 に直接到達できる場合でも、成功するチャンスがもう 1 つあります。

Stefan Beller ( )によるコミット fb43e31 (2016 年 2 月 24 日)を参照してください。 手伝い:浜野ジュニオC ( ) . ( 2016 年 2 月 26 日コミット 9671a76Junio C Hamanoによってマージされました)stefanbeller
gitster
gitster

サブモジュール: sha1 を直接取得することにより、必要な sha1 を取得することをより困難にします

Gerrit のサブモジュールも更新する変更をレビューする場合、一般的なレビュー方法は、パッチをローカルにダウンロードしてチェリー ピックしてテストすることです。
ただし、ローカルでテストするとgit submodule update、サブモジュールの対応するコミットがまだプロジェクト履歴の一部ではなく、提案された変更に過ぎないため、「 」は正しいサブモジュール sha1 の取得に失敗する場合があります。

がデフォルトのフェッチに含まれていない場合は、直接$sha1をフェッチしようとし$sha1ます。ただし、一部のサーバーは sha1 による直接フェッチをサポートしていないため、git-fetchすぐに失敗します。
sha1 がまだ不足していると、後でチェックアウト段階で失敗する可能性があるため、ここで失敗する可能性があります。


MVGは、コメントで fb43e31をコミットするよう指摘しています(git 2.9、2016 年 2 月)。

コミット fb43e31が欠落しているコミットを SHA1 ID で要求しているように思われるため、サーバーのおよびuploadpack.allowReachableSHA1InWant設定uploadpack.allowTipSHA1InWantはおそらくこれが機能するかどうかに影響します。私は今日 git list に投稿
を書き、いくつかのシナリオ、つまりコミットもタグである場合に、浅いサブモジュールの使用がどのようにうまく機能するかを指摘しました。 待って見てみましょう。

これが、fb43e31 がデフォルト ブランチのフェッチ後に特定の SHA1 のフェッチをフォールバックにした理由だと思います。
それにもかかわらず、「--depth 1」の場合は、早期に中止するのが理にかなっていると思います: リストされた ref のいずれも要求されたものと一致せず、SHA1 による要求がサーバーでサポートされていない場合は、意味がありません。どちらの方法でもサブモジュールの要件を満たすことができないため、何かをフェッチします。


2016 年 8 月更新 (3 年後)

Git 2.10 (2016 年第 3 四半期) では、次のことが可能になります。

 git config -f .gitmodules submodule.<name>.shallow true

詳細については、「余分な重みのない Git サブモジュール」を参照してください。


Git 2.13 (2017 年第 2 四半期) は、 Sebastian Schuberth ( )によるcommit 8d3047c (2017 年 4 月 19 日) を追加します。( 2017 年 4 月 20 日コミット 8d3047cSebastian Schuberthによってマージされました)sschuberth
sschuberth

このサブモジュールのクローンは、浅いクローン(履歴の深さ 1)として実行されます。

ただし、Ciro Santilliはコメントに追加します(詳細は彼の回答に記載されています) 。

shallow = trueon.gitmodulesを使用すると、リモートの HEAD によって追跡される参照にのみ影響します--recurse-submodules。ターゲットのコミットがブランチによって指されている場合でも、 を配置branch = mybranchした場合でも.gitmodules同様です。


Git 2.20 (2018 年第 4 四半期) ではサブモジュールのサポートが改善されており、ファイルが作業ツリーにないHEAD:.gitmodules場合にBLOB から読み取るように更新されています。.gitmodules

commit 2b1257e、commit 76e9bdc (2018 年 10 月 25 日)、およびcommit b5c259fcommit 23dd8f5commit b2faad4commit 2502ffccommit 996df4dcommit d1b13dfcommit 45f5ef3commit bcbc780 (05 Oct 2018) by Antonio Ospite ( ao2)を参照してください。
( 2018 年 11 月 13 日、コミット abb4824Junio C Hamanoによってマージされました)gitster

submodule.gitmodules:作業ツリーにない場合の読み取りをサポート

ファイルが作業ツリーで利用できない場合.gitmodulesは、インデックスと現在のブランチのコンテンツを使用してみてください。
これは、ファイルがリポジトリの一部であるが、スパース チェックアウトなどの何らかの理由でチェックアウトされていない場合をカバーします。

これにより、作業ツリーを完全に設定しなくても、少なくとも構成ファイルを読み取る ' ' コマンドを使用できるようになりますgit submodulegitmodules

への書き込みに.gitmodulesはファイルがチェックアウトされている必要があるため、 を呼び出す前にそれを確認してくださいconfig_set_in_gitmodules_file_gently

同様のチェックを追加して、安全に書き込み可能でない場合に " " コマンドgit-submodule.sh::cmd_add()が最終的に失敗することを予測します。これにより、コマンドが誤った状態でリポジトリを離れることを防ぎます (たとえば、サブモジュール リポジトリは複製されましたが、失敗したために更新されませんでした)。git submodule add.gitmodules.gitmodulesconfig_set_in_gitmodules_file_gently

さらに、config_from_gitmodules()グローバル オブジェクト ストアにアクセスするようになったため、関数を呼び出すすべてのコード パスを、グローバル オブジェクト ストアへの同時アクセスから保護する必要があります。
現在、これは でのみ発生するbuiltin/grep.c::grep_submodules()ため、 grep_read_lock()を含むコードを呼び出す前に呼び出してconfig_from_gitmodules()ください。

注: この新機能がまだ適切に動作しないまれなケースが 1 つあります:.gitmodules作業ツリーにないネストされたサブモジュールです。


注: Git 2.24 (2019 年第 4 四半期) では、サブモジュールの浅いクローンを作成するときに発生する可能性があった segfault が修正されています。

Ali Utku Selen ( )によるcommit ddb3c85 (2019 年 9 月 30 日)を参照してください。( 2019 年 10 月 9 日コミット 678a9caJunio C Hamanoによってマージされました)auselen
gitster


Git 2.25 (2020 年第 1 四半期) は、git submodule updateドキュメントを明確にします。

Philippe Blain ( )によるコミット f0e58b3 (2019 年 11 月 24 日)を参照してください。( 2019 年 12 月 5 日コミット ef61045Junio C Hamanoによってマージされました)phil-blain
gitster

doc: 'git submodule update' が欠落しているコミットをフェッチすることを述べます

支援者: Junio C Hamano
支援者: Johannes Schindelin
署名者: Philippe Blain

スーパープロジェクトに記録された SHA-1 が見つからない場合、 ' git submoduleupdate'はサブモジュール リモートから新しいコミットを取得します。これはドキュメントには記載されていませんでした。


警告: Git 2.25 (2020 年第 1 四半期) では、" git clone --recurse-submodules" と代替オブジェクト ストアとの間の相互作用の設計が適切ではありませんでした。

ドキュメントとコードは、ユーザーが失敗したときに、より明確な推奨事項を示すように教えられています。

コミット 4f3e57eコミット 10c64a0 (2019 年 12 月 2 日) by Jonathan Tan ( jhowtan)を参照してください。
( 2019 年 12 月 10 日、コミット 5dd1d59Junio C Hamanoによってマージされました)gitster

submodule--helper: 致命的な代替エラーについてアドバイスします

署名者: ジョナサン・タン
承認者: ジェフ・キング

で定義されたいくつかの浅いモジュールを使用してスーパープロジェクトを再帰的に複製し.gitmodules、次に " --reference=<path>" で再複製すると、エラーが発生します。例えば:

git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  master
git clone --recurse-submodules --branch=master -j8 \
  https://android.googlesource.com/platform/superproject \
  --reference master master2

次のエラーで失敗します:

fatal: submodule '<snip>' cannot add alternate: reference repository
'<snip>' is shallow

スーパープロジェクトの代替から計算された代替を追加できない場合は、この場合でも別の場合でも、" submodule.alternateErrorStrategy" 構成オプションを構成し、複製時--reference-if-ableに " " の代わりに " "を使用することをお勧めします。--reference

詳細は次のとおりです。

Git 2.25 (2020 年第 1 四半期) では、「git clone --recurse-submodules」と代替オブジェクト ストアとの間の相互作用が適切に設計されていませんでした。

Doc: submodule.alternateErrorStrategy について説明します

署名者: ジョナサン・タン
承認者: ジェフ・キング

コミット31224cbdc7 (" clone: recursive and reference option triggers submodule alternatives"、2016-08-17、Git v2.11.0-rc0 --バッチ #1に記載されているマージ) は Git にスーパープロジェクトで構成オプション " " および " "をサポートするように教えました.submodule.alternateLocationsubmodule.alternateErrorStrategy

submodule.alternateLocationスーパープロジェクトで" " が " " に構成されている場合superproject、そのスーパープロジェクトのサブモジュールが複製されるたびに、スーパープロジェクトからそのサブモジュールの類似の代替パスを計算し、それ$GIT_DIR/objects/info/alternatesを参照します。

" submodule.alternateErrorStrategy" オプションは、その代替が参照できない場合にどうなるかを決定します。
ただし、そのオプションが「die」に設定されていない場合に代替が指定されていないかのようにクローンが進行するかどうかは明確ではありません ( 31224cbdc7のテストで確認できます)。
したがって、それに応じて文書化してください。

config サブモジュールのドキュメントには、次のものが含まれるようになりました。

submodule.alternateErrorStrategy::

で計算されたサブモジュールの代替でエラーを処理する方法を指定しますsubmodule.alternateLocation
可能な値はignore、、、infoですdie
デフォルトはdieです。またはに設定されている場合、計算された代替にエラーがある場合、代替が指定されていないかのように複製が続行されること
に注意してください。ignoreinfo


注: " git submodule update --quiet" ( man )は、基になる( man )まで quiet オプションを伝播しませんでした。これは、Git 2.32 (2021 年第 2 四半期) で修正されています。git fetch

Nicholas Clark ( )によるcommit 62af4bd (2021 年 4 月 30 日)を参照してください。( 2021 年 5 月 11 日コミット 74339f8Junio C Hamanoによってマージされました)nwc10
gitster

submodule update: 基礎となるフェッチを " --quiet"で沈黙させます

署名者: Nicholas Clark

などのコマンド

$ git submodule update --quiet --init --depth=1

浅いクローンを含む場合は、シェル関数fetch_in_submodule,を呼び出します。シェル関数は を呼び出しますgit fetch。そこにオプションを
渡します。--quiet

于 2013-07-17T06:32:59.157 に答える
34

Git 2.9.0はサブモジュールの浅いクローンを直接サポートしているため、次のように呼び出すことができます。

git clone url://to/source/repository --recursive --shallow-submodules
于 2016-08-15T10:50:45.473 に答える
16

ライアンの答えに続いて、すべてのサブモジュールを反復処理し、それらを浅いクローンにするこの単純なスクリプトを思いつくことができました。

#!/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
于 2010-01-30T23:26:07.123 に答える
8

git-submodule の「ソース」を読むとgit submodule add、すでにリポジトリが存在するサブモジュールを処理できるようです。その場合...

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
$ git submodule add $remotesub1 $sub1
#repeat as necessary...

必要なコミットがサブモジュール リポジトリにあることを確認する必要があるため、適切な --depth を設定してください。

編集: 複数の手動サブモジュール クローンとそれに続く単一の更新で回避できる場合があります。

$ git clone $remote1 $repo
$ cd $repo
$ git clone --depth 5 $remotesub1 $sub1
#repeat as necessary...
$ git submodule update
于 2010-01-30T03:32:05.737 に答える
2

サブモジュールの正規の場所は離れていますか? もしそうなら、それらを一度複製してもよろしいですか?言い換えれば、頻繁なサブモジュールの (再) クローンによる無駄な帯域幅に苦しんでいるという理由だけで、浅いクローンが必要ですか?

ローカル ディスク領域を節約するために浅いクローンが必要な場合は、Ryan Graham の回答が適切な方法のようです。リポジトリが浅くなるように、手動でクローンを作成します。それが役に立つと思うなら、それgit submoduleをサポートするように適応してください。それについて質問するリストに電子メールを送ってください(それを実装するためのアドバイス、インターフェースに関する提案など)。私の意見では、建設的な方法で Git を強化することを真剣に望んでいる潜在的な貢献者を、そこの人々は非常に支持しています。

各サブモジュールの 1 つの完全なクローンを実行することに問題がない場合 (およびそれらを最新の状態に保つために後でフェッチする)、(Git 1.6.4 以降にある)の--referenceオプションを使用して、ローカル オブジェクト ストアを参照してみてください (例:正規のサブモジュール リポジトリのクローンをgit submodule update作成し、サブモジュールでこれらのローカル クローンを指すように使用します)。/を使用する前に、必ず/について読んでください。ミラーの参照に関する唯一の可能性のある問題は、それらが早送り以外の更新をフェッチすることになった場合です (ただし、reflog を有効にし、有効期限ウィンドウを拡張して、問題を引き起こす可能性のある放棄されたコミットを保持するのに役立てることができます)。限り、問題はないはずです。--mirror--referencegit clone --referencegit clone --shared--reference

  • ローカル サブモジュールのコミットを行わない、または
  • 標準リポジトリが公開する可能性のある非早送りによってぶら下がったままになっているコミットは、ローカルサブモジュールコミットの祖先ではありません。または
  • 正規のサブモジュールリポジトリで公開されている可能性のある非早送りに基づいて、ローカルサブモジュールのコミットを維持することに熱心です。

このようなものを使用していて、作業ツリーでローカル サブモジュールのコミットを実行する可能性がある場合は、チェックアウトされたサブモジュールによって参照される重要なオブジェクトがコミットされていないことを確認する自動化されたシステムを作成することをお勧めします。ミラーリポジトリにぶら下がったままにします(見つかった場合は、それらを必要とするリポジトリにコピーします)。

また、マンページにあるように、これらの意味を理解していない場合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サブモジュールの URL を編集してから、.git/configgit submodule update. ハードリンクを取得するには、既存のチェックアウトされたサブモジュールを再クローン化する必要があります。ミラーに一度ダウンロードするだけで帯域幅を節約し、それらからチェックアウトしたサブモジュールにローカルにフェッチします。ハード リンクはディスク スペースを節約します (ただし、フェッチは蓄積され、チェックアウトされたサブモジュールのオブジェクト ストアの複数のインスタンス間で複製される傾向があります。ミラーからチェックアウトされたサブモジュールを定期的に再クローン化して、ディスク スペースの節約を取り戻すことができます。ハードリンク)。

于 2010-01-30T15:08:07.710 に答える