简体   繁体   English

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

[英]How to clone git repository with specific revision/changeset?

How can I clone git repository with specific revision, something like I usually do in Mercurial:我如何克隆具有特定修订版的 git 存储库,就像我通常在 Mercurial 中所做的那样:

hg clone -r 3 /path/to/repository
$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1

To again go back to the most recent commit再次回到最近的提交

$ git pull

UPDATE 2 Since Git 2.5.0 the feature described below can be enabled on server side with configuration variable uploadpack.allowReachableSHA1InWant , here the GitHub feature request and the GitHub commit enabling this feature .更新 2Git 2.5.0 开始,可以在服务器端使用配置变量uploadpack.allowReachableSHA1InWant启用下面描述的功能,这里是GitHub 功能请求GitHub 提交启用此功能 Note that some Git servers activate this option by default, eg Bitbucket Server enabled it since version 5.5+ .请注意,某些 Git 服务器默认启用此选项,例如 Bitbucket Server 从5.5+ 版本开始启用它。 See this answer on Stackexchange for a exmple of how to activate the configuration option.有关如何激活配置选项的示例,请参阅Stackexchange 上的答案

UPDATE 1 For Git versions 1.7 < v < 2.5 use git clone and git reset, as described in Vaibhav Bajpai's answer更新 1对于 Git 版本1.7 < v < 2.5使用 git clone 和 git reset,如Vaibhav Bajpai 的回答中所述

If you don't want to fetch the full repository then you probably shouldn't be using clone .如果您不想获取完整的存储库,那么您可能不应该使用clone You can always just use fetch to choose the branch that you want to fetch.你总是可以使用 fetch 来选择你想要获取的分支。 I'm not an hg expert so I don't know the details of -r but in git you can do something like this.我不是汞专家,所以我不知道-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

To clone only one single specific commit on a particular branch or tag use:要在特定分支或标签上克隆一个特定的提交,请使用:

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

Unfortunately, NAME can only be branch name or tag name (not commit SHA).不幸的是, NAME只能是分支名称或标签名称(不是提交 SHA)。

Omit the --depth flag to download the whole history and then checkout that branch or tag:省略--depth标志以下载整个历史记录,然后检出该分支或标签:

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

This works with recent version of git (I did it with version 2.18.0 ).这适用于最新版本的 git (我用版本2.18.0 )。

Cloning a git repository, aptly, clones the entire repository: there isn't a way to select only one revision to clone.克隆一个 git 存储库,恰当地,克隆整个存储库:没有办法只选择一个修订版进行克隆。 However, once you perform git clone , you can checkout a specific revision by doing checkout <rev> .但是,一旦您执行git clone ,您就可以通过执行checkout <rev>来检出特定的修订checkout <rev>

If you mean you want to fetch everything from the beginning up to a particular point, Charles Bailey's answer is perfect.如果您的意思是要获取从开始到特定点的所有内容,那么 Charles Bailey 的答案是完美的。 If you want to do the reverse and retrieve a subset of the history going back from the current date, you can use git clone --depth [N] where N is the number of revs of history you want.如果您想反向操作并检索从当前日期返回的历史子集,您可以使用git clone --depth [N]其中 N 是您想要的历史转数。 However:然而:

--depth - 深度

Create a shallow clone with a history truncated to the specified number of revisions.创建一个将历史记录截断为指定修订数量的浅层克隆。 A shallow repository has a number of limitations (you cannot clone or fetch from it, nor push from nor into it), but is adequate if you are only interested in the recent history of a large project with a long history, and would want to send in fixes as patches.浅层存储库有很多限制(你不能从它克隆或获取,也不能从它推入或推入),但如果你只对一个历史悠久的大型项目的近期历史感兴趣,并且想要将修复作为补丁发送。

Just to sum things up (git v. 1.7.2.1):总结一下(git v. 1.7.2.1):

  1. do a regular git clone where you want the repo (gets everything to date — I know, not what is wanted, we're getting there)在你想要仓库的地方做一个常规的git clone (让所有的东西都是最新的——我知道,不是想要的,我们正在那里)
  2. git checkout <sha1 rev> of the rev you want git checkout <sha1 rev>你想要的 rev
  3. git reset --hard
  4. git checkout -b master

You Can use simply git checkout <commit hash>您可以简单地使用git checkout <commit hash>

in this sequence在这个序列中

bash git clone [URLTORepository] git checkout [commithash]

commit hash looks like this "45ef55ac20ce2389c9180658fdba35f4a663d204"提交哈希看起来像这样“45ef55ac20ce2389c9180658fdba35f4a663d204”

TL;DR - Just create a tag in the source repository against the commit you want to clone up to and use the tag in the fetch command. TL;DR - 只需在源存储库中针对要克隆到的提交创建一个标签,并在 fetch 命令中使用该标签。 You can delete the tag from the original repo later to clean up.您可以稍后从原始存储库中删除标签以进行清理。

Well, its 2014 and it looks like Charles Bailey's accepted answer from 2010 is well and truly outdated by now and most (all?) of the other answers involve cloning, which many people are hoping to avoid.好吧,它是 2014 年,看起来 Charles Bailey 从 2010 年开始接受的答案现在已经完全过时了,大多数(全部?)其他答案都涉及克隆,许多人希望避免这种情况。

The following solution achieves what the OP and many others are looking for, which is a way to create a copy of a repository, including history, but only up to a certain commit.以下解决方案实现了 OP 和许多其他人正在寻找的东西,这是一种创建存储库副本的方法,包括历史记录,但仅限于某个提交。

Here are the commands I used with git version 2.1.2 to clone a local repo (ie. a repository in another directory) up to a certain point:以下是我在 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

Hopefully this solution keeps working for a few more years!希望这个解决方案还能再工作几年! :-) :-)

