如何克隆git存储库与特定的修订/更改集?

我如何用特定的版本克隆git存储库,就像我通常在Mercurial中做的那样:

hg clone -r 3 /path/to/repository
646477 次浏览

克隆一个git存储库,恰当地说,就是克隆整个存储库:没有办法只选择一个修订版本来克隆。然而,一旦你执行了git clone,你就可以通过执行checkout <rev>来检出一个特定的修订。

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

更新1对于Git版本1.7 < v < 2.5使用Git克隆和Git重置,如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

如果你的意思是你想要从开始到某一点的所有东西,查尔斯·贝利的答案是完美的。如果你想做相反的事情,从当前日期检索历史的子集,你可以使用git clone --depth [N],其中N是你想要的历史的转速数。然而:

——深度

创建一个浅克隆,其历史记录被截断为指定的修订数。浅存储库有许多限制(您不能从它复制或获取,也不能从它推入或进入它),但如果您只对具有较长历史的大型项目的最近历史感兴趣,并且希望以补丁的形式发送修复,那么浅存储库就足够了。

总结一下(git v. 1.7.2.1):

  1. 在你想要回购的地方做一个常规的git clone(得到所有的日期-我知道,不是想要的,我们正在那里)
  2. 你想要的rev的git checkout <sha1 rev>
  3. git reset --hard
  4. git checkout -b master
$ git clone $URL
$ cd $PROJECT_NAME
$ git reset --hard $SHA1

再次返回到最近的提交

$ git pull

为了在线(远程)保存还原的提交,你必须强制执行origin:

git push origin -f

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

在这个序列中

< p > <代码> bash git克隆[URLTORepository] Git checkout [commit] < /代码> < / p >

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

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

好吧,现在已经是2014年了,看起来查尔斯·贝利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

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

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

使用上述答案中的两个(如何克隆git存储库与特定的修订/更改集?如何克隆git存储库与特定的修订/更改集?) 帮我想出了一个定语。如果你想克隆到一个点,那么这个点必须是一个标签/分支,而不仅仅是一个SHA,否则FETCH_HEAD就会混淆。在git获取集之后,如果你使用一个分支或标记名,你会得到一个响应,如果你简单地使用SHA-1,你不会得到响应 以下是我所做的:- 从实际的源

创建一个完整的完整工作克隆的完整回购
cd <path to create repo>
git clone git@<our gitlab server>:ui-developers/ui.git

然后在有趣的地方创建一个本地分支

git checkout 2050c8829c67f04b0db81e6247bb589c950afb14
git checkout -b origin_point

然后创建我的新的空白回购,我的本地副本作为它的起源

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

那时我得到了这样的回应。我指出这一点是因为如果使用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

现在在我的情况下,我需要把它放回gitlab,作为一个新的repo,所以我做了

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

这意味着我可以通过使用git --git-dir=../ui/.git format-patch -k -1 --stdout <sha1> | git am -3 -k来远程拾取樱桃,然后使用git push origin将整个区块上传到它的新家,从而从原始点重建我的回购。

希望这能帮助到别人

我的版本是公认的答案和最多赞的答案的结合。但它有点不同,因为每个人都使用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>

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

cd repository (navigate to the repository)

git fetch origin 2600f4f928773d79164964137d514b85400b09b2

git checkout FETCH_HEAD

要在特定的分支或标记上克隆只有一个特定的提交,请使用:

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(我使用版本2.18.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 $@








# 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,你就不能得到没有历史记录的修订,而你可以为它创建一个标记并克隆特殊标记。

我能够使用git clone——config选项来完成这一点,这是我从这个回答中学到的: https://stackoverflow.com/a/43759576/1330650 < / p >

我的场景涉及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>

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

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

克隆单个分支的完整工作流程,选择提交,然后检查特定的提交…此方法需要2.28.0或更高版本的git来使用选项--no-write-fetch-head,使用2.35.3版本进行测试。(如果你已经知道你想要提交的完整sha1哈希值,请跳过最后一个代码块中的第二个方法)

#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

可以选择截断本地分支的历史记录:

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

要截断远程分支历史记录,你可以执行以下命令,但请记住,如果你将历史记录截断为一个比你签出的提交更新的提交,git status将告诉你,你已经通过<n>提交偏离了远程

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

如果你不需要远程跟踪,并且已经知道完整的提交散列:

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
在我看来,这个方法更好的地方在于它真正只获取一个提交。我们还避免创建FETCH_HEAD或ORIG_HEAD,使.git目录保持干净。这也使reflog干净(只有一个条目),而不是由于git reset --hard commit而有两个条目 在不需要远程跟踪和使用fetch --depth 1的情况下,它创建了尽可能小的克隆(浅克隆)

不需要下载整个历史,也不需要调用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

这有缺点,对CB百利的答案,你仍然会下载1个不必要的修订。但它在技术上是一个git clone (OP想要的),并且它不会强迫你下载某个分支的整个历史记录。

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