|
| 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