How can I clone git repository with specific revision, something like I usually do in 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 To save online (remote) the reverted commit, you must to push enforcing origin:
git push origin -f --depth which is very important for large repos. This solution requires pulling all objects, and then resetting to an earlier revision. This is very time consuming and wasteful of network bandwidth.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. Note that some Git servers activate this option by default, e.g. Bitbucket Server enabled it since version 5.5+. See this answer on Stackexchange for a exmple of how to activate the configuration option.
UPDATE 1 For Git versions 1.7 < v < 2.5 use git clone and git reset, as described in Vaibhav Bajpai's answer
If you don't want to fetch the full repository then you probably shouldn't be using clone. You can always just use fetch to choose the branch that you want to 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.
# 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 fetch origin <sha1> works; it seems like you need to pass a named reference such as a tag or branch name. See kerneltrap.org/mailarchive/git/2009/1/13/4707444git fetch origin <SHA1> to switch to any revision I wanted after I'd fetched the master from the remote and done the reset --hard to actual instantiate the branch locally. I was not able to fetch the individual revisions directly. With git 1.7, git fetch origin <SHA1> did not work, as reported by @artur; you need to use git checkout <SHA1> followed by a reset --hard.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).
Omit the --depth flag to download the whole history and then checkout that branch or tag:
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).
--branch option is used for both branches and tagsCloning a git repository, aptly, clones the entire repository: there isn't a way to select only one revision to clone. However, once you perform git clone, you can checkout a specific revision by doing checkout <rev>.
git clone --single-branch ...You can use simply git checkout <commit hash>
in this sequence
git clone [URLTORepository] git checkout [commithash] commit hash looks like this 45ef55ac20ce2389c9180658fdba35f4a663d204.
git checkout makes the revision current. If you simply clone, you are at the tip of the default (or specified) branch, which is often not what you wanted.If you mean you want to fetch everything from the beginning up to a particular point, CB Bailey's answer is perfect. 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. 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 clone where you want the repo (gets everything to date — I know, not what is wanted, we're getting there) git checkout <sha1 rev> of the rev you wantgit reset --hardgit checkout -b mastermaster and switches to it.git reset --hard? The docs for that say "Resets the index and working tree. Any changes to tracked files in the working tree since <commit> [which defaults to HEAD, which is now <sha1 rev>] are discarded." But at this point we haven't made any changes since cloning, so what's the purpose? Does it truncate the current branch at <sha1 rev>?No need to download the whole history, and no need to call 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 Bailey's answer, that you will still download 1 unnecessary revision. 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.
2.40.0. Can you prove the opposite?fatal: Couldn't find remote ref faf2a5a6. So I upvoted your method, it's great.--depth=1, as specified in that answer's code block? From what I measured, that answer is slightly faster than mine.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. You can delete the tag from the original repo later to clean up.
Well, it's 2014 and it looks like CB 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.
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.
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:
# 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 2.49.0-rc0 finally added the --revision option to git clone https://github.com/git/git/commit/337855629f59a3f435dabef900e22202ce8e00e1
git clone --revision=<commit-ish> $OPTIONS $URL I was able to accomplish this using the git clone --config option, which I learned from this answer: 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. The clone command doesn't accept a commit hash as a parameter. 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:
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> git clone --branch ... where this only accepts a SHA, but won't work with a branch name or tag. Just saving people like me from having to find that out by trial and error so you know what this is useful for.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
git fetch local_copy origin_point differ from JamesGs git fetch origin refs/tags/tmptag?git fetch local_copy origin_point leave you in a state with an empty reduced-repo directory, only containing a .git. There is something else missing to these instructions...# 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.
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. (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)
#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 fetch --no-write-fetch-head --depth <n> If you don't need remote tracking and already know the the full commit hash :
mkdir repo && cd repo && git init git remote add --no-tags 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. 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).
git fetch --depth=1 --no-write-fetch-head [email protected]:torvalds/linux.git 9154301a47b33bdc273d8254c407792524367558 error: unknown option `no-write-fetch-head'--no-write-fetch-head was added in version 2.28if you just want to go to a specific commit and don't care about the progress past that point then you can simply do this:
git clone <repo URL> git reset --hard <commit-hash> with this, you will be standing at that specific commit. Useful if you are following a tutorial and the instructor asks you to clone a repo but that repo already has new commits on it.
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
$ 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
git reset --hard <sha1> git ls-remote <repo> <pattern> to list remote refs (including the hash). pattern is the name of a reference or a shell glob. If you omit pattern all refs are listed. Can optionally use --tags or --heads as an additional filter.I would suggest git clone --single-branch --branch NAME https://github.com/your/repo.git as explained below.
The following are given in other answers.
git reset --hard $SHA1 to go to the specific commit given by that hash. (Vaibhav Bajpai)git clone --depth=1 --branch NAME https://github.com/your/repo.git to only get the latest commit in the specific branch and nothing else (no history, no other branches) (Peter Kovac)git clone --branch NAME https://github.com/your/repo.git to get all history (of the desired branch AND other branches) and point to the latest commit of the desired branch (Peter Kovac)However, they do not appear to exactly match what the question is asking for, for the following reasons (corresponding to the 3 suggestions above):
I would suggest that git clone --single-branch --branch NAME https://github.com/your/repo.git provides the most matching answer, with just the whole single branch history obtained, and the HEAD pointer pointing to the latest commit (we see it as a straight line with git log --all --graph with HEAD pointing to the commit at the top/tip), whereas:
git clone --depth=1 --branch NAME https://github.com/your/repo.git then git log --all --graph only shows the tip of the branchgit clone --branch NAME https://github.com/your/repo.git then git log --all --graph shows the tree structure with the desired branch and other branches branching at various times from various other commits.The above were all tested with git version 2.24.3 ; I've read that --single-branch was added in git version 1.7.10.
mkdir linux-4.3.20151106 cd linux-4.3.20151106/ git init git fetch [email protected]: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 [email protected]: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 I use this snippet with GNU make to close any revision tag, branch or hash
it was tested on git version 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 $@ For single files and when the commit number is known, one can use a wget onliner:
wget https://raw.githubusercontent.com/torvalds/linux/896066ee1cf4d653057dac4e952f49c96ad16fa7/README git clone https://github.com/ORGANIZATION/repository.git (clone the repository)
cd repository (navigate to the repository)
git fetch origin 2600f4f928773d79164964137d514b85400b09b2
git checkout FETCH_HEAD
git clone -o <sha1-of-the-commit> <repository-url> <local-dir-name> git uses the word origin in stead of popularly known revision
Following is a snippet from the manual $ git help clone
--origin <name>, -o <name> Instead of using the remote name origin to keep track of the upstream repository, use <name>. --depth=1 is not mentioned in the answer, so why would you say this answer worked if you added more things that aren't mentioned here? I'm happy it worked out for you, but this answer is misleading and doesn't answer the question even in part. Hence the downvotes.git clone <url> <local_dir_name>, just try it for yourself. The only difference is that the remote (shown using git remote) will be called some cryptic sha1 sequence instead of the name "origin" that is customary. In other words, the <sha1-of-the-commit> mentioned in this answer has no bearing whatsoever on which revisions are fetched from the server or which branch will be checked out.git clone -o 896066ee1cf4d653057dac4e952f49c96ad16fa7 https://github.com/torvalds/linux.git linux --depth=1. This gives me revision 8a28d674 and not 896066ee as you and this answer claims.
git clone -b 10.1 https://github.com/MariaDB/server.git --depth=1 mariadb-server-srcgit clonecommand that downloads just that one commit.