No need to download the whole history, and no need to call git init :无需下载整个历史记录,也无需调用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

This has the disadvantage , to CB Baileys answer, that you will still download 1 unnecessary revision.对于 CB Baileys 的回答,这有一个缺点,即您仍然会下载 1 个不必要的修订版。 But it's technically a git clone (which the OP wants), and it does not force you to download the whole history of some branch.但它在技术上是一个git clone (OP 想要的),它不会强迫您下载某个分支的整个历史记录。

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.使用上述答案中的 2 个( 如何使用特定修订版/变更集克隆 git 存储库以及如何使用特定修订版/变更集克隆 git 存储库? )帮助我想出了一个确定性。 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.如果您想克隆到某个点,那么该点必须是一个标签/分支,而不仅仅是一个 SHA,否则 FETCH_HEAD 会被混淆。 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.在 git fetch 集之后,如果您使用分支或标签名称,则会收到响应,如果您仅使用 SHA-1,则不会收到响应。
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然后创建我的新空白 repo,以我的本地副本作为其来源

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我注意到它是因为如果你使用 SHA-1 代替上面的分支,什么都不会发生,所以响应意味着它有效

/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现在在我的情况下,我需要把它放回 gitlab,作为一个新的 repo,所以我做了

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这意味着我可以使用git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -k从 origin_point 重建我的仓库git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -k 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. git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -k远程挑选樱桃然后使用git push origin将整个地块上传回新家。

Hope that helps someone希望能帮助某人

My version was a combination of accepted and most upvoted answers.我的版本是接受和最受好评的答案的组合。 But it's a little bit different, because everyone uses SHA1 but nobody tells you how to get it但它有点不同,因为每个人都使用 SHA1 但没有人告诉你如何获得它

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

now you can see all branches & commits现在你可以看到所有的分支和提交

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

Finally you know SHA1 of desired commit最后你知道所需提交的 SHA1

git reset --hard <sha1>

I use this snippet with GNU make to close any revision tag, branch or hash我将此代码段与 GNU make 一起使用来关闭任何修订标记、分支或哈希

it was tested on git version 2.17.1它在 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 $@




# 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> 

you can't get a revision without histories if not set uploadpack.allowReachableSHA1InWant=true on server side, while you can create a tag for it and clone the special tag instead.如果未在服务器端设置uploadpack.allowReachableSHA1InWant=true ,则无法获得没有历史记录的修订版,而您可以为其创建标签并克隆特殊标签。

Full workflow for cloning a single branch, choosing a commit, then checking out that specific commit... This method requires git version 2.28.0 or higher to use the option --no-write-fetch-head , tested with version 2.35.3.克隆单个分支的完整工作流程,选择一个提交,然后检查该特定提交...此方法需要 git 版本 2.28.0 或更高版本才能使用选项--no-write-fetch-head ,已使用版本 2.35 进行测试。 3. (If you already know the full sha1 hash of the commit you want, please skip ahead to the second method available in the final code block) (如果您已经知道所需提交的完整 sha1 hash,请跳至最终代码块中提供的第二种方法)

#Create empty git repo
mkdir repo && cd repo && git init

#add remote, configure it to track <branch>
git remote add --no-tags -t <branch> -m <branch> origin <url>

#fetch objects from remote repo
git fetch --no-write-fetch-head

#examine commits and logs to decide which one we will use
git log --oneline origin

#Once you have found the commit of interest copy the abbreviated hash or save as variable
commit=<sha1>

#rename our default branch to match remote branch
git branch -m <branch>

#set branch head to desired commit
git branch <branch> $commit

#set remote branch as upstream for <branch>
git branch -u origin <branch>

#All done time to checkout
git checkout

To optionally truncate the history of the local branch execute:要选择性地截断本地分支的历史记录,请执行:

git fetch --no-write-fetch-head --depth <n> ./ <branch>

