GIT-CLONE(1)
๐
git-clone(1) โ straight up out of the Git Manual ๐
okay so bestie, you know how everyone's always like "just clone the repo" โ this is the page that tells you literally everything that command can do. it's giving main character energy, it's giving wow that's a lot of flags, and honestly? we're gonna get through it together ๐ซถ
โจ NAME โจ
git-clone โ Clone a repository into a new directory ๐
๐ SYNOPSIS ๐
git clone [--template=<template-directory>]
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
[-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
[--dissociate] [--separate-git-dir <git-dir>]
[--depth <depth>] [--[no-]single-branch] [--[no-]tags]
[--recurse-submodules[=<pathspec>]] [--[no-]shallow-submodules]
[--[no-]remote-submodules] [--jobs <n>] [--sparse] [--[no-]reject-shallow]
[--filter=<filter-spec> [--also-filter-submodules]] [--] <repository>
[<directory>]
like, yes, that's the whole vibe up there. no cap, that's the real synopsis, don't @ me ๐
๐ DESCRIPTION ๐
So what does it actually do? Bestie. It clones a repository into a newly created directory โ like, it makes you a whole fresh baby copy ๐ โ and then it:
- creates remote-tracking branches for each branch in the cloned repository (you can peek at them with
git branch --remotes๐) - creates and checks out an initial branch that is forked from the cloned repository's currently active branch
Basically it sets you up so you're already on the branch the repo had going, and all the other branches are chilling in the background waiting for you. Iconic behavior, honestly ๐
Then, after the clone is done โ and this is the part that ate โ a plain git fetch with no arguments will update all the remote-tracking branches, and a plain git pull with no arguments will in addition merge the remote master branch into the current master branch, if any. (โ ๏ธ heads up: this is untrue when --single-branch is given โ see below, iykyk.)
And how does it pull off this default config? By creating references to the remote branch heads under refs/remotes/origin and by initializing the remote.origin.url and remote.origin.fetch configuration variables. That's the whole magic trick โจ
๐ฆ OPTIONS ๐ฆ
okay this is the long part, hydrate first ๐ง
-l,--localโ When the repository you're cloning from is on a local machine, this flag bypasses the normal "Git aware" transport mechanism and just clones the repository by making a copy of HEAD and everything under theobjectsandrefsdirectories. The files under the.git/objects/directory get hardlinked to save space when possible ๐
If the repository is specified as a local path (e.g., /path/to/repo), this is the default, and --local is essentially a no-op. If the repository is specified as a URL, then this flag is ignored (and we never use the local optimizations, periodt). Specifying --no-local will override the default when /path/to/repo is given, using the regular Git transport instead.
If the repository's $GIT_DIR/objects has symbolic links or is a symbolic link, the clone will fail. This is a security measure to prevent the unintentional copying of files by dereferencing the symbolic links ๐
This option does not work with repositories owned by other users for security reasons, and --no-local must be specified for the clone to succeed.
NOTE: this operation can race with concurrent modification to the source repository, similar to runningcp -r <src> <dst>while modifying<src>. ๐ so like, don't be doing that
--no-hardlinksโ Force the cloning process from a repository on a local filesystem to copy the files under the.git/objectsdirectory instead of using hardlinks. This may be desirable if you're trying to make a back-up of your repository ๐ธ like, fair.-s,--sharedโ When the repository you're cloning is on the local machine, instead of using hard links, automatically setup.git/objects/info/alternatesto share the objects with the source repository. The resulting repository starts out without any object of its own. ๐ซถ
Note: this is a possibly dangerous operation โ do not use it unless you understand what it does. If you clone your repository using this option and then delete branches (or use any other Git command that makes any existing commit unreferenced) in the source repository, some objects may become unreferenced (or dangling). These objects may be removed by normal Git operations (such asgit commit) which automatically callgit maintenance run --auto. (Seegit-maintenance(1).) If these objects are removed and were referenced by the cloned repository, then the cloned repository will become corrupt. ๐ญ like genuinely, be careful.
Note that running git repack without the --local option in a repository cloned with --shared will copy objects from the source repository into a pack in the cloned repository, removing the disk space savings of clone --shared. It is safe, however, to run git gc, which uses the --local option by default โ
If you want to break the dependency of a repository cloned with --shared on its source repository, you can simply run git repack -a to copy all objects from the source repository into a pack in the cloned repository. freedom ๐
--reference=<repository>,--reference-if-able=<repository>โ If the reference<repository>is on the local machine, automatically setup.git/objects/info/alternatesto obtain objects from the reference<repository>. Using an already existing repository as an alternate will require fewer objects to be copied from the repository being cloned, reducing network and local storage costs ๐ When using the--reference-if-able, a non existing directory is skipped with a warning instead of aborting the clone.
Note: see the NOTE for the--sharedoption, and also the--dissociateoption. ๐
--dissociateโ Borrow the objects from reference repositories specified with the--referenceoptions only to reduce network transfer, and stop borrowing from them after a clone is made by making necessary local copies of borrowed objects. This option can also be used when cloning locally from a repository that already borrows objects from another repository โ the new repository will borrow objects from the same repository, and this option can be used to stop the borrowing. cute, clean break ๐ฆ-q,--quietโ Operate quietly ๐คซ Progress is not reported to the standard error stream.-v,--verboseโ Run verbosely ๐ฃ๏ธ Does not affect the reporting of progress status to the standard error stream. (like, it's chatty but not that chatty)--progressโ Report progress status on the standard error stream by default when attached to a terminal, unless--quietis specified. This flag forces progress status even if the standard error stream is not directed to a terminal โจ--server-option=<option>โ Transmit the given string to the server when communicating using protocol version 2. The given string must not contain a NUL or LF character โ ๏ธ The server's handling of server options, including unknown ones, is server-specific. When multiple--server-option=<option>are given, they are all sent to the other side in the order listed on the command line. When no--server-option=<option>is given from the command line, the values of configuration variableremote.<name>.serverOptionare used instead ๐-n,--no-checkoutโ Do not checkout HEAD after the clone is complete. that's it, that's the whole thing ๐--no-reject-shallow,--reject-shallowโ Fail if the source repository is a shallow repository. Theclone.rejectShallowconfiguration variable can be used to specify the default ๐--bareโ Make a bare Git repository. That is, instead of creating<directory>and placing the administrative files in<directory>/.git, make the<directory>itself the$GIT_DIR. This obviously implies the--no-checkoutbecause there is nowhere to check out the working tree ๐ญ Also the branch heads at the remote are copied directly to corresponding local branch heads, without mapping them torefs/remotes/origin/. When this option is used, neither remote-tracking branches nor the related configuration variables are created โญ--sparseโ Employ a sparse-checkout, with only files in the toplevel directory initially being present. Thegit-sparse-checkout(1)command can be used to grow the working directory as needed ๐ฑ--filter=<filter-spec>โ Use the partial clone feature and request that the server sends a subset of reachable objects according to a given object filter. When using--filter, the supplied<filter-spec>is used for the partial clone filter ๐
If --filter=auto is used the filter specification is determined automatically through the promisor-remote protocol (see gitprotocol-v2(5)) by combining the filter specifications advertised by the server for the promisor remotes that the client accepts (see the promisor.acceptFromServer configuration option in git-config(1)). This allows the server to suggest the optimal filter for the available promisor remotes ๐
As with other filter specifications, the "auto" value is persisted in the configuration. This ensures that future fetches will continue to adapt to the server's current recommendation ๐ฅ
For details on all other available filter specifications, see the --filter=<filter-spec> option in git-rev-list(1).
For example, --filter=blob:none will filter out all blobs (file contents) until needed by Git. Also, --filter=blob:limit=<size> will filter out all blobs of size at least <size> ๐
--also-filter-submodulesโ Also apply the partial clone filter to any submodules in the repository. Requires--filterand--recurse-submodules. This can be turned on by default by setting theclone.filterSubmodulesconfig option ๐ฆ--mirrorโ Set up a mirror of the source repository. This implies--bare. Compared to--bare,--mirrornot only maps local branches of the source to local branches of the target, it maps all refs (including remote-tracking branches, notes etc.) and sets up a refspec configuration such that all these refs are overwritten by agit remote updatein the target repository ๐ช like, a real mirror. no cap.-o<name>,--origin=<name>โ Instead of using the remote nameoriginto keep track of the upstream repository, use<name>. Overridesclone.defaultRemoteNamefrom the config โจ-b<name>,--branch=<name>โ Point the newly created HEAD to<name>branch instead of the branch pointed to by the cloned repository's HEAD. In a non-bare repository, this is the branch that will be checked out.--branchcan also take tags and detaches the HEAD at that commit in the resulting repository ๐ฏ--revision=<rev>โ Create a new repository, and fetch the history leading to the given revision<rev>(and nothing else), without making any remote-tracking branch, and without making any local branch, and detach HEAD to<rev>. The argument can be a ref name (e.g.refs/heads/mainorrefs/tags/v1.0) that peels down to a commit, or a hexadecimal object name. This option is incompatible with--branchand--mirrorโ ๏ธ pick a lane bestie
~ okay we are literally not even done yet, the options keep going, so stay with me ๐ ~
-u<upload-pack>,--upload-pack=<upload-pack>โ when you're pulling from a repo over ssh, this lets you point at a different path for the command that runs on the other end. Not the default one? Say it here. ๐--template=<template-directory>โ tells git which directory to steal its templates from (peep the "TEMPLATE DIRECTORY" section ofgit-init(1)for the tea ๐ซ).-c<key>=<value>,--config=<key>=<value>โ sets a config variable in the brand-new repo you just made. It kicks in immediately after the repo is initialized, but before the remote history gets fetched or any files get checked out. The<key>is in the same formatgit-config(1)expects (like,core.eol=true). Give the same key multiple times and every value gets written to the config file โ which is lowkey iconic, because it means it's totally safe to, say, add extra fetch refspecs to theoriginremote. โจ
Heads up bestie: because of limitations in the current implementation, some config variables just won't take effect until after the initial fetch and checkout. The ones known to be like this are:remote.<name>.mirrorandremote.<name>.tagOpt. So use the matching--mirrorand--no-tagsoptions instead, mkay? ๐
--depth=<depth>โ makes a shallow clone, with the history chopped down to the number of commits you give it. This implies--single-branchunless you also throw in--no-single-branch(which fetches histories near the tips of all the branches). Wanna shallow-clone submodules too? Also pass--shallow-submodules.--shallow-since=<date>โ shallow clone, but the history starts after the time you specify. โฐ--shallow-exclude=<ref>โ shallow clone, except history excludes commits reachable from a specific remote branch or tag. You can pass this multiple times, bestie. ๐--single-branch,--no-single-branchโ clones only the history leading to the tip of a single branch โ either the one you named with--branch, or whatever the primary branch's remoteHEADpoints at. Any future fetches into that repo will only update the remote-tracking branch for the branch you used this option on at clone time. And if the remoteHEADwasn't pointing at any branch when you did the--single-branchclone? Then boom, no remote-tracking branch gets created. ๐--tags,--no-tagsโ controls whether tags get cloned or not. When you give--no-tags, it becomes permanent by setting theremote.<remote>.tagOpt=--no-tagsconfig. That guarantees futuregit pullandgit fetchwon't follow any tags. (Subsequent explicit tag fetches still work fine โ seegit-fetch(1).) By default tags are cloned, so passing--tagsis usually a no-op, unless it's cancelling out an earlier--no-tags. You can pair it with--single-branchto clone and maintain a branch with no references other than that single cloned branch โ which is genuinely useful, like for maintaining minimal clones of some repo's default branch for search indexing. ๐ฅ--recurse-submodules[=<pathspec>]โ once the clone is created, initialize and clone the submodules inside it based on the<pathspec>you give. No=<pathspec>? Then all submodules get initialized and cloned. You can give this multiple times for pathspecs with multiple entries. The resulting clone hassubmodule.activeset to your pathspec, or"."(meaning all submodules) if you didn't give one. Submodules get initialized and cloned with their default settings โ equivalent to runninggit submodule update --init --recursive <pathspec>right after the clone finishes.
This option is ignored if the repo you're cloning doesn't have a worktree/checkout โ i.e. if you passed any of--no-checkout/-n,--bare, or--mirror. ๐ซถ
--shallow-submodules,--no-shallow-submodulesโ every submodule that gets cloned will be shallow, with a depth of1.--remote-submodules,--no-remote-submodulesโ every submodule that gets cloned uses its remote-tracking branch's status to update itself, instead of the superproject's recorded SHA-1. Equivalent to passing--remotetogit submodule update. ๐--separate-git-dir=<git-dir>โ instead of putting the cloned repo where it's "supposed" to go, it places the cloned repository at the directory you specify, then makes a filesystem-agnostic Git symbolic link pointing there. Result: your Git repository can live totally separate from the working tree. Main character energy. ๐--ref-format=<ref-format>โ specifies the ref storage format for the repo. Valid values are:filesโ for loose files with packed-refs. This is the default.reftableโ for the reftable format.
-j<n>,--jobs=<n>โ how many submodules get fetched at the same time. Defaults to thesubmodule.fetchJobsoption.<repository>โ the (possibly remote)<repository>to clone from. Scroll down to the GIT URLS section for more on how to specify repositories. ๐<directory>โ the name of the new directory to clone into. If you don't explicitly give one, the "humanish" part of the source repo's name gets used (repofor/path/to/repo.git, andfooforhost.xz:foo/.git). Cloning into an existing directory is only allowed if that directory is empty. ๐จ--bundle-uri=<uri>โ before fetching from the remote, fetch a bundle from the<uri>you give and unbundle that data into the local repo. The refs from the bundle land under the hiddenrefs/bundle/*namespace.
This option is incompatible with--depth,--shallow-since, and--shallow-exclude. Pick a lane, bestie. ๐
๐ GIT URLS ๐
Okay so generally, URLs carry info about the transport protocol, the address of the remote server, and the path to the repo. Depending on which transport protocol you're on, some of that info might just not be there. Nbd. ๐ฆ
Git supports the ssh, git, http, and https protocols. (Also, ftp and ftps can be used for fetching, but it's inefficient and deprecated โ do not use them, periodt.) ๐ซ
The native transport (i.e. a git:// URL) does no authentication and should be used with caution on unsecured networks. Fr fr, be careful. ๐ญ
Here are the syntaxes you can use with them:
ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>git://<host>[:<port>]/<path-to-git-repo>http[s]://<host>[:<port>]/<path-to-git-repo>ftp[s]://<host>[:<port>]/<path-to-git-repo>
There's also an alternative scp-like syntax for the ssh protocol:
[<user>@]<host>:/<path-to-git-repo>
This one is only recognized if there are no slashes before the first colon โ which is what helps git tell it apart from a local path that happens to contain a colon. Like, the local path foo:bar could be written as an absolute path, or as ./foo:bar, to avoid being misinterpreted as an ssh URL. ๐
The ssh and git protocols additionally support ~<username> expansion:
ssh://[<user>@]<host>[:<port>]/~<user>/<path-to-git-repo>git://<host>[:<port>]/~<user>/<path-to-git-repo>[<user>@]<host>:~<user>/<path-to-git-repo>
For local repositories โ also natively supported by Git โ you can use these syntaxes:
/path/to/repo.git/file:///path/to/repo.git/
These two are mostly equivalent, except the first one implies the --local option. โจ
git clone, git fetch, and git pull โ but not git push โ will also accept a suitable bundle file. See git-bundle(1). ๐
When Git doesn't know how to handle a certain transport protocol, it tries to use the remote-<transport> remote helper, if one exists. To explicitly request a remote helper, use:
<transport>::<address>
where <address> can be a path, a server and path, or any arbitrary URL-like string that the specific remote helper being invoked recognizes. See gitremote-helpers(7) for the details. ๐ซถ
Got a ton of similarly-named remote repositories and you want a different format for them (so the URLs you type get rewritten into URLs that actually work)? Make a config section like this:
[url "<actual-url-base>"]
insteadOf = <other-url-base>
Like, with this:
[url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:
a URL like "work:repo.git" or "host.xz:/path/to/repo.git" gets rewritten โ in any context that takes a URL โ to "git://git.host.xz/repo.git". Slay. ๐ฅ
Wanna rewrite URLs for push only? Then make a config section like this:
[url "<actual-url-base>"]
pushInsteadOf = <other-url-base>
For example, with this:
[url "ssh://example.org/"]
pushInsteadOf = git://example.org/
a URL like "git://example.org/path/to/repo.git" gets rewritten to "ssh://example.org/path/to/repo.git" for pushes โ but pulls will still use the original URL. Iconic behaviour, honestly. ๐
๐ EXAMPLES ๐
- Clone from upstream:
$ git clone git://git.kernel.org/pub/scm/.../linux.git my-linux
$ cd my-linux
$ make
- Make a local clone that borrows from the current directory, without checking things out:
$ git clone -l -s -n . ../copy
$ cd ../copy
$ git show-branch
- Clone from upstream while borrowing from an existing local directory:
$ git clone --reference /git/linux.git \
git://git.kernel.org/pub/scm/.../linux.git \
my-linux
$ cd my-linux
- Create a bare repository to publish your changes to the public:
$ git clone --bare -l /home/proj/.git /pub/scm/proj.git
- Clone a local repository from a different user:
$ git clone --no-local /home/otheruser/proj.git /pub/scm/proj.git
๐ CONFIGURATION ๐
Everything below this line is selectively included from the git-config(1) docs, and the content is literally the same as whatโs found there โ just with better vibes ๐.
๐ธ init.templateDir ๐ธ
Specifies the directory from which templates get copied. (Peep the "TEMPLATE DIRECTORY" section of git-init(1) for the full lore.)
๐ธ init.defaultBranch ๐ธ
Lets you override the default branch name, like when youโre initializing a new repository.
๐ธ init.defaultObjectFormat ๐ธ
Lets you override the default object format for new repositories. See --object-format= in git-init(1). Both the command-line option and the GIT_DEFAULT_HASH environment variable take precedence over this config.
๐ธ init.defaultRefFormat ๐ธ
Lets you override the default ref storage format for new repositories. See --ref-format= in git-init(1). Both the command-line option and the GIT_DEFAULT_REF_FORMAT environment variable take precedence over this config.
๐ธ init.defaultSubmodulePathConfig ๐ธ
A boolean that specifies if git init and git clone should automatically set extensions.submodulePathConfig to true. This lets all new repositories automatically use the submodule path extension. Defaults to false when unset.
๐ธ clone.defaultRemoteName ๐ธ
The name of the remote to create when cloning a repository. Defaults to origin. It can be overridden by passing the --origin command-line option.
๐ธ clone.rejectShallow ๐ธ
Reject cloning a repository if itโs a shallow one; this can be overridden by passing the --reject-shallow option on the command line.
๐ธ clone.filterSubmodules ๐ธ
If a partial clone filter is provided (see --filter in git-rev-list(1)) and --recurse-submodules is used, also apply the filter to submodules.
๐ GIT ๐
Part of the git(1) suite โ obviously, sheโs iconic ๐
.
Thatโs the whole vibe check, bestie: source/version Git 2.56.0, date 2026-09-27, page GIT-CLONE(1) โ bye, slay your clones โจ๐ซถ
๐ฆ where this page comes from
- arch rolling: git 2.56.0-1 ยท GPL-2.0-only
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms