Though Git is distributed and every clone essentially is a backup, there are some tricks that can be useful when backing up Git repositories. A normal Git repository has a working copy of the files it tracks and the full history of the repository in the .git
folder of that repository. The repositories on the server, the one you push to and pull from, will usually be bare
repositories. A bare
repository is a repository without a working copy. Roughly, it is just the .git
folder of a normal repository. A mirror
repository is almost the same as a bare
repository, except it fetches all the references under refs/*
, where a bare only fetches the references that fall under refs/heads/*
. We'll now take a closer look at a normal, a bare
, and a mirror
clone of the Jgit repository.
We'll start by creating three clones of the Jgit repository, a normal, a bare, and a mirror clone. When we create the first clone, we can use that as a reference repository for the other clones. In this way, we can share the objects in the database, and we don't have to transfer the same data three times:
$ git clone https://git.eclipse.org/r/jgit/jgit $ git clone --reference jgit --bare https://git.eclipse.org/r/jgit/jgit $ git clone --mirror --reference jgit https://git.eclipse.org/r/jgit/jgit jgit.mirror
git
branch as follows:$ cd jgit $ git branch * master $ cd ../jgit.git # or cd ../jgit.mirror $ git branch * master stable-0.10 stable-0.11 stable-0.12 ...
bare
and mirror
repositories, we need to list the different refspecs
fetch and the different refs
namespaces. List the fetch refspec
for origin
in the mirror repository (jgit.mirror
):$ git config remote.origin.fetch +refs/*:refs/*
refs
namespaces in the mirror repository:$ git show-ref | cut -f2 -d " " | cut -f1,2 -d / | sort -u refs/cache-automerge refs/changes refs/heads refs/meta refs/notes refs/tags
refspec
fetch in the configuration for origin
in the bare
repository (jgit.git
). When no configuration entry is found, Git uses the default refspec
fetch, as it does in a normal repository. We can check the remote URL of origin
using the following command:$ git config remote.origin.url https://git.eclipse.org/r/jgit/jgit
refs
namespaces in the bare
repository using the following command:$ git show-ref | cut -f2 -d " " | cut -f1,2 -d / | sort -u refs/heads refs/tags
refspec
fetch and refs
namespaces for the normal repository (jgit
):$ git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/* $ git show-ref | cut -f2 -d " " | cut -f1,2 -d / | sort -u refs/heads refs/remotes refs/tags
refs- cache-automerge
, changes
, meta
, and notes
. The normal repository is the only one that has the refs/remote
namespace.The normal and bare repositories are pretty similar, only the mirror sticks out. This is due to the refspec
fetch on the mirror repository, +refs/*:refs/*
, which will fetch all refs from the remote and not just refs/heads/*
and refs/tags/*
as a normal repository (and bare) does. The many different ref namespaces on the Jgit repository is because the Jgit repository is managed by Gerrit Code Review that uses different namespaces for some repository specific content, such as changes
branches for all commits submitted for code review, metadata on code review score, and so on.
The mirror
repositories are good to know when you would like a quick way to back up a Git repository, and make sure you have everything included without needing more access than the Git access to the machine that hosts the Git repository.
The repositories on GitHub store extra information in some refs
namespaces. If a repository has had a pull request made, the pull request will be recorded in the refs/pull/*
namespace. Let's look at it in the following code:
$ git clone --mirror [email protected]:jenkinsci/extreme-feedback-plugin.git $ cd extreme-feedback-plugin.git $ git show-ref | cut -f2 -d " " | cut -f1,2 -d / | sort -u refs/heads refs/meta refs/pull refs/tags