リモートGitリポジトリから特定のコミットを取得する


189

PCに複製せずに、リモートGitリポジトリから特定のコミットを1つだけ取得する方法はありますか?リモートリポジトリの構造は私のリポジトリとまったく同じなので、競合は発生しませんが、これを行う方法がわからず、巨大なリポジトリのクローンを作成したくありません。

gitは初めてですが、方法はありますか?


1
あなたの既存のリポジトリはすでにリモートのリポジトリのクローンですか、それとも完全に異なりますか?
CharlesB 2013

さて、リポジトリはLinuxカーネルソースで、ほとんど同じです
Varun Chitre 2013

それはクローンですか、それともノーですか?
CharlesB 2013

1
ではない正確に。これを検討してください。リモートリポジトリが先頭Dにあり、自分が先頭Aにあり、B、C、Dのコミットが遅れているとします。これらのリポジトリのB、C、Dコミットはそれぞれの専門分野によって異なるため、あるリポジトリからのコミットBと別のリポジトリからのC、および別のリポジトリからのDをマージしたいと思います
Varun Chitre

1
@ VarunChitre、VonCからの他の回答を受け入れることができますか?
CharlesB 16

回答:


108

Gitバージョン2.5以降(2015年第2四半期)以降、実際には(完全なリポジトリを複製せずに)単一のコミットをフェッチすることが可能です。

参照してください68ee628をコミットすることにより、フレドリックメドレー(moroten、5月21日2015年
(で合併Junio C浜野- gitster-a9d3493コミット、2015年6月1日)

これで新しい設定ができました(サーバー側)

uploadpack.allowReachableSHA1InWant

upload-pack参照チップから到達可能なオブジェクトを要求するフェッチ要求を受け入れることを許可します。ただし、オブジェクトの到達可能性の計算には計算コストがかかることに注意してください。
デフォルトはfalseです。

そのサーバー側の構成をシャロークローン(git fetch --depth=1)と組み合わせると、単一のコミットを要求できます(t/t5516-fetch-push.sh

git fetch --depth=1 ../testrepo/.git $SHA1

git cat-file次のコマンドを使用して、コミットがフェッチされたことを確認できます。

git cat-file commit $SHA1

git upload-pack」それはあります「git fetch」と、限り、彼らはREFから到達可能なように、任意のREFの先端ではないコミットを果たすのかを知らせることができますuploadpack.allowReachableSHA1InWant 設定変数。


完全なドキュメントは次のとおりです。

upload-pack:必要に応じて、到達可能なsha1のフェッチを許可します

ではuploadpack.allowReachableSHA1InWant、サーバー側の設定オプションのセット、「git fetch欲しい」行その名前宣伝されていないオブジェクト(おそらくバンドのか、サブモジュールのポインタから得られているために)「との要求を行うことができます」。
ブランチの先端から到達可能なオブジェクト、つまり、アドバタイズされたブランチとによって非表示にされたブランチの結合のみtransfer.hideRefsが処理されます。
到達可能性を確認するために履歴をさかのぼることには関連するコストがかかることに注意してください。

この機能は、特に浅いフェッチを使用する場合、リポジトリ全体を複製する必要なしに、sha1が既知である特定のコミットのコンテンツを取得するときに使用できます。

有用なケースは例えば

  • 履歴に大きなファイルを含むリポジトリ、
  • サブモジュールのチェックアウトに必要なデータのみをフェッチし、
  • 変更番号の代わりにコミットの観点から考えると、それが属している正確なブランチを知らずにsha1を共有する場合、およびGerrit内で。
    allowTipSHA1InWantすべてのGerritの変更には参照があるため、Gerritのケースはすでに解決されています。)

Git 2.6(2015年第3四半期)では、このモデルが改善されます。Jeff King()によるcommit 2bc31d1commit cc118a6(2015年7月28日)を
参照してください。(による合併Junio C浜野- -824a0beコミット、2015年8月19日)をpeff
gitster

refsネガティブをサポート transfer.hideRefs

構成を使用して参照の階層を非表示にする場合transfer.hideRefs、後でその構成をオーバーライドして「再表示」する方法はありません。
このパッチは、「負の」非表示を実装します。これにより、別の一致によって非表示にされたとしても、一致はすぐに非表示としてマークされます。
通常の「最後の1つが勝つ」設定の優先順位が機能するように、設定機械からのフィードとは逆の順序で一致を適用するよう注意します(.git/configたとえば、のエントリはオーバーライドされます)/etc/gitconfig)。

だからあなたは今やることができます:

git config --system transfer.hideRefs refs/secret
git config transfer.hideRefs '!refs/secret/not-so-secret'

refs/secret特定の1つのリポジトリの1つの公開ビットを除いて、すべてのリポジトリに非表示にします。


Git 2.7(2015年11月/ 12月)が再び改善されます。

