浅いサブモジュールを持つことは可能ですか?私はいくつかのサブモジュールを持つスーパープロジェクトを持っており、それぞれに長い履歴があるため、そのすべての履歴をドラッグすると不必要に大きくなります。
私が見つけたすべてはこの未回答のスレッドです。
これを実装するにはgit-submoduleをハックするだけですか?
浅いサブモジュールを持つことは可能ですか?私はいくつかのサブモジュールを持つスーパープロジェクトを持っており、それぞれに長い履歴があるため、そのすべての履歴をドラッグすると不必要に大きくなります。
私が見つけたすべてはこの未回答のスレッドです。
これを実装するにはgit-submoduleをハックするだけですか?
回答:
"
git submodule update
"は、オプションでサブモジュールリポジトリを浅くクローンできます。
(そしてgit 2.10 Q3 2016では、それをで記録できますgit config -f .gitmodules submodule.<name>.shallow true
。
この回答の最後を参照してください)
commit 275cd184d52b5b81cb89e4ec33e540fb2ae61c1fを参照してください。
追加
--depth
「git submodule」のaddコマンドとupdateコマンドにオプションをます。これは、その後cloneコマンドに渡されます。これは、サブモジュールが巨大で、最新のコミット以外には何も関心がない場合に便利です。テストが追加され、「サブモジュールの更新でpwdのシンボリックリンクを処理できる」に関するテストファイルの残りの部分に準拠するように、いくつかのインデント調整が行われました。
署名者:Fredrik Gustafsson
<iveqy@iveqy.com>
承認者:Jens Lehmann<Jens.Lehmann@web.de>
つまり、これは機能します:
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を使用するsubmodule update --depth
と、リモートリポジトリヘッドの1つからSHA1に直接到達できる場合でも、が成功するチャンスがもう1つあります。
参照してくださいfb43e31コミットすることにより(2016年2月24日)ステファンBellerを(stefanbeller
)。
協力者:ジュニオC浜野(gitster
)。
(合併によりJunio C浜野- gitster
-で9671a76コミットし、2016年2月26日)を
サブモジュール:sha1を直接フェッチすることにより、必要なsha1をフェッチするためにさらに努力する
Gerritのサブモジュールも更新する変更を確認する場合、一般的な確認方法は、パッチをダウンロードしてローカルで選択してテストすることです。
ただし、ローカルでテストする場合git submodule update
、サブモジュール内の対応するコミットがプロジェクト履歴の一部ではなく、提案された変更であるため、 ' 'は正しいサブモジュールsha1のフェッチに失敗する可能性があります。
$sha1
がデフォルトのフェッチの一部でない場合は、$sha1
直接フェッチを試みます。ただし、一部のサーバーはsha1による直接フェッチをサポートしていないため、git-fetch
すぐに失敗します。
まだ抜けているsha1はとにかくチェックアウトステージで失敗につながるため、ここで失敗する可能性があります。したがって、ここで失敗しても、できる限りのことです。
MVG はコメントでfb43e31をコミットすることを指摘しています(git 2.9、2016年2月)
commit fb43e31がSHA1 idによる欠落しているコミットを要求しているように思えるので、サーバーの
uploadpack.allowReachableSHA1InWant
およびuploadpack.allowTipSHA1InWant
設定はおそらくこれが機能するかどうかに影響します。今日、gitリストへの投稿
を書いて、浅いサブモジュールの使用をいくつかのシナリオで、つまりコミットがタグでもある場合に、よりうまく機能させる方法を指摘しました。 待って見てみましょう。これが、fb43e31が特定のSHA1のフェッチをデフォルトブランチのフェッチ後のフォールバックにした理由だと思います。
それでも、「-depth 1」の場合、早期に中止することは理にかなっていると思います。リストされた参照のいずれも要求された参照と一致せず、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()によるコミット8d3047c(2017年4月19日)を追加します。(による合併セバスチャンシューベルト- -で8d3047cをコミットし、2017年4月20日)sschuberth
sschuberth
このサブモジュールのクローンは、浅いクローンとして実行されます(履歴の深さは1)
ただし、Ciro Santilliはコメント(および彼の回答の詳細)を追加しています
shallow = true
.gitmodules
のみ使用する際の基準は、リモートのHEADによって追跡影響--recurse-submodules
ターゲットがコミットしても、ブランチで指され、あなたが入れた場合でも、branch = mybranch
上.gitmodules
にも。
Git 2.20(2018年第4四半期)はHEAD:.gitmodules
、.gitmodules
ファイルが作業ツリーから欠落しているときにblobから読み取るように更新されたサブモジュールのサポートを改善しました。
見る 2b1257eをコミットし、76e9bdcコミット(2018年10月25日)、およびb5c259fコミット、23dd8f5をコミットし、b2faad4コミット、2502ffcコミット、996df4dをコミットし、d1b13dfをコミットし、45f5ef3をコミットし、bcbc780コミットすることにより(2018年10月5日)アントニオ・Ospiteを(ao2
)。
(合併によりJunio C浜野- gitster
-でabb4824コミット 2018年11月13日)
submodule
:.gitmodules
作業ツリーにないときの読み取りをサポート
.gitmodules
ファイルが作業ツリーで使用できない場合は、インデックスと現在のブランチのコンテンツを使用してみてください。
これは、ファイルがリポジトリの一部であるが、何らかの理由で、たとえばスパースチェックアウトのためにチェックアウトされない場合をカバーします。これにより、少なくとも作業ツリーにデータを
git submodule
入力せずに構成ファイルを読み取る ' 'コマンドを使用できるようになりgitmodules
ます。への書き込みで
.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.24(2019年第4四半期)では、サブモジュールのシャローを複製するときに発生する可能性があったsegfaultが修正されています。
Ali Utku Selen()によるcommit ddb3c85(2019年9月30日)を参照してください。(合併によりJunio C浜野- -で678a9caコミット 2019年10月9日)auselen
gitster
Git 2.25(2020年第1四半期)、git submodule update
ドキュメントを明確化。
Philippe Blain()によるcommit f0e58b3(2019年11月24日)を参照してください。(合併によりJunio C浜野- -でef61045コミット 2019年12月5日)phil-blain
gitster
doc
: 'git submodule update'が不足しているコミットをフェッチすることを言及支援者:Junio C Hamano
支援者:Johannes Schindelin承認者
:Philippe Blainスーパープロジェクトに記録されたSHA-1が見つからない場合、 '
git submodule
update' はサブモジュールリモートから新しいコミットをフェッチします。これはドキュメントでは言及されていません。
警告:Git 2.25(2020年第1四半期)では、 " git clone --recurse-submodules
"と代替オブジェクトストアの間の相互作用が不適切に設計されていました。
ドキュメントとコードは、ユーザーが失敗を見つけたときに、より明確な推奨を行うように教えられています。
参照4f3e57eをコミットし、10c64a0コミットにより(2019年12月2日)のジョナサン・タン(jhowtan
)に。
(合併によりJunio C浜野- gitster
-で5dd1d59コミットし、2019年12月10日)を
submodule--helper
:致命的な代替エラーに関するアドバイスサインオフ:Jonathan Tan
Acked-by:ジェフキングで定義されたいくつかの浅いモジュールを持つスーパー
.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の説明サインオフ:Jonathan Tan
Acked-by:ジェフキングコミット31224cbdc7( "
clone
:再帰的および参照オプションがサブモジュールの代替をトリガーする"、2016-08-17、Git v2.11.0-rc0- バッチ#1にリストされているマージ)Gitに構成オプションをサポートするように教えたsubmodule.alternateLocation
"および "submodule.alternateErrorStrategy
"。「
submodule.alternateLocation
」が「」に設定されている場合superproject
スーパープロジェクトで、そのスーパープロジェクトのサブモジュールが複製されるときは常に、スーパープロジェクトからそのサブモジュールの類似の代替パスが計算され、$GIT_DIR/objects/info/alternates
参照されます。「
submodule.alternateErrorStrategy
」オプションは、その代替が参照できない場合にどうなるかを決定します。
ただし、そのオプションが "die"に設定されていない場合(31224cbdc7のテストで確認できるように)、代替が指定されていないかのようにクローンが進行するかどうかは明確ではありません。
したがって、それを文書化してください。
設定サブモジュールのドキュメントは今含まれています:
submodule.alternateErrorStrategy::
を介して計算されたサブモジュールの代替でエラーを処理する方法を指定します
submodule.alternateLocation
。
可能な値はignore
、info
、die
。
デフォルトはdie
です。またはに
設定され、計算された代替にエラーがある場合、クローンは代替が指定されていないかのように続行することに注意してください。ignore
info
--depth
shoudlも議論をします;)
uploadpack.allowReachableSHA1InWant
およびuploadpack.allowTipSHA1InWant
設定はおそらくこれが機能するかどうかに影響します。今日はgitリストへの投稿を書いて、浅いサブモジュールを使用すると、いくつかのシナリオで、つまりコミットもタグである場合に、どのようにうまく機能するかを指摘しました。待って見てみましょう。
.gitmodules
が機能し--depth 1
ますか?
Git 2.9.0は、サブモジュールの浅い複製を直接サポートするため、次のように呼び出すことができます。
git clone url://to/source/repository --recursive --shallow-submodules
ライアンの答えに続いて、すべてのサブモジュールを反復処理して浅いクローンを作成するこの簡単なスクリプトを思いつくことができました。
#!/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
fatal: reference is not a tree: 88fb67b07621dfed054d8d75fd50672fb26349df
各サブモジュールを取得しています
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
in は、リモートサブモジュールのが必要なコミットを指している場合に.gitmodules
のみ影響しgit clone --recurse-submodules
ます。HEAD
ターゲットコミットがブランチによって指し示されている場合でも、をbranch = mybranch
オンにした場合でも.gitmodules
同様です。
ローカルテストスクリプト。GitHub 2017-11での同じ動作。HEAD
デフォルトのブランチリポジトリ設定によって制御されます。
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そして、返答は:
理論的には、これは簡単なはずです。:)
残念ながら実際にはそれほどではありません。これは、クローン作成がブランチ(通常はマスター)の最新のヒントを取得するためです。クローンには、必要な正確なsha1を指定するメカニズムはありません。
ワイヤープロトコルは、正確なsha1sを要求することをサポートしているため、カバーする必要があります。(警告:サーバーオペレーターがgithubがAFAICTではないuploadpack.allowReachableSHA1InWantを有効にしている場合にのみ機能します)
git-fetchは任意のsha1をフェッチできるため、回避策として、「git submodule update」を使用して再帰的クローンの後にフェッチを実行できます。これは、最初のクローンの後にフェッチを使用するためです。
TODOテスト:allowReachableSHA1InWant
。
git clone --recursive
その特定のコミットのみをフェッチするダウンストリームユーザーがいる単純な方法はないようです。
サブモジュールの正規の場所はリモートですか?もしそうなら、一度それらを複製しても大丈夫ですか?言い換えれば、頻繁なサブモジュール(再)クローンの無駄な帯域幅に苦しんでいるという理由だけで、浅いクローンが必要ですか?
浅いクローンでローカルのディスクスペースを節約したい場合、Ryan Grahamの答えは良い方法のようです。リポジトリが浅くなるように手動で複製します。役立つと思われる場合は、git submodule
サポートに対応してください。リストにメールを送信するそれについて尋ねる(それを実装するためのアドバイス、インターフェースの提案など)。私の意見では、Gitを建設的な方法で強化したいと真剣に考えている潜在的な貢献者を支持している人々がいます。
各サブモジュールの1つの完全なクローンを作成することに問題がなければ(さらに、最新の状態に保つために後でフェッチする)、ローカルオブジェクトストア(たとえば、Git 1.6.4以降)の--reference
オプションを使用してみてgit submodule update
ください。--mirror
正規のサブモジュールリポジトリのクローンを作成--reference
し、サブモジュールでこれらのローカルクローンを指すように使用します)。使用する前にgit clone --reference
/ について必ずお読みください。参照ミラーで起こりそうな唯一の問題は、最終的に非早送りの更新をフェッチしてしまうことです(reflogを有効にして、有効期限ウィンドウを拡張し、問題の原因となる可能性のある破棄されたコミットを保持するのに役立ちます)。限り問題はないはずですgit 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/config
から、git submodule update
。ハードリンクを取得するには、既存のチェックアウト済みサブモジュールを再クローンする必要があります。ミラーにダウンロードするのは1度だけで、チェックアウトしたサブモジュールにローカルからフェッチすることで、帯域幅を節約できます。ハードリンクを使用すると、ディスク領域を節約できます(ただし、フェッチは蓄積され、チェックアウトされたサブモジュールのオブジェクトストアの複数のインスタンス間で複製される傾向があります。ミラーからチェックアウトされたサブモジュールを定期的に再クローンして、ディスクスペースの節約を回復できます。ハードリンク)。
私はわずかに異なるバージョンを作成しました。それは最先端では実行されていないときのために、すべてのプロジェクトが実行するわけではありません。標準のサブモジュールの追加は機能せず、上記のスクリプトも機能しませんでした。そこで、タグ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
特定のリビジョン/チェンジセットで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の前に、それをunshallowでフェッチする必要があります)
略さずに:
#!/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
サブモジュールの浅いクローンは、特定のリビジョン/チェンジセットでスナップショットをとるため、完璧です。ウェブサイトから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
40文字のsha1と、それに対応するパスが続くを取得します.gitmodules
。私はperlを使用して、コロンで区切られたこの情報を連結してから、変数変換を使用して値をmysha
とに分離していますmysub
。
これらは重要なキーです。ダウンロードするためにsha1とurl
.gitmodules内のを関連付けるためのパスが必要だからです。
典型的なサブモジュールエントリがあるとします。
[submodule "label"]
path = localpath
url = https://github.com/repository.git
myurl
キーをオンにするとpath =
、2行後に値が取得されます。この方法は一貫して機能せず、改良が必要な場合があります。URLのgrep .git
は、最後の型/
と.
。
mydir
あるmysub
マイナス最後の/name
ディレクトリでのサブモジュール名に至るまででしょう。
次は、wget
ダウンロード可能なzipアーカイブURLの形式のです。これは将来変更される可能性があります。
mydir
サブモジュールパスで指定されたサブディレクトリになるファイルを解凍します。結果のフォルダーはurl
-の最後の要素になりsha1
ます。
サブモジュールパスで指定されたサブディレクトリが存在するかどうかを確認し、抽出されたフォルダーの名前を変更できるように削除します。
mv
sha1を含む抽出されたフォルダーの名前を正しいサブモジュールパスに変更します。
ダウンロードしたzipファイルを削除します。
サブモジュールinit
これは、ソリューションというより、WIPの概念実証です。動作すると、結果は指定されたチェンジセットでのサブモジュールの浅いクローンになります。
リポジトリがサブモジュールを別のコミットにリホームする場合は、スクリプトを再実行して更新します。
このようなスクリプトが役立つのは、ソースプロジェクトの非協力的なローカルビルドの場合のみです。
git submodule add/update
"がサブモジュールリポジトリを浅くクローンできるようになりました!以下の私の回答を