web-dev-qa-db-ja.com

浅いクローンからプッシュできないのはなぜですか?

git clone --depthコマンドオプションには

--depth <depth> 
Create a shallow clone with a history truncated to the specified number of revisions. 
A shallow repository has a number of limitations 
(you cannot clone or fetch from it, nor Push from nor into it),
 but is adequate if you are only interested in the recent history of a large project with a long history,
 and would want to send in fixes as patches. 

浅いクローンにこの制限があるのはなぜですか?なぜパッチのみのワークフローですか?

一部のプロジェクトワークフローでは、1つのブランチからコーダーに最新のコミットを渡すだけで、メインサーバーにPush(早送り)開発を行えるようにする必要があります。これは、一部はセキュリティ、IP保護、およびレポサイズのためであり、一部は大きなレポが素朴なコーダーにもたらす混乱を軽減するためです。これを可能にするgitワークフローはありますか?


更新:Karl Bielefeldtの回答に基づいて、git checkout --Orphanが正しい答えになるはずです。しかし、そのブランチだけを新しいユーザーに「クローン」し、効果的にプッシュできるようにする必要があります。

マニュアルページの状態:

git checkout [-q] [-f] [-m] [[-b|-B|--Orphan] <new_branch>] [<start_point>] --Orphan

<new_branch>から始まる<start_point>という名前の新しい孤立ブランチを作成し、それに切り替えます。この新しいブランチで行われた最初のコミットには親がなく、他のすべてのブランチとコミットから完全に切り離された新しい履歴のルートになります。

インデックスと作業ツリーは、以前にgit checkout <start_point>を実行したかのように調整されます。これにより、<start_point>を簡単に実行してルートをコミットすることで、git commit -aに類似した一連のパスを記録する新しい履歴を開始できます。

これは、完全な履歴を公開せずにコミットからツリーを公開する場合に役立ちます。これを行うと、現在のツリーが「クリーン」であるプロジェクトのオープンソースブランチを公開できますが、完全な履歴には独自のコードまたは邪魔なコードが含まれます。

<start_point>のパスとはまったく異なるパスのセットを記録する切断された履歴を開始する場合は、作業の最上位からgit rm -rf .を実行して、Orphanブランチを作成した直後にインデックスと作業ツリーをクリアする必要があります木。その後、他の場所からファイルをコピーしたり、tarballを抽出したりすることで、作業ファイルを再作成して新しいファイルを準備する準備が整います。

VonCのJunioのコメントへのリンクは興味深い。この場合、マニュアルはガイダンスを提供し、正しいコマンドを許可する必要があると思います(例: clone <branch> --options]リポジトリの関連部分のみを抽出します。 Pushが成功する確率は、履歴の下部にいくつかのリンクされたコミットとSHA1があり、レポマッチングをロックダウンすることで明らかに増加します。


Git 1.9.0の更新:リリースノート14年2月14日。

「主に関連するコードパスが慎重に吟味されておらず、そのような使用法をサポートしなかったため、浅くクローンされたリポジトリからのフェッチは禁止されていました。 (つまり、受信者は切り捨てられた履歴を持つ浅いリポジトリになります。)

これは、浅いクローン作成者にとって朗報です。次-おそらく狭いクローン。

42
Philip Oakley

Junio C. Hamano(メインGitメンテナー) put it

ルールは多かれ少なかれそうではありません:

浅いリポジトリの履歴が十分に長く伸びず、他のリポジトリが切り捨てられた履歴の前に分岐した場合、共通の祖先を計算できず、プッシュできません。

2014年更新:「 git clone --depth 1(shallow clone)は、それよりも有用ですか? 」:Git 1.9でその制限が解除されます!

更新2015:Git 2.5+では、1つのコミットをフェッチすることさえできます。 「 リモートgitリポジトリから特定のコミットをプル 」を参照してください


元の回答(2011年8月):

実際に考えてみると、「共通を計算できない」よりもはるかに強力です。

履歴は次のようになります。

          R---R---R
         /
  --R---R---X---X---S---S---S

ここで、Sは浅いリポジトリにあるコミットで、Rはプッシュを受信するリポジトリに存在するコミットです。
履歴が浅いため、どちらのリポジトリにも 'X'がありません。これは、受信者リポジトリの履歴を完全に保つために存在する必要があるコミットです。受信者は最初は浅くなく、浅くしたくありません。

少し前に浅くクローンを作成し、反対側が進行中に反対側と通信せずに作業した場合、[〜#〜] and [〜#〜]反対側の進捗状況に履歴の巻き戻しと再構築が含まれる場合、同様のトポロジが表示されます。
上の図の左端の 'S'は、深さ1で浅くクローンを作成したときのブランチの先端である可能性があり、それ以降、リモートエンドは最上位の3つのコミットを破棄して再構築した可能性があります右端の「R」につながるその履歴。
このような場合、リモートのHEADへのプッシュは失敗します。


したがって、couldは動作する場合がありますが、サポートされていません:

これについて何か言わなければならないなら...

  • 「サポートされていません」は十分な情報を提供するための簡潔な方法だと思いますが、それは知的な人々にのみ有効です。

  • 誰もが賢いわけではありません。自分で試してみて、操作が限られた回数の試行で動作するように見えることを確認し、ほとんどの場合動作すると結論付けます。
    そして、彼らは「常に」ではなく、「ほとんどの時間」と言った自身の知性を祝福します。
    そして、彼らは、警告されたにもかかわらず、それが機能しないのを見ると動揺します。


浅いクローンの更新プロセスの詳細については、「 gitの浅いクローンを更新する方法? 」を参照してください。

22
VonC

これを可能にするgitワークフローはありますか?

はい、修正をパッチとして送信することです。 git format-patchは、これを可能にするために特別に設計されています。詳細をグーグルで検索する場合は、「ゲートキーパー」ワークフローと呼ばれます。組織が「セキュリティとIP保護」に関心を持っていると信じるのは、あなたの組織が既に似たようなものを使用していないためです。1人または小さなグループが「信頼できない」変更を実際のビルドに組み込む前に調査する責任があります。


あなたのコメントに基づいて、私はあなたの要件のより良いアイデアを持っています。私がお勧めするのは、Orphanブランチ( git checkout --Orphan を参照)を作成することです。始めること。それらの開発者がアクセスできる別のリポジトリにそのブランチのみをクローンし、そのリポジトリから通常どおりクローン、プッシュ、プルを実行します。

次に、公式の保護されたリポジトリに変更を再統合する必要がある場合、ブランチをプルし、git branchでコピーを作成して、元の孤児を上書きしないようにします(後でプロセスを繰り返したい場合) 、コピーを元の分岐点にリベースし、通常どおりにマージします。履歴は、保護されたリポジトリから直接機能したように見えます。

それは通常よりも少し複雑ですが、それは余分な隔離のために支払われる代償です。

9
Karl Bielefeldt