473

如何克隆具有特定修订版的 git 存储库,就像我通常在 Mercurial 中所做的那样:

hg clone -r 3 /path/to/repository
4

17 回答 17

926
$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1

再次回到最近的提交

$ git pull

要在线(远程)保存恢复的提交,您必须推送执行源:

git push origin -f
于 2012-12-30T13:41:51.110 回答
269

更新 2由于Git 2.5.0可以在服务器端使用配置变量启用下面描述的功能uploadpack.allowReachableSHA1InWant,这里是GitHub 功能请求启用此功能的 GitHub 提交。请注意,一些 Git 服务器默认激活此选项,例如 Bitbucket 服务器从5.5+ 版本开始启用它。有关如何激活配置选项的示例,请参阅 Stackexchange 上的此答案。

更新 1对于 Git 版本,请1.7 < v < 2.5使用 git clone 和 git reset,如Vaibhav Bajpai 的回答中所述

如果您不想获取完整的存储库,那么您可能不应该使用clone. 您始终可以使用 fetch 来选择要获取的分支。我不是汞专家,所以我不知道细节,-r但在 git 中你可以做这样的事情。

# make a new blank repository in the current directory
git init

# add a remote
git remote add origin url://to/source/repository

# fetch a commit (or branch or tag) of interest
# Note: the full history up to this commit will be retrieved unless 
#       you limit it with '--depth=...' or '--shallow-since=...'
git fetch origin <sha1-of-commit-of-interest>

# reset this repository's master branch to the commit of interest
git reset --hard FETCH_HEAD
于 2010-08-15T22:40:47.353 回答
84

要在特定分支或标签上仅克隆一个特定提交,请使用:

git clone --depth=1 --branch NAME https://github.com/your/repo.git

不幸的是,NAME只能是分支名称或标签名称(不能提交 SHA)。

省略--depth标志以下载整个历史记录,然后签出该分支或标签:

git clone --branch NAME https://github.com/your/repo.git

这适用于最新版本的 git(我用 version 做到了2.18.0)。

于 2018-08-09T16:16:35.230 回答
59

克隆一个 git 存储库,恰如其分地克隆了整个存储库:没有办法只选择一个修订版进行克隆。但是,一旦您执行git clone,您可以通过执行来签出特定的修订checkout <rev>

于 2010-08-15T20:49:43.230 回答
31

如果您的意思是要获取从开始到特定点的所有内容,Charles Bailey 的答案是完美的。如果您想反向操作并检索从当前日期返回的历史子集,您可以使用git clone --depth [N] 其中 N 是您想要的历史转数。然而:

- 深度

创建一个浅克隆,其历史被截断为指定的修订数。浅层存储库有许多限制(您不能克隆或从中获取,也不能从中推送或进入),但如果您只对历史悠久的大型项目的近期历史感兴趣,并且想要作为补丁发送修复。

于 2010-08-15T22:45:42.630 回答
30

你可以简单地使用git checkout <commit hash>

在这个序列中

bash git clone [URLTORepository] git checkout [commithash]

提交哈希看起来像这样“45ef55ac20ce2389c9180658fdba35f4a663d204”

于 2013-08-03T21:35:51.970 回答
27

总结一下(git v. 1.7.2.1):

  1. 在你想要回购的地方定期做git clone(得到最新的一切——我知道,不是想要的,我们到了那里)
  2. git checkout <sha1 rev>你想要的转速
  3. git reset --hard
  4. git checkout -b master
于 2012-03-04T20:07:46.467 回答
18

TL;DR - 只需在源存储库中针对要克隆的提交创建一个标签,然后在 fetch 命令中使用该标签。您可以稍后从原始存储库中删除标签以进行清理。

好吧,它是 2014 年,看起来查尔斯·贝利(Charles Bailey)从 2010 年开始接受的答案现在已经过时了,而且大多数(全部?)其他答案都涉及克隆,许多人希望避免这种情况。

以下解决方案实现了 OP 和许多其他人正在寻找的东西,这是一种创建存储库副本的方法,包括历史记录,但仅限于某个提交。

以下是我在 git 版本 2.1.2 中使用的命令,用于克隆本地存储库(即另一个目录中的存储库)直到某个点:

# in the source repository, create a tag against the commit you want to check out
git tag -m "Temporary tag" tmptag <sha1>

# create a new directory and change into that directory
cd somewhere_else;mkdir newdir;cd newdir

# ...and create a new repository
git init

# add the source repository as a remote (this can be a URL or a directory)
git remote add origin /path/to/original/repo

# fetch the tag, which will include the entire repo and history up to that point
git fetch origin refs/tags/tmptag

# reset the head of the repository
git reset --hard FETCH_HEAD

# you can now change back to the original repository and remove the temporary tag
cd original_repo
git tag -d tmptag

希望这个解决方案能继续工作几年!:-)

于 2014-11-18T23:56:21.387 回答
1

Using 2 of the above answers (How to clone git repository with specific revision/changeset? and How to clone git repository with specific revision/changeset?) Helped me to come up with a definative. If you want to clone up to a point, then that point has to be a tag/branch not simply an SHA or the FETCH_HEAD gets confused. Following the git fetch set, if you use a branch or tag name, you get a response, if you simply use an SHA-1 you get not response.
Here's what I did:- create a full working clone of the full repo, from the actual origin

cd <path to create repo>
git clone git@<our gitlab server>:ui-developers/ui.git 

Then create a local branch, at the point that's interesting

git checkout 2050c8829c67f04b0db81e6247bb589c950afb14
git checkout -b origin_point

Then create my new blank repo, with my local copy as its origin

cd <path to create repo>
mkdir reduced-repo
cd reduced-repo
git init
git remote add local_copy <path to create repo>/ui
git fetch local_copy origin_point

