Skip to content

Commit 64e8271

Browse files
brabojclaude
andcommitted
docs: add bare repositories recipe to playbook
Covers creating, cloning, converting, and using bare repos as local remotes. Includes layout comparison, push-to-non-bare gotcha, and practical multi-developer walkthrough. Closes #172 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent af89b0d commit 64e8271

2 files changed

Lines changed: 147 additions & 0 deletions

File tree

chapters/07-playbook.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ For definitions, see [Glossary](09-glossary.md).
3939
| [Remote Operations](playbook/remote-operations.md) | Push, pull, force push safely, sync forks |
4040
| [Remote Management](playbook/remote-management.md) | Add, rename, remove remotes, switch URL, SSH setup |
4141
| [SSH Setup](playbook/ssh-setup.md) | Key generation, agent, GitHub registration, troubleshooting |
42+
| [Bare Repositories](playbook/bare-repositories.md) | Create, clone, convert, and use bare repos as local remotes |
4243

4344
## Project Structure
4445

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
title: "Bare Repositories"
3+
description: "Git recipes for creating, cloning, and working with bare repositories — the standard layout for central and shared repositories."
4+
section: "playbook/bare-repositories"
5+
order: 93
6+
---
7+
8+
## Bare Repositories
9+
10+
A bare repository has no working tree — only the Git internals (objects,
11+
refs, config). It is the standard layout for central repositories that
12+
multiple developers push to. Hosting services like GitHub and GitLab
13+
store every repository as bare on the server.
14+
15+
For the theory behind bare vs non-bare repositories, see
16+
[Building Blocks](../02-building-blocks.md#bare-repository).
17+
18+
### Create a bare repository
19+
20+
```text
21+
$ git init --bare project.git
22+
Initialized empty Git repository in /home/user/project.git/
23+
```
24+
25+
The `.git` suffix is a convention, not a requirement — it signals that
26+
the directory is a bare repository.
27+
28+
### Compare the layouts
29+
30+
```text
31+
# Bare — no working tree, internals at the top level
32+
project.git/
33+
├── HEAD
34+
├── config
35+
├── hooks/
36+
├── objects/
37+
└── refs/
38+
39+
# Non-bare — working tree + .git folder
40+
project/
41+
├── .git/
42+
│ ├── HEAD
43+
│ ├── config
44+
│ ├── hooks/
45+
│ ├── objects/
46+
│ └── refs/
47+
└── README.md
48+
```
49+
50+
In a bare repository, what normally lives inside `.git/` sits at the
51+
top level. There is no place to check out files.
52+
53+
### Use a bare repository as a local remote
54+
55+
This is the most common use case — simulate a central server on your
56+
own machine for practice or local collaboration.
57+
58+
```text
59+
# 1. Create the bare (central) repository
60+
$ git init --bare /tmp/central.git
61+
62+
# 2. Clone it into a working copy
63+
$ git clone /tmp/central.git /tmp/dev-alice
64+
$ cd /tmp/dev-alice
65+
66+
# 3. Make a commit and push
67+
$ echo "Hello" > greeting.txt
68+
$ git add greeting.txt
69+
$ git commit -m "Add greeting"
70+
$ git push origin main
71+
72+
# 4. Clone again to simulate a second developer
73+
$ git clone /tmp/central.git /tmp/dev-bob
74+
$ cd /tmp/dev-bob
75+
$ cat greeting.txt
76+
Hello
77+
```
78+
79+
Both clones push to and pull from the same bare repository, exactly
80+
like working with GitHub.
81+
82+
### Convert a non-bare repository to bare
83+
84+
```text
85+
$ git clone --bare project project.git
86+
```
87+
88+
This copies only the Git data — no working tree files. The result is
89+
a bare repository you can use as a central remote.
90+
91+
You can also convert in place:
92+
93+
```text
94+
$ cd project
95+
$ mv .git ../project.git
96+
$ cd ..
97+
$ rm -rf project
98+
$ cd project.git
99+
$ git config --bool core.bare true
100+
```
101+
102+
### Clone a bare repository
103+
104+
```text
105+
$ git clone --bare https://github.com/user/project.git
106+
```
107+
108+
Useful for creating mirrors or backup copies that do not need a
109+
working tree.
110+
111+
### Push to a non-bare repository (and why it fails)
112+
113+
Pushing to a non-bare repository is rejected by default:
114+
115+
```text
116+
$ git push /tmp/dev-alice main
117+
remote: error: refusing to update checked out branch: refs/heads/main
118+
```
119+
120+
Git refuses because the push would change the branch that the working
121+
tree is based on, leaving the working tree out of sync. This is
122+
exactly why central repositories are bare — they have no working tree
123+
to desynchronize.
124+
125+
If you need to accept pushes on a non-bare repository (rare), you
126+
can enable it:
127+
128+
```text
129+
$ git config receive.denyCurrentBranch updateInstead
130+
```
131+
132+
This tells Git to update both the branch and the working tree on push.
133+
Use this only for special setups like deployment targets — not for
134+
regular development.
135+
136+
### Gotchas
137+
138+
- **You cannot run `git add` or `git commit` in a bare repository**
139+
there is no working tree to stage files from. All changes must arrive
140+
via `git push` from another repository.
141+
- **The `.git` suffix is convention only.** Git does not require it,
142+
but omitting it makes the directory harder to identify.
143+
- **Bare does not mean read-only.** A bare repository accepts pushes,
144+
runs hooks, and stores the same history as a non-bare one.
145+
- **`git clone` of a bare repository produces a non-bare clone by
146+
default.** Use `git clone --bare` if you want another bare copy.

0 commit comments

Comments
 (0)