如何克隆具有特定版本/变更集的git存储库?

Joh*_*ohn 363 git revision git-clone

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

hg clone -r 3 /path/to/repository
Run Code Online (Sandbox Code Playgroud)

Vai*_*pai 805

$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1
Run Code Online (Sandbox Code Playgroud)

再次回到最近的提交

$ git pull
Run Code Online (Sandbox Code Playgroud)

  • 对于大型回购,这不是一个好的选择,因为它可以提取所有东西. (64认同)
  • @FlorianSegginger如果我想要克隆一个特定的版本,那可能是我不想克隆所有内容,而只是克隆那个版本.对我来说这是问题.此解决方案回答了另一个问题:"如何查看我的仓库中的特定修订?".获取整个回购正是这里很多人想要避免的. (17认同)
  • 这只有在提交位于主分支中时才有效,如果不是它会弄乱本地引用.为什么git重置而不是git checkout? (12认同)
  • 这个解决方案应该是最重要的。没有人关心它“不是最佳的”,这是 OP 所要求的。具体来说:“如何克隆具有特定修订版的 git 存储库”? (2认同)
  • 没有解决实际问题恕我直言,因为能够在克隆期间指定修订还允许我使用`--depth`,这对于大型存储库非常重要。此解决方案需要拉动所有对象,然后重置为较早的版本。这非常耗时且浪费网络带宽。 (2认同)

CB *_*ley 178

更新2Git 2.5.0开始,可以在服务器端使用配置变量启用下面描述的功能uploadpack.allowReachableSHA1InWant,此处GitHub功能请求启用此功能GitHub提交.请注意,默认情况下,某些Git服务器会激活此选项,例如Bitbucket Server自5.5+版本启用它.有关如何激活配置选项的详细信息,请参阅Stackexchange上的答案.

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

如果您不想获取完整的存储库,那么您可能不应该使用它clone.您始终可以使用fetch来选择要获取的分支.我不是一个hg专家,所以我不知道细节,-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
Run Code Online (Sandbox Code Playgroud)

  • @artur:你认为它不起作用,或者你已经尝试过它并不起作用? (46认同)
  • 使用git 1.4,我发现我能够使用`git fetch origin <SHA1>`切换到我从远程获取主服务器并完成`reset --hard`到实际实例化之后我想要的任何修订版本当地的分支机构.我无法直接获取单个修订版.使用git 1.7,`git fetch origin <SHA1>`不起作用,如@artur报道的那样; 你需要使用`git checkout <SHA1>`然后使用`reset --hard`. (37认同)
  • 我不认为`git fetch origin <sha1>`有效; 您似乎需要传递命名引用,例如标记或分支名称.见http://kerneltrap.org/mailarchive/git/2009/1/13/4707444 (30认同)
  • 这个答案已经过时了.这不适用于git 1.7和git 1.8,也不适用于https://和ssh协议.("找不到远程参考df44398762393c67af487edeb0831ad9579df4aa" - 它不是参考,它是一个提交.) (23认同)
  • git fetch origin <sha1>对我不起作用 (21认同)
  • 我刚刚将其与 ubuntu 18 中的 github https 和 git 客户端一起使用,效果很好。没有指定协议或任何具体内容 (6认同)
  • @CharlesBailey是的,我和Danny有同样的疑问,任何答案?我在bitbucket有一个项目,我想拉出特定提交的内容(我的意思是文件和文件夹). (5认同)
  • 通过SHA-1获取仅适用于http和rsync协议.见http://kerneltrap.org/mailarchive/git/2009/1/14/4716044/thread#mid-4716044 (5认同)
  • ********请*********删除此作为接受的答案.这已经过时了,并且已经有好几年了(这是几年的git版本) (4认同)
  • 如何获取替换<sha1>的参数? (2认同)
  • 有人可以解释这可怕的重置吗?如果我想检查一个错误是否在某个特定版本中,我可以跳过这个重置内容吗?就像暂时偷看之前的版本一样. (2认同)
  • 在提取中添加--depth = 1标志不会提取完整的提交历史记录。 (2认同)
  • Downvoted:试过它而不工作(致命:模糊的参数'FETCH_HEAD':未知的修订或路径不在工作树中.),我给出的提交哈希存在.后来看到下面的答案,这是非常容易和工作.您也可以编辑您的答案,以便给出@ Vaibhav的答案. (2认同)
  • 这在2.3.4中不起作用.具体来说,提取完成,但结帐会抱怨"<SHA1>不是树". (2认同)
  • 对于当前的GIT版本,它不再有效.我downvoted,因为这是一个版本特定的功能,服务器需要允许签出SHA.否则它必须是标签/分支 (2认同)
  • 请注意:要从 GitHub 获取,您需要使用 `git -c protocol.version=2 fetch origin &lt;sha&gt;`。 (2认同)