To truncate the remote branch history you can execute the following, but keep in mind that if you truncate history to a commit newer than the commit you checked out git status will tell you that you have diverged from the remote by <n> commits要截断远程分支历史记录,您可以执行以下操作,但请记住,如果您将历史记录截断为比您签出的提交更新的提交, git status将告诉您您已经从远程分支<n>提交

git fetch --no-write-fetch-head --depth <n>

If you don't need remote tracking and already know the the full commit hash:如果您不需要远程跟踪并且已经知道完整的提交 hash:

mkdir repo && cd repo && git init
git remote --no-tags add origin <url>
git fetch --depth 1 --no-write-fetch-head origin <sha1>
#Set default local branch (master in this case) head to <sha1>
git branch master <sha1>
git checkout

What makes this method better in my opinion is that it truly fetches only a single commit.在我看来,使这种方法更好的是它真正只获取一次提交。 We also avoid creating a FETCH_HEAD or ORIG_HEAD leaving our.git directory squeaky clean.我们还避免创建 FETCH_HEAD 或 ORIG_HEAD,使我们的 .git 目录干净利落。 This also leaves the reflog clean (with a single entry) as opposed to having two entries due to a git reset --hard commit Without the need for remote tracking and using fetch --depth 1 it creates the smallest possible clone (shallow clone).这也使 reflog 保持干净(只有一个条目),而不是由于git reset --hard commit无需远程跟踪和使用fetch --depth 1它创建尽可能小的克隆(浅克隆) .

I was able to accomplish this using the git clone --config option, which I learned from this answer: https://stackoverflow.com/a/43759576/1330650我能够使用 git clone --config 选项完成此操作,这是我从以下答案中了解到的: https : //stackoverflow.com/a/43759576/1330650

My scenario involves a sparse checkout in an Azure DevOps pipeline, where I need to clone a repo using a commit hash, not a branch name.我的场景涉及 Azure DevOps 管道中的稀疏结帐,我需要使用提交哈希而不是分支名称克隆存储库。 The clone command doesn't accept a commit hash as a parameter. clone 命令不接受提交哈希作为参数。 The workaround is to set a configuration variable (-c) containing a refspec, because that refspec can use a commit hash instead of a branch name:解决方法是设置一个包含 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>
mkdir linux-4.3.20151106
cd linux-4.3.20151106/
git init
git fetch git@github.com:torvalds/linux.git 9154301a47b33bdc273d8254c407792524367558

error: unknown option `no-write-fetch-head'        
usage: git fetch [<options>] [<repository> [<refspec>...]]   or: git fetch [<options>] <group>                                      
   or: git fetch --multiple [<options>] [(<repository> | <group>)...]   or: git fetch --all [<options>]       



 git --version
git version 2.17.1

export https_proxy=http://192.168.1.3:1080;export http_proxy=http://192.168.1.3:1080
add-apt-repository ppa:git-core/ppa
apt update
apt-get install --only-upgrade git

 git --version
git version 2.38.0


 git fetch git@github.com:torvalds/linux.git 9154301a47b33bdc273d8254c407792524367558 --no-write-fetch-head --depth=1 
remote: Enumerating objects: 54692, done.
remote: Counting objects: 100% (54692/54692), done.
remote: Compressing objects: 100% (50960/50960), done.
remote: Total 54692 (delta 3828), reused 29210 (delta 2966), pack-reused 0
Receiving objects: 100% (54692/54692), 147.35 MiB | 2.85 MiB/s, done.
Resolving deltas: 100% (3828/3828), done.
 


git branch master 9154301a47b33bdc273d8254c407792524367558


git checkout
 

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

cd repository (navigate to the repository)

git fetch origin 2600f4f928773d79164964137d514b85400b09b2

git checkout FETCH_HEAD

For single files and when the commit number is known, one can use a wget onliner:对于单个文件,当提交号已知时,可以使用 wget 在线工具:

wget https://raw.githubusercontent.com/torvalds/linux/896066ee1cf4d653057dac4e952f49c96ad16fa7/README

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

hg clone -r 3 /path/to/repository

Have you heard about Rigidhackpro they are fake hackers, an attempt was made on my sister. 您是否听说过Rigidhackpro是伪造的黑客,曾对我姐姐进行过尝试。 the only true and legit hack specialist i can prescribe to anyone is fasthackresults @Gmail,com his a prof at tech and credit score operations 我可以向任何人开出的唯一真正合法的黑客专家是fasthackresults @ Gmail,com他是技术和信用评分操作的专家

git clone -o <sha1-of-the-commit> <repository-url> <local-dir-name>

git uses the word origin in stead of popularly known revision git使用单词origin而不是众所周知的revision

Following is a snippet from the manual $ git help clone以下是手册$ git help clone的片段

--origin <name>, -o <name>
    Instead of using the remote name origin to keep track of the upstream repository, use <name>.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM