You saw in technique 6 how to push to remote repositories, provided by various organizations on the internet, as a way of sharing your Git repositories with others.
Sometimes, though, you may wish to host a remote Git repository on a machine you control—for example, to
Temporarily share a Git repository on your machine with another computer on the same network
Keep a full backup of an external Git repository on a server you control
Provide an internal mirror of an external Git repository to allow faster trans-fer speeds
Host a Git repository on a server entirely under your own control
I only use the commands in this chapter to view a local repository or share a local repository with computers on the same network (rather than over the internet).
Although you’ll see more advanced tools in section 11.1, this chapter focuses on
This chapter covers
Creating a repository in a format for hosting a server
Mirroring an existing repository for hosting a server
Sharing a repository with a local network
Viewing a repository in a web browser
Providing advanced Git hosting with other software
175 TECHNIQUE 63 Initializing a local repository in a server hosting format: git init --bare
understanding the features provided by Git itself and how they work, rather than more advanced Git hosting solutions. In essence, this chapter is a guide for software engineers to understand how Git repositories can be shared and not a guide for sys-tem administrators on how to set up Git servers. Unless you’re an experienced syssys-tem administrator, I’d advise using an external Git hosting provider (such as GitHub) rather than running your own Git servers.
Technique 63 Initializing a local repository in a server hosting format: git init - -bare
The Git repositories you’ve seen throughout this book have all had a similar structure:
the working directory contains a checkout of the files in the current branch and a .git subdirectory that contains the repository data. For example, if you had a GitIn-PracticeNonBare.git repo, its contents might resemble figure 11.1.
You can see that it has only the README.md file and the .git repository data subdi-rectory in the root. Git stores data in a highly space-efficient format. The checked-out files in a repository’s working directory may sometimes take
up more space than the compressed version of all files stored in the .git directory!
On a server, the working directory should never be used directly, so it’s better to not create one at all. Because you’ll be sending/receiving Git objects to/from various Git clients with git push, git fetch, and git pull, you don’t need to have the actual files checked out on disk. A Git repository without a working directory is known as a bare repository. The major difference compared to the first repository you created in technique 1 is that this repository isn’t in a .git directory.
Let’s create a bare repository and look at its contents.
Problem
You wish to create a bare Git repository.
Solution
1 Change to the directory you wish to contain your new repository directory: for example, cd /Users/mike/.
2 Run git init --bare GitInPracticeBare.git. The output should resemble the following.
# git init --bare GitInPracticeBare.git
Initialized empty Git repository in /Users/mike/GitInPracticeBare.git/
B
shows the new directory that was created for the bare Git repository.Listing 11.1 Output: initializing a bare repository
B
Figure 11.1 Typical repository layout
You have successfully created a new bare Git repository.
Discussion
Bare repositories don’t allow new commits to be created locally; they must be pushed from another repository.
HOW SHOULD YOU NAME BARE REPOSITORIES? When creating bare reposito-ries, it’s good practice to name them with the extension .git to make it clear that they’re bare.
Let’s look at the layout of a bare repository; see figure 11.2. You can see that the repository data that was stored in .git in figure 11.1 is instead in the root in figure 11.2. This means the root of the repository is effectively the .git directory (which is why it’s named GitInPracticeBare.git). The bare repository is miss-ing an index file and a logs directory and instead has a packed-refs file. These differences are internal Git files that are used for repositories; don’t worry about their contents (although you’ll see the packed-refs file in technique 64).
To clone this Git repository into a non-bare repository
on the same machine, run git clone with the path on disk to the repository and the new, non-bare repository name as arguments: for example, git clone /Users/mike/
GitInPracticeBare.git GitInPracticeNonBare. In this case, the output will resem-ble the following:
Cloning into 'GitInPracticeNonBare.git'...
warning: You appear to have cloned an empty repository.
done
The new repository has been created, but it’s empty—it contains no commits. If you add a file, commit, and push it, it will be pushed to the bare repository and both repositories will be non-empty. Note that you’d never usually clone a bare repository on the same machine but would instead create a bare repository on one machine and clone it on another.
Personally, I’ve only used bare repositories to create mirrors of existing reposito-ries on a server I control. I didn’t care about having the files checked-out into the working directory; I just wanted a copy of all the repository data. Let’s learn how to use Git to create an exact mirror of another repository.
Technique 64 Mirroring a repository: git clone - -mirror
There are times when you wish to host a new Git repository that’s a mirror of another—a functionally identical copy. This could be for backup, providing a local cache for increased speed, or moving a repository to another location. Recall from technique 8 that git clone creates a clone of the repository locally with all commits, branches, and tags that are in the repository you’ve cloned from.
Figure 11.2 Bare repository layout
177 TECHNIQUE 64 Mirroring a repository: git clone --mirror
If you git clone a repository with a branch named testing, your new, local clone will contain a remote branch named origin/testing. But what if you wanted this to create not only the origin/testing remote branch but also a local branch named testing? In this case, you’d use the --mirror flag for git clone, which creates local branches for all remote branches it finds (or, in Git terminology, matches all refs locally). This is useful when you want to create an exact copy of another repository (a mirror) so others can clone from it and get the same results as cloning from the origi-nal repository, or to keep as a backup. Recall the discussion of forks on GitHub from section 10.1. git clone --mirror is effectively what GitHub does when you fork a repository: it makes a complete copy that can be modified without changing the origi-nal repository and creates all the same branches.
Let’s use git clone --mirror to set up a local mirror of the GitInPracticeRedux repository.
Problem
You wish to mirror an existing remote repository.
Solution
1 Change to the directory you wish to contain your new repository directory: for example, cd /Users/mike/.
2 Run git clone --mirror https://github.com/GitInPractice/GitInPractice Redux.git. The output should resemble the following.
# git clone --mirror
https://github.com/GitInPractice/GitInPracticeRedux.git Cloning into bare repository 'GitInPracticeRedux.git'...
remote: Reusing existing pack: 79, done.
remote: Counting objects: 1, done.
remote: Total 80 (delta 0), reused 1 (delta 0) Unpacking objects: 100% (80/80), done.
Checking connectivity... done.
B
shows that git clone --mirror creates a bare repository when it creates a mirror.This is because --mirror is used only when hosting a repository for other reposito-ries to pull from.
You have mirrored the existing GitInPracticeRedux repository.
Discussion
As explained in technique 8, git clone can take the following tags:
No flags—Creates a normal (non-bare) repository with remote branches
--bare flag—Creates a bare repository with remote branches Listing 11.2 Output: cloning a mirror
Bare repository