How-to

git clone: How to Clone a Repository from GitHub and Beyond

Updated: · Skillaria.Top

git clone downloads an entire remote repository, including all files, full commit history and branches, and creates a local copy with the origin remote already set up. Basic usage: git clone repository-url. Flags let you pick the folder or branch, or fetch only the latest commits with --depth 1.

The git clone command creates a complete local copy of a remote repository: files, full commit history, branches and tags. It's the standard way to start working on a project that already lives on GitHub, GitLab or a company server. Unlike downloading a ZIP archive, a clone is a fully functional repository where you can commit and push changes back.

Basic git clone usage

Copy the repository URL (on GitHub, the green "Code" button) and run:

git clone https://github.com/username/project.git
Cloning into 'project'...
remote: Enumerating objects: 1532, done.
remote: Counting objects: 100% (1532/1532), done.
remote: Compressing objects: 100% (812/812), done.
Receiving objects: 100% (1532/1532), 2.41 MiB | 6.10 MiB/s, done.
Resolving deltas: 100% (701/701), done.

Git creates a project folder in the current directory (the name comes from the URL minus .git). Then step into it:

cd project
git status

What git clone does under the hood

Cloning is more than downloading files. Knowing the steps explains why everything "just works" after a clone and where the branches prefixed with origin/ come from. Step by step, the command:

  1. creates a folder and runs the equivalent of git init in it;
  2. adds a remote named origin pointing to the source URL;
  3. downloads all objects and refs, the equivalent of git fetch;
  4. creates remote-tracking branches origin/main, origin/develop and so on;
  5. creates the default local branch (usually main), sets it to track origin/main and checks out the files.

That's why you don't need to configure git remote manually after cloning: git push and git pull work right away.

git remote -v
origin  https://github.com/username/project.git (fetch)
origin  https://github.com/username/project.git (push)

Cloning over HTTPS vs SSH

HTTPSSSH
URLhttps://github.com/user/repo.gitgit@github.com:user/repo.git
Public repositoryClones without authenticationRequires an SSH key added to your account
Private repository, pushRequires a Personal Access Token instead of a passwordWorks with your key, no password prompts
Corporate networksPort 443 is almost always openPort 22 is sometimes blocked

For reading other people's public projects, HTTPS is enough. For your own repositories that you push to regularly, SSH is more convenient:

git clone git@github.com:username/project.git

If you already cloned over HTTPS and want to switch to SSH, there's no need to clone again:

git remote set-url origin git@github.com:username/project.git

How to clone into a specific folder

The second argument is the name or path of the target directory:

# Into a folder with a different name
git clone https://github.com/username/project.git my-copy

# Into the current folder (it must be empty)
git clone https://github.com/username/project.git .

If the target folder exists and isn't empty, Git refuses: fatal: destination path 'project' already exists and is not an empty directory.

How to clone a specific branch

By default, after cloning you're on the remote repository's default branch. To land on a different one straight away, use -b (--branch):

git clone -b develop https://github.com/username/project.git

Note that this still downloads all branches; you just end up on develop. If you want only that one branch and nothing else, add --single-branch:

git clone -b develop --single-branch https://github.com/username/project.git

The -b flag also accepts a tag name, giving you the project as of that release (in detached HEAD state):

git clone -b v2.1.0 --depth 1 https://github.com/username/project.git

Where are the other branches after cloning?

Beginners are often surprised that git branch shows only main. The other branches were downloaded as remote-tracking branches, and you can see them like this:

git branch -a
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/develop
  remotes/origin/feature/login

To start working on one of them, just switch to it by its short name, and Git creates a local branch that tracks the remote one:

git switch develop

Shallow clone: --depth for large repositories

In older projects the history can weigh gigabytes. If you need only the current code, say in CI or just to build the project, download only the latest commits:

git clone --depth 1 https://github.com/username/big-project.git

The --depth flag implies --single-branch, so you get only the default branch and a single commit. If you need the full history later, you can fetch the rest:

git fetch --unshallow

You can set a different depth, such as --depth 50, or limit history by date with --shallow-since=2025-01-01. For active development a shallow clone is inconvenient: git log, git blame and history searches will be incomplete.

Partial clone: --filter

An alternative for huge monorepos is to download the commit history but fetch file contents on demand:

git clone --filter=blob:none https://github.com/username/monorepo.git

This keeps the full history for log and switching branches while saving bandwidth and disk space. It requires server support; GitHub and GitLab both support it.

Mirror clone and migrating a repository

A regular clone stores branches as remote-tracking branches and doesn't copy the server's internal refs. To move a project to another host or make an exact backup, use --mirror:

git clone --mirror https://github.com/username/project.git
cd project.git
git push --mirror git@gitlab.com:username/project.git