At that point I got this response. I note it because if you use a SHA-1 in place of the branch above, nothing happens, so the response, means it worked

/var/www/html/ui-hacking$ git fetch local_copy origin_point
remote: Counting objects: 45493, done.
remote: Compressing objects: 100% (15928/15928), done.
remote: Total 45493 (delta 27508), reused 45387 (delta 27463)
Receiving objects: 100% (45493/45493), 53.64 MiB | 50.59 MiB/s, done.
Resolving deltas: 100% (27508/27508), done.
From /var/www/html/ui
 * branch            origin_point -> FETCH_HEAD
 * [new branch]      origin_point -> origin/origin_point

Now in my case, I then needed to put that back onto gitlab, as a fresh repo so I did

git remote add origin git@<our gitlab server>:ui-developers/new-ui.git

Which meant I could rebuild my repo from the origin_point by using git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -k to cherry pick remotely then use git push origin to upload the whole lot back to its new home.

Hope that helps someone

于 2016-01-07T10:47:47.830 回答
1
# clone special tag/branch without history
git clone  --branch=<tag/branch> --depth=1 <repository>


# clone special revision with minimal histories
git clone --branch <branch> <repository> --shallow-since=yyyy-MM-ddTHH:mm:ss  # get the commit time
cd <dir>
git reset --hard <revision> 

如果未在服务器端设置,则无法获得没有历史记录的修订uploadpack.allowReachableSHA1InWant=true,而您可以为其创建标签并克隆特殊标签。

于 2020-04-14T09:42:14.840 回答
1

我的版本是接受和最受好评的答案的组合。但这有点不同,因为每个人都使用 SHA1 但没有人告诉你如何获取它

$ git init
$ git remote add <remote_url>
$ git fetch --all

现在你可以看到所有的分支和提交

$ git branch -a
$ git log remotes/origin/master <-- or any other branch

最后你知道了所需提交的 SHA1

git reset --hard <sha1>
于 2016-10-28T10:27:36.007 回答
0

就我个人而言,我最喜欢克隆单个提交的方式。

mkdir repo && cd repo && git init
git remote add origin <url>
git fetch --depth 1 --no-tags --no-write-fetch-head origin tag <tag>
git branch master <tag>
git checkout

为了避免分离的头部状态,我们将默认分支(在本例中为 master)设置为指向我们的标记/提交。

在我看来,使这种方法更好的是它真正只获取一个标签。我们还避免创建无用的 FETCH_HEAD,因为tag <tag>语法会将标签本地保存在 refs/tags/* 下。这--no-tags将阻止 git 下载可能指向同一提交的其他标签。

--no-tags tag <tag>语法的替代方法是

git config --add remote.origin.fetch 'refs/tags/*:refs/tags/*'

现在我们的 fetch 操作变成了

git fetch --depth 1 --no-write-fetch-head origin <tag>

根据我的经验,列出的其他方法将下载单个提交以及与该特定提交关联的所有标签。例如,检查任何 Google 源代码库,git clone -b <tag> --depth 1 <url>您最终会得到一堆标签,这些标签都链接到同一个提交。git log这对大多数人来说都不是问题,但是当您有 10-15 个与提交相关联的标签时,它会让事情变得非常难看。第三方也不清楚您对哪个标签感兴趣。假设您正在克隆它以将其作为子模块添加到另一个项目......当标签 x 存在时,用户将无法告诉您您对标签感兴趣标记 s 到 z。最终标签都指向同一个提交,所以没关系,但是有一个标签更清楚。

于 2022-03-05T17:28:30.017 回答
0

我能够使用 git clone --config 选项来完成此操作,我从这个答案中了解到: https ://stackoverflow.com/a/43759576/1330650

我的场景涉及 Azure DevOps 管道中的稀疏签出,我需要使用提交哈希而不是分支名称来克隆存储库。clone 命令不接受提交哈希作为参数。解决方法是设置一个包含 refspec 的配置变量 (-c),因为该 refspec 可以使用提交哈希而不是分支名称:

git clone -c remote.origin.fetch=+<commit hash>:refs/remotes/origin/<commit hash> <repo_url> --no-checkout --progress --depth 1
git sparse-checkout init --cone
git sparse-checkout set <file list>
git checkout <commit hash>
于 2021-07-19T21:06:23.017 回答
0

我将此片段与 GNU make 一起使用来关闭任何修订标签、分支或哈希

它在 git 版本 2.17.1 上进行了测试

${dir}:
    mkdir -p ${@D}
    git clone --recursive --depth 1 --branch ${revison} ${url} ${@} \
 || git clone --recursive --branch ${revison} ${url} ${@} \
 || git clone ${url} ${@}
    cd ${@} && git reset --hard ${revison}
    ls $@




于 2019-06-27T18:28:12.443 回答
-1

对于单个文件并且当提交号已知时,可以使用 wget onliner:

wget https://raw.githubusercontent.com/torvalds/linux/896066ee1cf4d653057dac4e952f49c96ad16fa7/README
于 2021-08-15T19:12:07.277 回答
-2

git clone https://github.com/ORGANIZATION/repository.git(克隆存储库)

cd repository (navigate to the repository)

git fetch origin 2600f4f928773d79164964137d514b85400b09b2

git checkout FETCH_HEAD

于 2018-07-10T05:59:36.253 回答
-6
git clone -o <sha1-of-the-commit> <repository-url> <local-dir-name>

git使用这个词origin而不是众所周知的revision

以下是手册的片段$ git help clone

--origin <name>, -o <name>
    Instead of using the remote name origin to keep track of the upstream repository, use <name>.
于 2015-06-06T08:02:01.223 回答