コミット948bfa2を参照00b293eコミット、(2015年11月5日)を78a766aコミット92cab49をコミットし92cab49コミット92cab49コミット(2015年11月3日)、00b293eをコミットし00b293eコミット(2015年11月5日)を、そして92cab49をコミットし92cab49コミット92cab49をコミットしコミット92cab49(03 Nov 2015)by Lukas Fleischer(lfos
協力者:エリックサンシャイン(sunshineco
(による合併ジェフ・キング- peff-dbba85eをコミットし、2015年11月20日)

config.txt:のセマンティクスを文書化する hideRefs名前空間し

現在のところ、transfer.hideRefs名前空間が設定された場合の動作の明確な定義はありません。その場合
hideRefs接頭辞は省略された名前と一致することを説明します。これが、hideRefsパターンが現在receive-packで処理される方法です。

hideRefs:完全参照のマッチングのサポートを追加

ストリップされた参照の照合に加えhideRefsて、完全な(ストリップされていない)参照が照合されるパターンを追加できるようになりました。
完全一致と完全一致を区別するには、これらの新しいパターンの先頭にサーカムフレックス(^)を付ける必要があります。

したがって、新しいドキュメント

transfer.hideRefs:

名前空間が使用されている場合、名前空間プレフィックスは、transfer.hiderefsパターンと照合される前に各参照から削除されます。
例えば、場合がrefs/heads/masterで指定されtransfer.hideRefs、現在の名前空間がされfoo、その後、refs/namespaces/foo/refs/heads/master 広告から省略されているが、refs/heads/masterrefs/namespaces/bar/refs/heads/masterはまだ、いわゆる「持っている」ラインとして宣伝されています。
ストリッピングの前に参照を照合するに^は、参照名の前にa を追加します。あなたが結合した場合!^!最初に指定する必要があります。


R ..コメントでconfig について言及しています。uploadpack.allowAnySHA1InWantこれにより、オブジェクトを要求upload-packするfetchリクエストを受け入れることができます。(デフォルトはfalse)。

David "novalis" Turner()によるcommit f8edeaa(2016年11月、Git v2.11.1)を参照してください。novalis

upload-pack:オプションで、sha1のフェッチを許可する

ユーザーがリポジトリ内のすべてに絶対にアクセスすることを信頼している場合、到達可能性チェックを行うのは少しばかげているようです。

また、分散システムでは際どい-1つのサーバーがrefをアドバタイズするが、別のサーバーがそのrefに強制的にプッシュし、2つのHTTPリクエストがこれらの異なるサーバーに向けられる可能性がある。


4
この単一のコミットだけでリポジトリクローンを作成する方法について、より完全な例を挙げられますか?試しましたが失敗しました。ありがとうございます。
Lars Bilke、2015

1
GitHubにプッシュしたい。多分彼らはこれを許可しません。
Lars Bilke、2015

2
@LarsBilkeは、クローンではなく、プルではなくプルについて話しています。そして、GitHubにはまだサーバー側にGit 2.5がありません。
VonC、2015

2
さらに良いuploadpack.allowAnySHA1InWantことに、到達可能性の計算ペナルティ(およびDoSベクトル)がありません。
R .. GitHub ICEのヘルプを停止する

1
ありがとう!彼らがそれを「ユーザーがアクセスすることを信頼する」と表現するのは面白いことだと思う。
R .. GitHub ICE HELPING ICEを停止する

97

複製は1回だけなので、リモートリポジトリの複製がすでにある場合、そこからプルしてもすべてが再度ダウンロードされるわけではありません。プルするブランチを指定するか、変更をフェッチして、必要なコミットをチェックアウトします。

新しいリポジトリからのフェッチは非常には帯域幅安価です。これは、必要のない変更のみをダウンロードするためです。最小の負荷で、Gitが正しいことを行うという観点から考えてください。

Gitはすべてを.gitフォルダーに格納します。コミットをフェッチして分離して保存することはできません。すべての祖先が必要です。それらは相互に関連しています。


ただし、ダウンロードサイズを小さくするには、特定のブランチまたはコミットに関連するオブジェクトのみをフェッチするようにgitに要求できます。

git fetch origin refs/heads/branch:refs/remotes/origin/branch

これにより、リモートブランチに含まれるコミットのみbranch (および見逃したコミットのみ)がダウンロードされ、次の場所に格納されます。origin/branchます。その後、マージまたはチェックアウトできます。

SHA1コミットのみを指定することもできます。

git fetch origin 96de5297df870:refs/remotes/origin/foo-commit

これにより、指定されたSHA-1 96de5297df870(およびその祖先)のコミットのみがダウンロードされ、(存在しない)リモートブランチとして保存されorigin/foo-commitます。


3
クローンの意味について混乱しているようです。リモートリポジトリから変更をフェッチする場合は、それを複製せず、履歴にコミットを取得します。次に、チェックアウトするコミットを選択するか、履歴にマージします
CharlesB

1
それでもgit fetchで大量のデータ(430mb)をダウンロードします。必要なコミットはほんの数キロバイトです。これを実際に行うための特別なコマンドはありませんか?「git fetched」リポジトリを削除したい場合はどうすればよいですか?どこに保管されていますか?
Varun Chitre 2013

9
これは現在かなり古くなっています。シャロークローンを実行する機能と、単一のコミットフェッチする機能の両方があります。浅いクローンは、プロジェクトの完全な履歴を知る必要なく、通常のプッシュとフェッチが許可されるようになりました。そのため、祖先がなければ単独でコミットは存在できないと言うのはもはや正しくありません。最初のクローンの後のフェッチについてあなたが言うことは非常に本当ですが、私たちにはさらに安価なオプションもあります。
セオドアマードック

6
最後のコマンド(SHA1コミットを使用)は機能しません。コマンドはしばらくの間「何か」を黙って実行し、その後メッセージや明らかな副作用なしで終了します。
HRJ 2016

1
@HRJはい、私もこれに遭遇しました。Gitを使用するUbuntu 16.04で2.7.4-0ubuntu1.3。ただし、2.16.2-0ppa1~ubuntu16.04.1git-core PPAから使用する場合、これは正常に機能します。修正されたバグのように聞こえます。クイック検索でそれへの参照を見つけることができませんでした。誰かが私にそれについてのポインタを得ることができるなら、私はこの修正をバックポートしてもらいたいです。
gertvdijk

62

私は私のgitリポジトリをプルしました:

git pull --rebase <repo> <branch>

gitがブランチのすべてのコードを取得できるようにしてから、興味のあるコミットにリセットしました。

git reset --hard <commit-hash>

お役に立てれば。


1
答えはどれもうまくいきませんでしたが、これは私の命を救いました!本当にありがとう!
michaeltintiuc 14

リセット後-クローン後にハードに働きました!ありがとう。
Nick-ACNB 2015年

3
-1:のような「破壊的な」コマンドはgit reset --hard、一般化されたソリューションで共有されると、データを失う(または、この場合、データを取り戻すことが重要な状態にある)トラップに人々を導く可能性があります。
yaauie

54

あなたは単純にリモートリポジトリの単一のコミットをフェッチすることができます

git fetch <repo> <commit>

どこ、

  • <repo>リモートリポジトリ名(例:)originまたはリモートリポジトリURL(例:https://git.foo.com/myrepo.git
  • <commit> SHA1コミットにすることができます

例えば

git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545

コミット(および欠落している祖先)をフェッチした後は、次のコマンドで単純にチェックアウトできます。

git checkout FETCH_HEAD

これにより、「ヘッドが取り外された」状態になります。


10
fetchあなたがそうしているように私が特定のリビジョンにしようとすると、gitはエラーコード1で失敗し、出力はありません。これは以前のバージョンで機能していたものですか?(私はv2.0.2です。)
Jack O'Connor、

2
編集:それが私がすでにローカルでそのコミットを持っている場合、私がすでにフルを実行した場合のように機能しますfetchが、その場合、私は用途が何であるかわかりません。
ジャックオコナー

2
確かに、これはgit 2.0.2ではもう機能しないようです。:(
フロー

2
git checkout FETCH_HEAD助けます。
lzl124631x

1
このメソッドは、浅いフェッチ(たとえば--depth=1)では機能しません。
kingmakerking

16

次のようにして、単純にリモートリポジトリをフェッチできます。

git fetch <repo>

どこ、

  • <repo>リモートリポジトリ名(などorigin)またはリモートリポジトリURL(例https://git.foo.com/myrepo.git)でもかまいません

例えば:

git fetch https://git.foo.com/myrepo.git 

レポジトリを取得した後、必要なコミットをマージできます(質問は1つのコミットの取得に関するものなので、マージではなく、cherry-pickを使用して1つのコミットのみを選択できます)。

git merge <commit>
  • <commit> SHA1コミットにすることができます

例えば:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

または

git merge 0a071603d87e0b89738599c160583a19a6d95545

マージしたい最新のコミットである場合は、FETCH_HEAD変数も使用できます。

git cherry-pick (or merge) FETCH_HEAD

これには、マシンでGitアカウントをセットアップする必要があります。テストアカウントでは機能しません。テストアカウントで機能するものはありますか?
jww

どういう意味ですか ?あなたはgit fetchを行うことができませんか?
セルジオ

ええと、コマンドは git config set uploadpack.allowReachableSHA1InWant
Alexander Mills

2

これは最もよく機能します:

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD

「temp」という名前を付けます。ただし、このブランチは孤立している可能性があります


はっきりしない古いgitのバージョンは1.8.xなどで
ソリン

1

最後に、git cherry-pickを使用して特定のコミットを複製する方法を見つけました。ローカルにリポジトリがなく、リモートから特定のコミットをプルしていると仮定すると、

1)ローカルに空のリポジトリを作成し、git init

2)git remote add origin " url-of-repository "

3)git fetch origin [マージしない限り、ファイルはローカルワークスペースに移動されません]

4)git cherry-pick " Enter-long-commit-hash-that-need-need "

完了。このようにすると、特定のコミットのファイルのみがローカルにあります。

Enter-long-commit-hash:

-> git log --pretty = onelineを使用してこれを取得できます



0

リクエストされたコミットがリモートリポジトリのプルリクエストに含まれている場合、そのIDで取得できます。

# Add the remote repo path, let's call it 'upstream':
git remote add upstream https://github.com/repo/project.git

# checkout the pull ID, for example ID '60':
git fetch upstream pull/60/head && git checkout FETCH_HEAD
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.