A mirror is a bare repository with no working files, where all branches and tags are stored as local refs. git push --mirror sends all of them to the new server, so the history moves over intact. Note that issues, pull requests and hosting settings don't come along this way; those are the service's data, not Git's.

The similar --bare flag also creates a repository without a working directory, but copies only branches and tags. It's a good fit for setting up a central repository on your own server from an existing project.

Cloning with submodules

If the project uses git submodules, their folders will be empty by default. To download everything at once:

git clone --recurse-submodules https://github.com/username/project.git

If you already cloned without the flag, fetch the submodules afterwards:

git submodule update --init --recursive

git clone vs fork vs downloading a ZIP

MethodWhat you getWhen to use it
git cloneA full repository with history and a remoteWorking on a project you have access to, or when you need the history
Fork on GitHubA copy of the repository under your account on the serverContributing to someone else's project via a pull request
Download ZIPJust the files, no .gitA quick look at the code with no plans to commit

Fork and clone don't compete: in open source you fork on the website first, then clone your fork and add the original as a second remote:

git clone git@github.com:me/project.git
cd project
git remote add upstream https://github.com/author/project.git
git fetch upstream

Common git clone errors

"Repository not found"

Either there's a typo in the URL or the repository is private and you don't have access. For private repositories GitHub deliberately responds with "not found" rather than "access denied". Check the URL and make sure you're signed in with the right account.

"Permission denied (publickey)"

You're cloning over SSH but your key isn't set up. Test with ssh -T git@github.com, add your public key in your account settings, or clone over HTTPS for now.

"Authentication failed" over HTTPS

You entered your account password. GitHub has long required a Personal Access Token instead of a password for Git operations over HTTPS. If Git cached the wrong credentials, remove them from your system's credential manager.

Clone fails on a large repository

Errors like early EOF or RPC failed are often caused by an unstable connection combined with repository size. A shallow clone with --depth 1 followed by git fetch --unshallow, or cloning over SSH, usually helps.

Line ending issues on Windows

After cloning, every file shows up as "modified": that's CRLF/LF conversion at work. Set git config --global core.autocrlf true on Windows (or input on Linux and macOS), and preferably define rules in the project's .gitattributes.

What to do right after cloning

The clone is ready, but before changing any code it's worth spending a couple of minutes on setup. It saves you from the usual problems on your first day with someone else's project.

  1. Read the README and CONTRIBUTING. They usually explain how to install dependencies, run tests, and how branches are named in the project.
  2. Check your branch and status. git status and git log --oneline -5 show where you are and what the latest changes are.
  3. Create your own branch. Don't work directly on main: git switch -c feature/my-task.
  4. Check your commit author. If you have several accounts on one machine (personal and work), set the email for this repository only, without --global: git config user.email "you@company.com".
  5. Install dependencies. Folders like node_modules or venv aren't committed; you create them locally with npm install, pip install -r requirements.txt and so on.

How to keep your clone up to date

You clone only once. After that, your teammates' new commits come from the same origin:

# See what's new on the server without changing anything
git fetch
git log --oneline main..origin/main

# Merge the changes into the current branch
git pull

Getting into the habit of running git fetch first and looking at what came in saves you from surprise conflicts. There's no need to re-clone a project "to update it": doing so loses your local branches and uncommitted work.

git clone cheat sheet

TaskCommand
Regular clonegit clone <url>
Into your own foldergit clone <url> <folder>
Land on a specific branchgit clone -b <branch> <url>
Only one branchgit clone -b <branch> --single-branch <url>
Without historygit clone --depth 1 <url>
Without old file contentsgit clone --filter=blob:none <url>
With submodulesgit clone --recurse-submodules <url>
Bare copy for a servergit clone --bare <url>

Summary

git clone downloads the whole repository and immediately links it to the server via origin, so you can commit, push and pull with no extra setup. Use SSH for your own projects, --depth or --filter for large ones, and -b for a specific branch. Working with remote repositories, push, pull and fetch are covered hands-on in the Git course.

FAQ

What's the difference between git clone and git pull?

git clone runs once and creates a new local copy of the repository. git pull runs inside an existing clone and brings in new changes from the server.

Can I clone just one folder from a repository?

Not directly. The closest option is a partial clone with --filter=blob:none --sparse followed by git sparse-checkout set path, so only the folder you need appears in the working directory.

How much disk space does a clone take?

Roughly the size of the full compressed history plus the checked-out files of the current version. You can check the repository size with git count-objects -vH.

Can I clone a local repository?

Yes, pass a path instead of a URL: git clone /path/to/repo copy. It's handy for experiments so you don't risk your main copy.

Do I need to run git init before git clone?

No. git clone creates the folder and initializes the repository in it for you.

Learn this topic on video

This topic is covered in depth with practice in the course “Git from Scratch to Confident Developer”.

Go to course