How to git clone a specific commit
Clone a specific Git commit
There is no single command that enables a developer to clone a specific Git commit. In Git, developers can only clone branches, not commits.
But there is a workaround. To achieve the equivalent result of performing a git clone of a specific Git commit, follow these two steps:
- Clone the branch that contains the specific Git commit.
- Reset the state of your workspace back to that specific Git commit.
An alternative approach is to clone the repository that contains the specific Git commit, and then create a new branch from that specific commit point.
Benefits and drawbacks to each approach
The benefit of the clone-and-reset approach is that you stay on one branch the whole time. However, if you must push your changes back to the repo you cloned, you may run into problems, especially if it’s a shared repository.
The drawback to the clone-and-branch approach is that it creates a new branch — although quite frankly, that’s not really a big deal. A local branch can easily be deleted.
If updates need to be pushed back to the remote Git repo, the new branch can be merged into the original branch and pushed back to the server without disrupting the commit history.
The clone-and-branch approach is the safer method if the changes you make after you git clone a specific commit must be pushed back to the server.
Steps to git clone a specific commit
Follow these steps to clone a specific Git commit:
- Obtain the URL of the remote repository.
- Perform a git clone of the remote repo.
- Switch to the branch that contains the commit.
- Obtain the seven-digit SHA id of the commit to clone.
- Issue a hard git reset that points to the commit id.
Specific git commit clone example
I have a GitHub repository where the third last commit on the master branch has the id of fcbd92b.
Here is the code to clone this specific Git commit:
clone-specific@commit:~$ git clone https://github.com/cameronmcnz/rock-paper-scissors.git Cloning into 'rock-paper-scissors'... remotes/origin/development
A look at the git log confirms the third commit back has the id of fcbd92b:
clone-specific@commit:~$ git log -n 5 --oneline 3ab3c6f (HEAD) Added stage to Jenkinsfile 1d1bbfc Fixed Jenkinsfile fcbd92b Update Jenkinsfile 326f527 Merge remote-tracking branch 'origin/master' 84ff492 Create rita.txt
Reset clone to specific Git commit id
To reset HEAD, the working directory and the commit history back to the specific Git commit with the id of fcbd92b, you’ll need to perform a hard git reset.
clone-specific@commit:~$ git reset --hard fcbd92b
HEAD is now at fcbd92b Update Jenkinsfile
When this command completes, the final result is equivalent to a git clone of specific commit.
Alternate Git commit id clone strategy
An alternate strategy is to follow these three steps:
- Clone the remote repository.
- Create a new branch based on the specific commit id.
- Switch to the new branch.
Commands to clone a single Git commit id
The result of running the following commands is equivalent to the clone of a single Git commit.
clone-specific@commit:~$ git clone https://github.com/cameronmcnz/rock-paper-scissors.git
Cloning into 'rock-paper-scissors'...
clone-specific@commit:~$ git branch specific-commit-branch fcbd92b
specific-commit-branch created
clone-specific@commit:~$ git switch specific-commit-branch
Switched to branch 'specific-commit-branch'
An inspection of the git log after the branch was created and checked out shows the local repository’s state points to the commit of interest:
clone-specific@commit:~$ git log --all --decorate --oneline --graph * 3ab3c6f (origin/master, origin/HEAD, master) Update Jenkinsfile * 1d1bbfc Update Jenkinsfile * fcbd92b (HEAD -> specific-commit-branch) Update Jenkinsfile
How to minimize clone depth
There are many reasons why a developer might want to clone a specific Git commit.
One of those reasons is to minimize the amount of data returned from the server. After all, a repository with a rich commit history pulls down a significant amount of data.
Shallow git clone for a specific commit id
One way to avoid deep clones is to set a clone depth. This strategy is also known as doing a shallow copy.
clone-specific@commit:~$ git clone --depth 5 https://github.com/cameronmcnz/rock-paper-scissors.git
Cloning into 'rock-paper-scissors'...
The result of issuing this command is that it pulls down only five commits.
If the specific Git commit to clone is included in this shallow copy, the reset and branch commands listed above can be performed on it.