git clone <url> [dir] does four things in one shot:
git initin the target directory (defaults to the repo name).- Adds a remote named
originwith the clone URL. git fetch origindownloads all objects and refs.- Checks out the default branch (usually
main, sometimesmaster).
After that you have a full working repository: git log, git status, git switch. The entire project history is there,
transparent to you.
URL formats
git clone https://github.com/foo/bar.git # HTTPS
git clone git@github.com:foo/bar.git # SSH
git clone ssh://user@host/path/to/repo.git # SSH with port
git clone /path/to/local/repo # local
HTTPS requires a login or token on push (or a credential helper to cache it). SSH requires ssh-keys-git but never prompts for a password after setup. Many teams use SSH for exactly that reason.
Useful flags
git clone --depth 1 <url> # shallow: last commit only
git clone --branch dev <url> # check out branch dev instead of main
git clone --filter=blob:none <url> # partial: skip blob objects until checkout
git clone --bare <url> # no working tree, just .git
git clone --recursive <url> # include submodules (see chapter 13)
--depth 1 saves bandwidth and disk space on large repositories. The
cost: you lose old history (git log goes back only to the shallow
boundary). Modern Git allows pushing from a shallow clone, but
operations that depend on the full history (merging old branches,
bisecting far back) will stumble. Suitable for CI where you only
need the current state.
What does not clone
- The
.git/configof the source (a fresh one is created on the clone). - Local branches in the source that were never pushed to that URL.
- Hooks from
.git/hooks/(they are local to each clone). - The stash of the source.
What does clone: all commits, all branches, all tags (by default), the full history.
Pitfalls
- Cloning over HTTPS without a credential helper will ask for a
password on every push. Fix:
git config --global credential.helper(macOS:osxkeychain, Linux:cache, Windows:manager-core). - The default remote name is
origin. You can set a different one immediately withgit clone -o upstream <url>, or rename it later:git remote rename origin upstream. git clonefetches the entire history, which can be gigabytes. For very large repositories, look at--filter=blob:none(partial clone) or--depth(shallow clone).