Open a terminal and run git clone with the repository URL after it. Git makes a new local folder, copies the project in, and saves the source as a remote named origin.
It works with GitHub, GitLab, Bitbucket and Azure DevOps, over HTTPS or SSH. Most people reach for it when they join a project that already lives somewhere else.
Don’t think of it as a Subversion checkout. By default Git pulls down every version of every file in the history (Pro Git), so the first transfer is the big one. Later fetches only bring in new commits.
How to clone a Git repository step by step

Run git clone and the URL, and you end up with a folder that holds the whole project.
- Check that Git is installed with
git --version. - Copy the clone URL from the repository page on GitHub, GitLab, or Bitbucket.
- Open a terminal and move to the folder that should hold the project.
- Run
git clone <url>and wait for the transfer to finish. - Move into the new folder with
cdand start working.
The syntax is git clone <repository> [<directory>], and that second argument is optional. It sets the name of the target folder.
Leave it out and Git names the folder after the repository. Cloning libgit2 gives you a libgit2 directory, while git clone https://github.com/libgit2/libgit2 mylibgit gives you mylibgit instead (Pro Git, git-scm.com).
Git prints a “Cloning into” line as soon as the transfer starts. On a big project it sits there for a while. That’s normal.
If the version check in step 1 throws an error, install Git first, since the clone command won’t run without it.
Windows users get the Git Bash terminal with Git for Windows, and it takes the same commands as a macOS or Linux shell.
What does git clone create on your machine?
You get a complete local repository. Every commit from the remote comes along, plus a hidden .git directory and a working tree for whichever branch the remote has active. It is not a snapshot of the latest files.
Subversion users expect a checkout to fetch one working copy. Git receives a full copy of nearly all the data the server holds (Pro Git).
- The project files of the checked-out branch, ready to edit
- A
.gitdirectory holding the object database, the configuration and the entire history - A remote called origin that points at the URL you cloned from
- One remote-tracking branch for each remote branch, plus a single new local branch that gets checked out
Git files the remote under the remote name origin by default, through the remote.origin.url and remote.origin.fetch settings. The clone.defaultRemoteName setting or the --origin flag renames it, according to the git-clone manual.
The remote-tracking branches sit under refs/remotes/origin. They record where each branch stood on the remote repository when you cloned, and a plain git fetch updates them later.
To check the result, run git remote -v for the fetch and push URLs and git branch --remotes for the tracking branches.
Bare clones are the exception. There’s no working tree, and the git-clone manual states that neither remote-tracking branches nor the related configuration variables get created.
HTTPS or SSH: which clone URL should you use?
HTTPS is quicker to set up. SSH pays off on a machine you clone from every day. Both fetch the same repository, and the only real difference is how Git proves who you are.
| Protocol | Example URL | Authentication | Best for |
|---|---|---|---|
| HTTPS | https://github.com/user/repo.git | Token or credential helper | Firewalls, proxies, first clones |
| SSH | git@github.com:user/repo.git | SSH key pair | Daily work on a trusted machine |
| Local path | ../project | Filesystem permissions | Copying a repository on the same machine |
A local path needs no network and no credentials, only read access to the source folder.
HTTPS in practice
HTTPS gets through firewalls and proxies, needs no key, and is available on every repository whatever its visibility (GitHub Docs).
The annoyance shows up with private repositories, which need a token or a credential helper. Without a helper, Git asks for your credentials on every single clone.
SSH in practice
SSH needs a key pair on your computer, and only the public half goes to your account on the host (GitHub Docs). The private key stays local, and once it sits in ssh-agent the clone runs without a prompt.
The catch is the network. When port 22 is closed, GitHub Docs point to SSH over the HTTPS port as a fallback, and on some networks that fails too, which leaves HTTPS as the only option.
Most developers end up with both. HTTPS for throwaway clones, SSH for the repositories they push to daily.
How to authenticate when cloning a private repository
A private repository needs a credential, either a personal access token over HTTPS or an SSH key pair. Your account password no longer works on GitHub.com.
GitHub stopped accepting account passwords for Git operations on August 13, 2021, and requires token-based authentication, SSH keys included (GitHub Changelog, 2021).
Clone with a personal access token
Generate a token in your account settings, run the HTTPS clone, and paste the token when Git asks for a password. The walkthrough on getting a GitHub token covers the settings screens.
GitLab documents a one-line form that embeds the token: git clone https://<username>:<token>@gitlab.example.com/tanuki/awesome_project.git.
It has a cost, though. Git records the cloned URL in remote.origin.url, so the token stays in .git/config and travels with every copy of the folder.
Clone with an SSH key
- Generate a key pair with
ssh-keygen. - Add the public key to your account on the host, as in the guide on adding an SSH key to GitHub.
- Load the private key into ssh-agent so the passphrase is requested once per session.
- Clone with the SSH URL, for example
git@github.com:user/repo.git.
Store credentials with a credential helper
As of October 2026, GitHub Docs recommend GitHub CLI or Git Credential Manager for remembering HTTPS credentials.
- Git Credential Manager defaults to the macOS Keychain and the Windows Credential Manager (GCM documentation)
- GitHub CLI stores your Git credentials if you choose HTTPS during login
- git credential-cache keeps them in memory for 900 seconds by default
- The plaintext store saves them unprotected in a file, which GCM itself marks as insecure
How to clone with GitHub CLI, GitHub Desktop or Visual Studio Code
All of these run the same clone underneath, so the result matches a terminal clone. Use whichever one you already have open.
GitHub CLI
The command is gh repo clone OWNER/REPO, with an optional directory after it (GitHub CLI manual). Extra git clone flags go after a double dash, as in gh repo clone cli/cli -- --depth=1.
Leave out OWNER/ and it defaults to your own account. The protocol follows the git_protocol setting unless you pass a full URL. Cloning a fork also adds the parent repository as a remote named upstream.
Authenticate once with gh auth login and every clone after that skips the URL copying. It suits anyone already using GitHub CLI for pull requests.
GitHub Desktop
The clone options on a GitHub repository page include Open with GitHub Desktop, which clones the project into the app. GitHub Docs name it as the way to clone without authenticating on the command line, so a newcomer can clone through the GitHub Desktop app and skip the token step.
Visual Studio Code
VS Code clones from the Source Control view or the Command Palette, and both routes run the same Git command underneath.
- Select Clone Repository in Source Control, or run Git: Clone from the Command Palette
- Paste a URL, or pick Clone from GitHub and sign in to browse your repositories
- Choose a parent folder, then open the cloned project
A public repository cloned by URL generally needs no sign-in (VS Code documentation). After the clone, a Workspace Trust dialog asks whether you trust the folder, and the answer matters for code you didn’t write.
GitLab, Bitbucket and Azure DevOps
GitLab clones over SSH or HTTPS and names the folder after the repository. The GitLab for VS Code extension adds its own Git: Clone command for GitLab projects (GitLab Docs).
Bitbucket and Azure DevOps each show their own clone URL on the repository page, and the git clone command stays the same.
How to clone a specific branch or into a named folder
Add --branch <name> to check out a branch other than the remote’s default. Put a folder name at the end of the command to choose where the files land.
Here are both in one line: git clone --branch release-2 https://github.com/user/repo.git my-copy
--branchpoints the new HEAD at that branch, and in a non-bare repository it’s the branch that gets checked out--single-branchfetches only the history leading to one branch tip, and later fetches update only that remote-tracking branch- The folder argument names the target directory, and a dot clones into the current folder, which has to be empty
Without --single-branch, Git still downloads every branch. The --branch flag only changes which one gets checked out.
Passing --depth switches single-branch on automatically, unless --no-single-branch is given (git-clone manual).
The same flag accepts a tag name. A tag isn’t a branch, so the clone lands in a detached HEAD state at the tagged commit, per the git-clone manual.
Commits made there belong to no branch. Run git switch -c fix-login straight after the clone to create a new branch before touching any file.
Which clone type fits: full, shallow, partial or sparse?
A full clone suits daily development and a shallow clone suits throwaway builds. Blobless partial clones help with very large repositories, and sparse checkout makes sense when only a few directories matter. Get it wrong and you pay in download time or in missing history.
| Clone type | Flag | Advantage | Limitation |
|---|---|---|---|
| Full | none | Every commit, tree, and file available offline | Slowest start on large repositories |
| Shallow | –depth 1 | Smallest transfer, latest commit only | History-dependent commands stop at the cut-off |
| Partial | –filter=blob:none | Full commit history, file contents on demand | Needs the server for later checkouts |
| Sparse | –sparse | Only chosen directories in the working tree | Does not shrink the download on its own |
Shallow clones
The GitHub Blog (December 2020) advises shallow clones only for builds that delete the repository afterwards.
A later git fetch inside a shallow clone can pull down an almost complete history, depending on how others contribute, which defeats the purpose.
They fit continuous integration builds that compile once and discard the folder. Anything that walks past the truncated history breaks, and --depth quietly implies --single-branch too.
Partial clones
The --filter option tells the server to hold back objects until Git needs them. --filter=blob:none omits all file contents, while --filter=blob:limit=1m omits only files of 1 MB or larger (GitLab Docs, which demonstrates both on its www-gitlab-com repository).
- GitHub.com supports blobless and treeless filters (GitHub Blog)
- Commands such as
git checkoutandgit blamedownload missing blobs when they run - No network means no blobs
Blobless keeps every commit and tree, which is why it suits ongoing development better than a shallow clone.
Sparse checkout
- Clone with
git clone --filter=blob:none --sparse <url>. - Choose the directories with
git sparse-checkout set data --cone.
That pair comes straight from the GitLab documentation, and the --filter half matters. Sparse checkout alone only fills the working tree, so the download stays full size.
Bare and mirror clones
A bare repository has no working tree, so nobody edits files in it.
--mirror implies --bare and also maps every ref, including remote-tracking branches and notes, which makes it the right option for a full backup copy (git-clone manual).
How to clone a repository with submodules and Git LFS files
Add --recurse-submodules and Git clones the parent repository and its submodules in one command. Git LFS files need the LFS extension installed before the clone, or the working tree fills up with pointer files.
Clone with submodules
A submodule embeds another repository at a pinned commit, and after a plain clone its folder stays empty. The flag is equivalent to running git submodule update --init --recursive right after the clone, and nested submodules come along automatically (git-clone manual, Pro Git).
git clone --recurse-submodules <url>covers the standard case- Add
--shallow-submodulesto give every submodule a depth of 1 - Add
--filterwith--also-filter-submodulesto apply a partial clone filter to them too - Forgot the flag? Run
git submodule update --init --recursiveinside the clone
The --also-filter-submodules option requires both --filter and --recurse-submodules, or Git rejects the command.
Clone repositories that use Git LFS
Git LFS keeps small pointer files in the repository and stores the large files somewhere else. Without git lfs install, a clone leaves those pointers in the working tree, and git lfs pull swaps them for the real files (Git LFS FAQ).
To skip the download, set GIT_LFS_SKIP_SMUDGE=1 before the clone and the pointers stay put. Microsoft’s vscode-docs repository stores its images in Git LFS and documents exactly this, followed by git lfs pull -I "docs/nodejs" to fetch one folder.
Windows has a limit worth knowing. Git before 2.34 can’t handle working-tree files over 4 GiB through smudge and clean filters such as Git LFS (Git LFS FAQ). Update Git, or skip the smudge step and run git lfs pull afterwards.
Why does git clone fail, and how do you fix it?
A failed clone usually traces back to a wrong credential, a missing SSH key, a wrong or inaccessible URL, a target folder that isn’t empty, or a default branch that was deleted on the remote.
| Error message | Usual cause | Fix |
|---|---|---|
| Authentication failed | Account password used, or outdated cached credentials | Use a token, then clear the stale cache entry |
| Permission denied (publickey) | No key loaded, key not on the account, or wrong SSH user | Test with ssh -T git@github.com, then add the key |
| Repository not found | Typo in the URL, or no access to a private repository | Copy the URL from the repository page, check permissions |
| Destination path already exists and is not an empty directory | Target folder already holds files | Pick another folder name or empty the folder |
| Remote HEAD refers to nonexistent ref | Default branch deleted on the remote | A repository admin sets a new default branch |
Cached incorrect or outdated entries in Windows Credential Manager make Git fail against GitHub. Deleting the GitHub entry there forces a fresh prompt (GitHub Docs).
GitHub requires every SSH connection, remote URLs included, to use the “git” user, so a URL built with your own username fails. When the test passes but the clone doesn’t, ssh-add -l shows whether the agent holds a key at all.
“Repository not found” is one message for two situations, a repository that doesn’t exist and a private one you can’t see. Check the spelling first, then the access rights, then the SSH test.
Git Clone FAQ
What is the difference between a clone and a fork?
A clone is a local copy on your computer. A fork is a copy of the repository under your own account on the hosting platform, such as GitHub.
Contributors usually fork first, then clone the fork.
Is git clone the same as git pull?
No. Git clone creates a new local repository once, while git pull updates an existing one by fetching new commits and merging them into the current branch.
How does git clone differ from git init?
Git init starts an empty repository in a local folder, with no history and no remote. Git clone copies an existing repository, history included, and sets up the origin remote for you.
Is downloading a ZIP file the same as cloning?
No. GitHub’s ZIP download delivers a snapshot of the files at one branch, tag, or commit, not the entire history, so it carries no .git directory and no remote to fetch from later.
Can you change the remote URL after cloning?
Yes. Run git remote set-url origin <new-url>, then confirm the change with git remote -v.
This switches an existing clone between HTTPS and SSH without cloning again.
How do you turn a shallow clone into a full clone?
Run git fetch --unshallow inside the clone to download the missing history. To add only part of it, git fetch --deepen=<n> extends the history by that many commits.
Does git clone work the same on Windows, macOS and Linux?
Yes. The command and its flags are identical, because Git defines them, not the operating system.
Only the terminal differs. Git Bash or PowerShell on Windows, Terminal on macOS, any shell on Linux.
Keeping a New Clone in Sync With Its Remote
A fresh clone stays safe to edit if you do a few things in a set order. Identity first, then a branch, then a fetch. Each step removes a problem the next one would otherwise inherit.
- Set
user.nameanduser.email - Branch off before the first edit
- Fetch, inspect, then merge
Commits record the name and email stored in git config, so a missing identity stamps your first commits with the wrong author.
A working branch keeps the default branch identical to the remote, so later updates apply to it without conflicts.
Fetching comes before pulling because git fetch only moves the remote-tracking branches, while git pull adds a merge into the current branch (git-clone manual). The price is one extra command per update, in return for seeing incoming commits before they touch your files.
- Notepad++ Android Options: Apps That Come Close - October 21, 2026
- Data Management Services: A Practical Guide for Growing Companies - October 21, 2026
- MongoDB Cheat Sheet - October 20, 2026




