Cloning a specific commit in Git allows you to start your repository from the exact state of a project at a particular point in time. This guide explains how to clone a specific commit from a Git repository.
Understanding commits and hashes
In order to understand how to clone a specific commit, it's helpful to understand how Git stores commits, and what it actually means to "clone" an object in Git.
- Commit hash: A unique identifier for a commit. It's a long string created by the SHA-1 hashing algorithm, representing the state of a repository at the time of the commit.
- Clone: To clone a repository means to make a complete local copy of that repository, including all the history, branches, tags, and commits.
Step 1: clone the repository
To clone a specific commit, you first need to clone the repository as you would normally. Navigate to the directory where you want the copy repository to reside, then run:
git clone <repository-url>
Replace <repository-url>
with the URL of the Git repository. This command clones the repository to your local machine but checks out the main
branch by default.
For a more detailed guide on the different methods of cloning (ssh/https) see this guide on Git cloning.
Step 2: check out the specific commit
After cloning the repository, navigate into the directory:
cd <repository-name>
To check out a specific commit, you need the commit hash. If you already know the commit hash, you can proceed to the next step. If not, you can list all of the commits with:
git log --oneline
The commit hashes will be the string of 13 characters preceding each commit.
This will display a shortened list of commits. Locate the commit you are interested in and note its hash. To check out this specific commit, use:
git checkout <commit-hash>
Replace <commit-hash>
with the actual commit hash. This command points your working directory to the state of the repository at that commit, effectively detaching your HEAD (the pointer to the current commit) from the branch history.
Considerations when cloning a specific commit
Detached HEAD state: Checking out a specific commit puts your repository in a "detached HEAD" state. In this state, any new commits you make will be orphaned when you switch back to a branch, unless you create a new branch starting from the detached HEAD.
Creating a New Branch: If you plan to make changes starting from this specific commit, it's a good idea to create a new branch:
Terminalgit checkout -b <new-branch-name> <commit-hash>This command creates a new branch named
<new-branch-name>
starting from<commit-hash>
.
Additional operations
Fetching a specific commit without cloning: If you only need to fetch a specific commit without cloning the entire repository, you can use sparse-checkout:
Terminalmkdir <repo-name>cd <repo-name>git initgit remote add origin <repository-url>git fetch origin <commit-hash>git checkout FETCH_HEADmkdir <repo-name>
- This command creates a new directory with the name
<repo-name>
. This directory will serve as a local repository. - Example:
mkdir myproject
- This command creates a new directory with the name
cd <repo-name>
- This changes the current working directory to the newly created directory.
- Example:
cd myproject
git init
- This initializes a new Git repository in the current directory. This sets up all the necessary Git files and structures needed to begin tracking files and commits in the repository.
git remote add origin <repository-url>
- This command adds a new remote to your local Git repository.
origin
is a conventional name used for the primary or original repository.<repository-url>
should be replaced with the URL of the Git repository from which you want to fetch data. - Example:
git remote add origin https://github.com/user/repo.git
- This command adds a new remote to your local Git repository.
git fetch origin <commit-hash>
- This command retrieves the commit specified by
<commit-hash>
from the remote repository linked asorigin
. This does not fetch the entire branch or tags, just the specific commit and the history necessary to reach it. - Example:
git fetch origin a1b2c3d4e5f6
- This command retrieves the commit specified by
git checkout FETCH_HEAD
- After fetching,
FETCH_HEAD
refers to the last fetched branch or commit from a remote repository. This command checks out the state of the repository at the fetched commit, putting the working directory in that state. You will be in a 'detached HEAD' state at this commit, meaning you're not working on any particular branch. For a more detailed guide on the 'detached HEAD state', including how to get out of it, see this guide on resolving a detached head state.
- After fetching,
Practical Usage
This method is particularly useful in scenarios where bandwidth or storage is limited. It allows you to access a specific part of a repository, such as a particular commit, without downloading the history associated with other parts of the project.
Downloading files from a specific commit: To download specific files from a commit without checking out, run:
Terminalgit fetch origingit checkout origin/<branch-name> -- <file-path>
This fetches updates from the original repository and then checks out specific files from a particular branch at their state in the most recent commit.
For futher reading on cloning in Git, see the official documentation.