Read Anthropic’s case study about Graphite Reviewer

Git clone bare and git clone mirror

Greg Foster
Greg Foster
Graphite software engineer


Note

This guide explains this concept in vanilla Git. For Graphite documentation, see our CLI docs.


Cloning a repository in Git can be done in several ways, depending on your specific needs for the repository's structure and content. This guide will delve into the differences and uses of git clone --bare and git clone --mirror, including how, and when to use each option.

A "bare" clone is essentially a copy of the Git repository's data files, without a working directory. This means it contains no editable working files (the files are not checked out and not available locally), but includes all of the Git database meta-files found in .git directory.

Join 20,000+ developers at top companies
Stop wrestling with Git commands
The Graphite CLI takes all the pain out of Git, allowing you to ship faster and stop googling Git commands.
main
diff1
diff2

Bare repositories are useful as server-side implementations of repositories for administrative management. These repositories aren't intended for local development and are instead used in automated scripts and deployment workflows where there is no need for a working copy of the source code. Every repo hosted on GitHub's servers for example is considered a "bare" repository. When you clone a repo from GitHub onto your local machine, with all of the code files, the repo you have locally is no longer "bare" as it contains a working directory.

To clone a repository as a bare repository, use the git clone --bare command:

Terminal
git clone --bare <repository-url>

This creates a bare repository in a directory named <repository-name>.git on the machine you are currently using. For example:

Terminal
git clone --bare https://github.com/exampleuser/old-repository.git

Remember that the repository created with the git clone --bare command will not contain a working directory, and will not include any of the code files in the repository.

In bare repositories, configuration settings can be adjusted using git config as usual, though it's important to remember that these settings only apply to repository maintenance tasks and not to development work, as there is no working directory.

Some examples of useful configurations in a bare repo are:

  1. Core settings

    • core.sharedRepository: This setting is useful in a team environment where multiple users are pushing to the repository. It can be set to a value like group or 0664 to adjust file permissions, ensuring that all users who are part of the repository's group can write to it.
  2. Remote settings

    • remote.<remote-name>.url: This setting defines the URL of a remote repository. In a bare repository, setting up remotes can facilitate syncing changes across multiple repository mirrors or backup locations.
  3. Branch management

    • branch.<branch-name>.merge: Specifies the default merge behavior for a specific branch, which is essential when the repository serves as the source for integration or release branches.
    • branch.<branch-name>.remote: Points to the default remote repository for a particular branch, useful for defining primary upstream locations for branch updates.
  4. Garbage collection

    • gc.auto: Adjusts when Git performs automatic garbage collection, cleaning up unnecessary files and optimizing the repository. This can be crucial for maintaining performance and reducing disk space in frequently updated repositories.
  5. Receive settings

    • receive.denyNonFastForwards: This setting can prevent users from pushing changes that would require a forced update of the branch on the server, which can help maintain linear history in critical branches.
    • receive.denyDeletes: When set, this prevents users from deleting branches or tags through push, which can be crucial for preserving important historical references in the repository.

Using git config to adjust these settings in a bare repository can greatly impact how effectively the repository functions as a collaboration tool, ensuring that operational standards are maintained and that the repository remains efficient and secure.

Join 20,000+ developers at top companies
The best engineers use Graphite to simplify Git
Engineers at Vercel, Snowflake & The Browser Company are shipping faster and staying unblocked with Graphite.
main
diff1
diff2

A mirror clone is a step beyond a bare clone. It mirrors the entire repository, including all refs (branches, tags, and remotes) and settings like hooks and configuration files. A mirrored clone differs from a regular clone in that, the mirror is configured to overwrite all of its local reference every time git fetch is run. This ensures the mirror will always be the exact same as the original repository.

Creating a mirror clone is straightforward with the following command:

Terminal
git clone --mirror <repository-url>

This command will create a complete mirror of the source repository, typically used for backing up a repository or migrating to a new server. For instance:

Terminal
git clone --mirror https://github.com/exampleuser/old-repository.git

After executing a mirror clone command, the entire structure and history of the original repository, including all branches and tags, are replicated locally. This is particularly useful for creating backups or read-only mirrors of the repository for archival purposes.

Once the mirror repository has been copied to a new machine, other users can then fetch and pull the references from the repository source that contains all the actual copies of the code.

While both commands create clones without a working directory, there are two main differences: completeness and purpose.

  • Bare clone: Suitable for developers who need a repository on a server for sharing changes but don't require local editing capabilities.
  • Mirror clone: Intended for full replication of the repository, including all Git data, making it ideal for backup or complete repository migration.

You can clone a repository to a new directory name using:

Terminal
git clone <repository-url> <new-name>

This works with both bare and mirror clones:

Terminal
git clone --bare <repository-url> <new-name>.git
git clone --mirror <repository-url> <new-name>.git

If you need to clone into a directory that already contains an unrelated project or data, Git will prevent you by default. To force the clone, you would typically need to remove or rename the existing directory first, as Git does not provide a direct overwrite option to prevent accidental data loss.

  1. Use bare clones for server-side repositories where developers push and pull changes but do not directly edit files.
  2. Use mirror clones for exact replicas of a repository, especially for creating backups or transitioning to a new server.
  3. Regularly update mirrored clones if they serve as backups to ensure they reflect the most current state of your project.

For further reading on cloning in Git, see the official Git documentation.

Graphite
Git stacked on GitHub

Stacked pull requests are easier to read, easier to write, and easier to manage.
Teams that stack ship better software, faster.

Or install our CLI.
Product Screenshot 1
Product Screenshot 2