从远程 Git 存储库检索特定提交

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14872486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 15:30:52  来源:igfitidea点击:

Retrieve specific commit from a remote Git repository

gitgit-fetch

提问by Varun Chitre

Is there any way to retrieve only one specific commit from a remote Git repo without cloning it on my PC? The structure of remote repo is absolutely same as that of mine and hence there won't be any conflicts but I have no idea how to do this and I don't want to clone that huge repository.

有没有办法只从远程 Git 存储库中检索一个特定的提交,而无需将其克隆到我的 PC 上?远程仓库的结构与我的完全相同,因此不会有任何冲突,但我不知道如何做到这一点,我不想克隆那个庞大的存储库。

I am new to git, is there any way?

我是 git 新手,有什么办法吗?

采纳答案by VonC

Starting with Git version 2.5+ (Q2 2015), fetching a single commit (without cloning the full repo) is actually possible.

从 Git 版本 2.5+(2015 年第二季度)开始,获取单个提交(不克隆完整存储库)实际上是可能的。

See commit 68ee628by Fredrik Medley (moroten), 21 May 2015.
(Merged by Junio C Hamano -- gitster--in commit a9d3493, 01 Jun 2015)

提交68ee628弗雷德里克混合泳(moroten,2015年5月21日
(以合并JUNIOÇ滨野- gitster-提交a9d3493,2015年6月1日)

You now have a new config (on the server side)

您现在有一个新配置(在服务器端)

uploadpack.allowReachableSHA1InWant

Allow upload-packto accept a fetch request that asks for an object that is reachable from any ref tip. However, note that calculating object reachability is computationally expensive.
Defaults to false.

允许upload-pack接受一个 fetch 请求,该请求请求一个可以从任何 ref 提示访问的对象。但是,请注意,计算对象可达性在计算上是昂贵的。
默认为false.

If you combine that server-side configuration with a shallow clone (git fetch --depth=1), you can ask for a single commit (see t/t5516-fetch-push.sh:

如果您将该服务器端配置与浅克隆 ( git fetch --depth=1)结合起来,您可以要求进行一次提交(请参阅t/t5516-fetch-push.sh

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

You can use the git cat-filecommand to see that the commit has been fetched:

您可以使用该git cat-file命令查看提交是否已被获取:

git cat-file commit $SHA1

"git upload-pack" that serves "git fetch" can be told to serve commits that are not at the tip of any ref, as long as they are reachable from a ref, with uploadpack.allowReachableSHA1InWantconfiguration variable.

git upload-pack”,它可“ git fetch”可被告知要投放不是在任何ref的尖端,只要它们是从REF到达,与提交uploadpack.allowReachableSHA1InWant配置变量。



The full documentation is:

完整的文档是:

upload-pack: optionally allow fetching reachable sha1

With uploadpack.allowReachableSHA1InWantconfiguration option set on the server side, "git fetch" can make a request with a "want" line that names an object that has not been advertised (likely to have been obtained out of band or from a submodule pointer).
Only objects reachable from the branch tips, i.e. the union of advertised branches and branches hidden by transfer.hideRefs, will be processed.
Note that there is an associated cost of having to walk back the history to check the reachability.

This feature can be used when obtaining the content of a certain commit, for which the sha1 is known, without the need of cloning the whole repository, especially if a shallow fetch is used.

Useful cases are e.g.

  • repositories containing large files in the history,
  • fetching only the needed data for a submodule checkout,
  • when sharing a sha1 without telling which exact branch it belongs to and in Gerrit, if you think in terms of commits instead of change numbers.
    (The Gerrit case has already been solved through allowTipSHA1InWantas every Gerrit change has a ref.)

upload-pack: 可选地允许获取可达的 sha1

uploadpack.allowReachableSHA1InWant服务器端设置配置选项后,“ git fetch”可以使用“想要”行发出请求,该行命名尚未公布的对象(可能是从带外或从子模块指针获得的)。
只有从分支提示可达的对象,即广告分支和隐藏分支的联合transfer.hideRefs,将被处理。
请注意,必须返回历史记录以检查可达性会产生相关成本。

当获取某个提交的内容时可以使用此功能,其中 sha1 是已知的,而无需克隆整个存储库,尤其是在使用浅提取时

有用的情况是例如

  • 历史记录中包含大文件的存储库,
  • 仅获取子模块检出所需的数据,
  • 当共享一个 sha1 而不告诉它属于哪个确切的分支和在 Gerrit 中时,如果你考虑的是提交而不是更改数字。
    (Gerrit 案例已经解决了,allowTipSHA1InWant因为每个 Gerrit 更改都有一个参考。)


Git 2.6 (Q3 2015) will improve that model.
See commit 2bc31d1, commit cc118a6(28 Jul 2015) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster--in commit 824a0be, 19 Aug 2015)

Git 2.6(2015 年第三季度)将改进该模型。
请参阅Jeff King ( ) 的commit 2bc31d1commit cc118a6(2015 年 7 月 28 日(由Junio C Hamano合并-- --提交 824a0be 中,2015 年 8 月 19 日)peff
gitster

refs: support negativetransfer.hideRefs

If you hide a hierarchy of refs using the transfer.hideRefsconfig, there is no way to later override that config to "unhide" it.
This patch implements a "negative" hide which causes matches to immediately be marked as unhidden, even if another match would hide it.
We take care to apply the matches in reverse-order from how they are fed to us by the config machinery, as that lets our usual "last one wins" config precedence work (and entries in .git/config, for example, will override /etc/gitconfig).

So you can now do:

refs: 支持否定transfer.hideRefs

如果您使用transfer.hideRefs配置隐藏 refs 层次结构,则无法稍后覆盖该配置以“取消隐藏”它。
这个补丁实现了一个“否定”隐藏,这会导致匹配立即被标记为未隐藏,即使另一个匹配会隐藏它。
我们注意以与配置机制将它们提供给我们的方式相反的顺序应用匹配,因为这让我们通常的“最后一个获胜”配置优先工作(.git/config例如, 中的条目将覆盖/etc/gitconfig)。

所以你现在可以这样做:

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

to hide refs/secretin all repos, except for one public bit in one specific repo.

隐藏refs/secret在所有存储库中,除了一个特定存储库中的一个公共位。



Git 2.7 (Nov/Dec 2015) will improve again:

Git 2.7(2015 年 11 月/12 月)将再次改进:

See commit 948bfa2, commit 00b293e(05 Nov 2015), commit 78a766a, commit 92cab49, commit 92cab49, commit 92cab49(03 Nov 2015), commit 00b293e, commit 00b293e(05 Nov 2015), and commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49(03 Nov 2015) by Lukas Fleischer (lfos).
Helped-by: Eric Sunshine (sunshineco).
(Merged by Jeff King -- peff--in commit dbba85e, 20 Nov 2015)

提交948bfa2提交00b293e(2015年11月5日),提交78a766a提交92cab49提交92cab49提交92cab49(2015年11月3日),提交00b293e提交00b293e(2015年11月5日),并提交92cab49提交92cab49提交92cab49,由Lukas Fleischer ( )提交 92cab49(2015 年 11 月 3 日。 帮助者:Eric Sunshine ( )(由Jeff King合并-- --commit dbba85e 中,2015 年 11 月 20 日)lfos
sunshineco
peff

config.txt: document the semantics of hideRefswith namespaces

Right now, there is no clear definition of how transfer.hideRefsshould behave when a namespace is set.
Explain that hideRefsprefixes match stripped names in that case. This is how hideRefspatterns are currently handled in receive-pack.

hideRefs: add support for matching full refs

In addition to matching stripped refs, one can now add hideRefspatterns that the full (unstripped) ref is matched against.
To distinguish between stripped and full matches, those new patterns must be prefixed with a circumflex (^).

config.txt: 记录hideRefswith 命名空间的语义

目前,对于transfer.hideRefs设置命名空间时的行为方式还没有明确的定义。
解释hideRefs在这种情况下前缀匹配剥离的名称。这就是hideRefs当前在接收包中处理模式的方式。

hideRefs:添加对匹配完整引用的支持

除了匹配剥离的 refs 之外,现在还可以添加hideRefs与完整(未剥离的)ref 匹配的模式。
为了区分剥离匹配和完整匹配,这些新模式必须以抑扬符号 ( ^)为前缀。

Hence the new documentation:

因此新的文档

transfer.hideRefs:

If a namespace is in use, the namespace prefix is stripped from each reference before it is matched against transfer.hiderefspatterns.
For example, if refs/heads/masteris specified in transfer.hideRefsand the current namespace is foo, then refs/namespaces/foo/refs/heads/masteris omitted from the advertisements but refs/heads/masterand refs/namespaces/bar/refs/heads/masterare still advertised as so-called "have" lines.
In order to match refs before stripping, add a ^in front of the ref name. If you combine !and ^, !must be specified first.

如果命名空间正在使用中,命名空间前缀会在每个引用与transfer.hiderefs模式匹配之前从每个引用中剥离。
例如,如果refs/heads/master在被指定transfer.hideRefs并且目前的命名空间foo,然后refs/namespaces/foo/refs/heads/master从广告省略,但refs/heads/masterrefs/namespaces/bar/refs/heads/master仍然通告为所谓的“有”行。
为了在剥离之前匹配 refs ^,请在 ref 名称前添加一个。如果组合!and ^!必须先指定。



R..mentions in the commentsthe config uploadpack.allowAnySHA1InWant, which allows upload-packto accept a fetchrequest that asks for any object at all. (Defaults to false).

R..在评论中提到了 config uploadpack.allowAnySHA1InWant,它允许upload-pack接受fetch要求任何对象的请求。(默认为false)。

See commit f8edeaa(Nov. 2016, Git v2.11.1) by David "novalis" Turner (novalis):

请参阅David "novalis" Turner ( ) 的commit f8edeaa(2016 年 11 月,Git v2.11.1 novalis

upload-pack: optionally allow fetching any sha1

It seems a little silly to do a reachabilty check in the case where we trust the user to access absolutely everything in the repository.

Also, it's racy in a distributed system -- perhaps one server advertises a ref, but another has since had a force-push to that ref, and perhaps the two HTTP requests end up directed to these different servers.

upload-pack: 可选地允许获取任何 sha1

在我们相信用户绝对可以访问存储库中的所有内容的情况下,进行可达性检查似乎有点愚蠢。

此外,它在分布式系统中很活跃——也许一个服务器通告一个 ref,但另一个服务器已经强制推送到那个 ref,也许这两个 HTTP 请求最终被定向到这些不同的服务器。

回答by CharlesB

You only clone once, so if you already have a clone of the remote repository, pulling from it won't download everything again. Just indicate what branch you want to pull, or fetch the changes and checkout the commit you want.

您只克隆一次,因此如果您已经拥有远程存储库的克隆,则从其中提取将不会再次下载所有内容。只需指出您要拉取的分支,或者获取更改并签出您想要的提交。

Fetching from a new repository is verycheap in bandwidth, as it will only download the changes you don't have. Think in terms of Git making the right thing, with minimum load.

从新存储库获取带宽非常便宜,因为它只会下载您没有的更改。从 Git 的角度考虑,以最小的负载做出正确的事情。

Git stores everything in .gitfolder. A commit can't be fetched and stored in isolation, it needs all its ancestors. They are interrelated.

Git 将所有内容存储在.git文件夹中。提交不能单独获取和存储,它需要其所有祖先。它们是相互关联的



To reduce download size you can however ask git to fetch only objects related to a specific branch or commit:

但是,为了减少下载大小,您可以要求 git 仅获取与特定分支或提交相关的对象:

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

This will download only commits contained in remote branch branch(and only the ones that you miss), and store it in origin/branch. You can then merge or checkout.

这将仅下载包含在远程分支中的提交branch(以及您错过的提交,并将其存储在origin/branch. 然后您可以合并或结帐。

You can also specify only a SHA1 commit:

您还可以仅指定 SHA1 提交:

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

This will download only the commit of the specified SHA-1 96de5297df870 (and its ancestors that you miss), and store it as (non-existing) remote branch origin/foo-commit.

这将仅下载指定 SHA-1 96de5297df870(及其您错过的祖先)的提交,并将其存储为(不存在的)远程分支origin/foo-commit

回答by Piu Sharma

I did a pull on my git repo:

我拉了我的 git 仓库:

git pull --rebase <repo> <branch>

Allowing git to pull in all the code for the branch and then I went to do a reset over to the commit that interested me.

允许 git 提取分支的所有代码,然后我去重置我感兴趣的提交。

git reset --hard <commit-hash>

git reset --hard <commit-hash>

Hope this helps.

希望这可以帮助。

回答by Flow

You can simply fetch a single commit of a remote repo with

您可以简单地获取远程存储库的单个提交

git fetch <repo> <commit>

where,

在哪里,

  • <repo>can be a remote repo name (e.g. origin) or even a remote repo URL (e.g. https://git.foo.com/myrepo.git)
  • <commit>can be the SHA1 commit
  • <repo>可以是远程仓库名称(例如origin),甚至是远程仓库 URL(例如https://git.foo.com/myrepo.git
  • <commit>可以是 SHA1 提交

for example

例如

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

after you fetched the commit (and the missing ancestors) you can simply checkout it with

获取提交(和丢失的祖先)后,您可以简单地使用

git checkout FETCH_HEAD

Note that this will bring you in the "detached head" state.

请注意,这将使您处于“分离头”状态。

回答by Sérgio

You can simply fetch the remote repo with:

您可以简单地使用以下命令获取远程仓库:

git fetch <repo>

where,

在哪里,

  • <repo>can be a remote repo name (e.g. origin) or even a remote repo URL (e.g. https://git.foo.com/myrepo.git)
  • <repo>可以是远程仓库名称(例如origin),甚至是远程仓库 URL(例如https://git.foo.com/myrepo.git

for example:

例如:

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

after you fetched the repos you may merge the commits that you want (since the question is about retrieve one commit, instead merge you may use cherry-pick to pick just one commit):

获取存储库后,您可以合并您想要的提交(因为问题是关于检索一个提交,而不是合并,您可以使用cherry-pick 只选择一个提交):

git merge <commit>
  • <commit>can be the SHA1 commit
  • <commit>可以是 SHA1 提交

for example:

例如:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

or

或者

git merge 0a071603d87e0b89738599c160583a19a6d95545

if is the latest commit that you want to merge, you also may use FETCH_HEAD variable :

如果是您要合并的最新提交,您也可以使用 FETCH_HEAD 变量:

git cherry-pick (or merge) FETCH_HEAD

回答by Alexander Mills

This works best:

这效果最好:

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD

name "temp" whatever you want...this branch might be orphaned though

随意命名“temp”......不过这个分支可能是孤立的

回答by surya deepak

Finally i found a way to clone specific commit using git cherry-pick. Assuming you don't have any repository in local and you are pulling specific commit from remote,

最后,我找到了一种使用git cherry-pick克隆特定提交的方法。假设您在本地没有任何存储库并且您正在从远程拉取特定提交,

1) create empty repository in local and git init

1)在本地和git init中创建空存储库

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

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

3) git fetch origin[this will not move your files to your local workspace unless you merge]

3) git fetch origin[除非您合并,否则这不会将您的文件移动到您的本地工作区]

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

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

Done.This way, you will only have the files from that specific commit in your local.

完成。这样,您将只在本地拥有来自该特定提交的文件。

Enter-long-commit-hash:

输入长提交哈希:

You can get this using -> git log --pretty=oneline

您可以使用 -> git log --pretty=oneline获取此信息

回答by Noam Manos

If the requested commit is in the pull requests of the remote repo, you can get it by its ID:

如果请求的提交在远程仓库的拉取请求中,您可以通过其 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

回答by Hubbitus

I think 'git ls-remote' ( http://git-scm.com/docs/git-ls-remote) should do what you want. Without force fetch or pull.

我认为 'git ls-remote' ( http://git-scm.com/docs/git-ls-remote) 应该做你想做的。没有强制获取或拉动。