小智 51

克隆一个git存储库,恰当地克隆了整个存储库:没有办法只选择一个要克隆的修订版.但是,一旦执行git clone,您可以通过执行检查特定修订checkout <rev>.

  • 你不能这样做.`git clone`抓住整个存储库.获得后,您可以签出特定的修订版. (6认同)
  • 我不想只克隆一个修订版.我只想指定克隆的限制.换句话说,我想克隆一切到指定的版本. (4认同)
  • 换句话说,约翰,这不是Git的工作方式. (4认同)
  • 有一点需要注意; Git通常非常有效地存储历史记录,因此不会仅仅通过克隆一半的修订来节省大量空间. (4认同)

Wal*_*ndt 32

如果你的意思是你想要从一开始到特定的地方取得一切,那么Charles Bailey的答案是完美的.如果您想要反向并检索从当前日期返回的历史记录的子集,您可以使用git clone --depth [N] 其中N是您想要的历史记录转数.然而:

- 深度

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

  • 较新版本的git改进了浅克隆,你可以从中拉出. (4认同)

小智 24

总结一下(git v.1.7.2.1):

  1. 做一个git clone你想要回购的常规地点(得到所有东西到目前为止 - 我知道,不是想要什么,我们到达那里)
  2. git checkout <sha1 rev> 你想要的转速
  3. git reset --hard
  4. git checkout -b master

  • 掌握已在步骤4中存在的主人 (9认同)
  • 第3步和第4步有什么作用? (6认同)
  • @phill:为什么`git reset --hard`?该文档说"重置索引和工作树.工作树中跟踪文件的任何更改,因为<commit> [默认为HEAD,现在是`<sha1 rev>`]被丢弃." 但是在这一点上我们克隆后没有做任何改变,那么目的是什么呢?它会截断"<sha1 rev>"的当前分支吗? (3认同)

Jam*_*esG 19

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
Run Code Online (Sandbox Code Playgroud)

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

  • 这是一个好主意,您是回购的所有者,不确定它是否适用于您不维护的公共回购 (3认同)

Pet*_*vac 18

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

git clone --depth=1 --branch NAME https://github.com/your/repo.git
Run Code Online (Sandbox Code Playgroud)

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

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

git clone --branch NAME https://github.com/your/repo.git
Run Code Online (Sandbox Code Playgroud)

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

  • 这需要更多的支持。这比其他过时的答案要好得多。 (2认同)
  • @Sz。是的,“--branch”选项用于分支和标签 (2认同)
  • 您在哪里指定提交? (2认同)

M.O*_*man 14

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

在这个序列中

bash git clone [URLTORepository] git checkout [commithash]

commit hash看起来像这样"45ef55ac20ce2389c9180658fdba35f4a663d204"

  • 像上一篇一样 - 为什么在克隆后结帐。克隆后,您将在本地存储库中拥有完整的历史记录。为什么这个答案有这么多赞成票? (6认同)

Joh*_*nes 14

无需下载整个历史记录,也无需调用git init

git clone --depth=1 URL
git fetch --depth=1 origin SHA1
git checkout SHA1
git branch -D @{-1}  # if you want to tidy up the fetched branch
Run Code Online (Sandbox Code Playgroud)

对于 CB Baileys 的回答,这有一个缺点,即您仍然会下载 1 个不必要的修订版。但从技术上讲,它是git clone(OP想要的),并且它不会强迫您下载某个分支的整个历史记录。


NJS*_*NJS 6

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

我的场景涉及 Azure DevOps 管道中的稀疏签出,其中我需要使用提交哈希而不是分支名称来克隆存储库。克隆命令不接受提交哈希作为参数。解决方法是设置一个包含 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>
Run Code Online (Sandbox Code Playgroud)