What's the difference between git clone --mirror and git clone --bare

Viewed 403415

The git clone help page has this to say about --mirror:

Set up a mirror of the remote repository. This implies --bare.

But doesn't go into detail about how the --mirror clone is different from a --bare clone.

8 Answers
$ git clone --bare https://github.com/example

This command will make the new "example" directory itself the $GIT_DIR (instead of example/.git). Also the branch heads at the remote are copied directly to corresponding local branch heads, without mapping. When this option is used, neither remote-tracking branches nor the related configuration variables are created.

$ git clone --mirror https://github.com/example

As with a bare clone, a mirrored clone includes all remote branches and tags, but all local references (including remote-tracking branches, notes etc.) will be overwritten each time you fetch, so it will always be the same as the original repository.

Unlike git clone, git clone --mirror and git clone --bare both are bare repos. The difference between them are in the config file.

git clone's config file looks like:

[remote "origin"]
    url = https://github.com/example
    fetch = +refs/heads/*:refs/remotes/origin/*

git clone --bare's config file looks like:

[remote "origin"]
    url = https://github.com/example

git clone --mirror's config file looks like:

[remote "origin"]
    url = https://github.com/example
    fetch = +refs/*:refs/*
    mirror = true

So, we see that the main difference in in the refspec to be used for fetching

The format of the refspec is, first, an optional +, followed by <src>:<dst>, where <src> is the pattern for references on the remote side and <dst> is where those references will be tracked locally. The + tells Git to update the reference even if it isn’t a fast-forward.

In case of git clone that is automatically written by a git remote add origin command, Git fetches all the references under refs/heads/ on the server and writes them to refs/remotes/origin/ locally.

In case of git clone --bare, there is no refspec to be used for fetching.

In case of git clone --mirror, the refspec to be used for fetching looks like fetch = +refs/*:refs/*. It means, tags, remotes, replace (which is under refs directory) along with heads will be fetched as well. Note that, by default git clone only fetch heads.

NOTE 1: git clone --mirror and git clone --bare --mirror are equivalent.

NOTE 2: there is also difference in packed-refs. As it records the same information as refs/heads/, refs/tags/, and friends record in a more efficient way.

Related