215

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

私はgitを初めて使用しますが、方法はありますか?

4

10 に答える 10

120

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

2015年521日、FredrikMedleyよるcommit68ee628参照してくださいmoroten
gitster

これで、(サーバー側に)新しい構成ができました。

uploadpack.allowReachableSHA1InWant

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

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

git fetch --depth=1 ../testrepo/.git <full-length SHA1>

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

git cat-file commit <full-length SHA1>

git upload-pack」は、 構成変数を使用git fetchして、参照から到達可能である限り、参照の先端にないコミットを処理するように指示できます。uploadpack.allowReachableSHA1InWant

コメントでマットが指摘したように:

SHAは完全に省略されていないSHAである必要があることに注意してください。そうでない場合、Gitはコミットを見つけることができなかったと主張します


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

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

uploadpack.allowReachableSHA1InWantサーバー側で構成オプションを設定すると、「」git fetchは、アドバタイズされていないオブジェクト(帯域外またはサブモジュールポインターから取得された可能性が高い)を指定する「want」行を使用して要求を行うことができます。
ブランチチップから到達可能なオブジェクト、つまりアドバタイズされたブランチとによって隠されたブランチの結合のみtransfer.hideRefsが処理されます。
到達可能性を確認するために履歴をさかのぼる必要があることに関連するコストがあることに注意してください。

この機能は、sha1がわかっている特定のコミットのコンテンツを取得するときに使用できます。特に、浅いフェッチが使用されている場合は、リポジトリ全体のクローンを作成する必要はありません

便利なケースは、例えば

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

Git 2.6(2015年第3四半期)はそのモデルを改善します。ジェフキング()によるコミット2bc31d1コミットcc118a6(2015年7月28日)を
参照してください。( Junio C Hamanoによってマージされました---コミット824a0be 、20158月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/secret1つの特定のリポジトリの1つのパブリックビットを除いて、すべてのリポジトリに非表示にします。


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

commit 948bfa2、commit 00b293e(2015年11月5日)、commit 78a766acommit 92cab49commit 92cab49commit 92cab49(2015年11月3日)、commit 00b293ecommit 00b293e(2015年11月5日)、およびcommit 92cab49commit 92cab49commit 92cab49Lukas Fleischer()による92cab49(2015年11月3日)をコミットします。 支援者:Eric Sunshine(( Jeff Kingによってマージされました---コミットdbba85e、2015年11月20日lfos
sunshineco
peff

config.txthideRefs:名前空間を使用してのセマンティクスを文書化する

現在、transfer.hideRefs名前空間が設定されたときにどのように動作するかについての明確な定義はありません。その場合、プレフィックスは削除された名前と一致
することを説明します。hideRefsこれはhideRefs、現在、receive-packでパターンが処理される方法です。

hiddenRefs:完全な参照を照合するためのサポートを追加します

hideRefsストリップされた参照の一致に加えて、完全な(ストリップされていない)参照が一致するパターンを追加できるようになりました。
削除された一致と完全な一致を区別するには、これらの新しいパターンの前に曲折アクセント記号(^)を付ける必要があります。

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

transfer.hideRefs:

transfer.hiderefs名前空間が使用されている場合、名前空間プレフィックスは、パターンと照合される前に各参照から削除されます。
たとえば、refs/heads/masterがで指定されtransfer.hideRefs、現在の名前空間がで あるfoo場合、thenrefs/namespaces/foo/refs/heads/master はアドバタイズメントから省略されますが、いわゆる「have」行としてアドバタイズされます。 ストリッピングする前に参照を一致させるには、参照名の前にを追加します。とを組み合わせる場合は、最初に指定する必要があります。refs/heads/masterrefs/namespaces/bar/refs/heads/master
^!^!


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

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

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

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

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


Git 2.34(Q4 2021)では、(man)の反対側で実行される " " man)は、git upload-packwant - ref要求を処理するときにref名前空間を考慮するのを忘れていました。git fetch

Kim Altintop()によるcommit 53a66eccommit 3955140commit bac01c6(2021年8月13日)を参照してください。( Junio C Hamanoによってマージされました---コミット1ab13eb、2021年9月10日kim
gitster

docs:transfer.hideRefsと名前空間の相互作用を明確にする

サインオフ-作成者:Kim Altintop
レビュー者:Jonathan Tan

のドキュメントの名前空間に関するセクションを展開して、との微妙な違いをtransfer.hideRefs指摘します。upload-packreceive-pack

3955140( " upload-pack.c:名前空間に関連するwant-refを処理する"、2021-07-30、Git v2.34.0-バッチ#5にリストされているマージ)は、非表示の参照のsを拒否するように教えられました。 非表示のrefの名前が明らかになることはありませんが、それが指すオブジェクトIDは明らかになる可能性があります。upload-packwant-ref

git config現在、そのマニュアルページに含まれています:

transfer.hiderefsパターンと照合される前の参照。ストリッピングする前に参照を一致させるに^は、参照名の前にを追加します。!とを組み合わせる場合は^!最初に指定する必要があります。

git config現在、そのマニュアルページに含まれています:

広告から省略されています。uploadpack.allowRefInWantが設定さ れている場合、protocolv2 コマンドで存在しないかのようupload-packに扱います。 一方、refが指しているオブジェクトIDは、その名前(いわゆる「e」行)を指定せずにアドバタイズします。want-ref refs/heads/masterfetchrefs/namespaces/foo/refs/heads/masterreceive-pack.hav

于 2015-06-08T05:22:17.167 に答える
104

クローンを作成するのは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ます。

于 2013-02-14T10:23:16.903 に答える
64

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

git pull --rebase <repo> <branch>

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

git reset --hard <commit-hash>

お役に立てれば。

于 2013-12-03T12:43:17.463 に答える
64

リモートリポジトリの単一のコミットを簡単にフェッチできます

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

これにより、「ヘッドが外れた」状態になることに注意してください。

于 2014-06-06T14:50:35.090 に答える
21

次の方法でリモートリポジトリを取得できます。

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
于 2015-07-16T17:32:16.637 に答える
6

これが最適です。

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD

好きな名前「temp」...このブランチは孤立している可能性があります

于 2019-05-16T23:15:14.440 に答える
1

'git ls-remote'(http://git-scm.com/docs/git-ls-remote)はあなたが望むことをするべきだと思います。強制的にフェッチまたはプルする必要はありません。

于 2015-01-28T15:42:04.597 に答える
1

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

1)ローカルおよびgitinitに空のリポジトリを作成します

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

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

4)gitcherry-pickEnter-long-commit-hash-that-you-need

これで、ローカルにその特定のコミットからのファイルのみが保存されます。

Enter-long-commit-hash:

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

于 2017-01-03T04:19:49.577 に答える
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
于 2019-06-16T14:56:11.073 に答える
0

プロジェクトで問題が発生したため、特定のコミットに戻らなければなりませんでした。次のコマンドで正常に完了しました。

git reset --hard <commitID>
于 2020-11-12T08:20:43.207 に答える