@@ -37,20 +37,37 @@ A repository can be **local** (on your machine) or **remote** (on a
3737server like GitHub). Git treats both as equals — you can push to and
3838pull from any repository you have access to.
3939
40- Git supports two repository layouts — ** bare** and ** non-bare** .
40+ Typically, the layout of a ** local** repository has a .git
41+ folder with all the internals, and a working tree with your project. This type
42+ of layout is called a ** non-bare repository** . The ` .git ` folder stores the
43+ full history and configuration. When you clone a repository, you get a regular
44+ repository with both the working tree and the ` .git ` folder.
4145
42- A ** bare repository** has no working tree — only the Git internals
43- (objects, refs, config) and no checked-out files. Hosting services like
44- GitHub and GitLab store repositories as bare on the server. When you
45- edit a file through GitHub's web interface, GitHub creates a commit
46- directly — it does not use a working tree.
46+ ``` text
47+ git clone project.git
48+
49+ PROJECT/
50+ │ readme.md # Working tree — your editable files
51+ └───.git # Repository internals (same as bare)
52+ ├───hooks # Event scripts
53+ ├───info # Repository metadata
54+ ├───objects # All Git objects
55+ │ ├───info # Object storage metadata
56+ │ └───pack # Compressed object packs
57+ └───refs # Named references
58+ ├───heads # Branch tips
59+ └───tags # Tag references
60+ ```
4761
48- > ** Note:** "bare" and "remote" are not the same thing. A remote is any
49- > repository you connect to via URL. Remotes are * usually* bare, but a
50- > remote can also be a regular repository on another machine.
62+ In contrast, the layout of remote repositories on hosting services like GitHub
63+ and GitLab is a little bit different — they are ** bare repositories** . A
64+ ** bare repository** has no working tree — only the Git internals
65+ (objects, refs, config) and no checked-out files. When you edit a file through
66+ GitHub's web interface, GitHub creates a commit directly — it does not use a
67+ working tree.
5168
5269``` text
53- git init --bare project.git
70+ git clone --bare project.git
5471
5572PROJECT.GIT/
5673├───hooks # Scripts that run on events (pre-commit, post-merge, etc.)
@@ -63,31 +80,22 @@ PROJECT.GIT/
6380 └───tags # Tag references
6481```
6582
66- A ** non-bare repository** (also called a regular or working repository)
67- is what you get when you clone or run ` git init ` . It has a working tree
68- where you create, edit and delete files, plus a hidden ` .git ` folder
69- that stores the full history and configuration.
83+ As a rule of thumb, if you see a ` .git ` folder, it's a regular repository with
84+ a working tree. If you see a folder that ends with ` .git ` but has no ` .git `
85+ inside it, it's a bare repository.
86+
87+ Both git clone and git init can create either type of repository. By default,
88+ they create regular repositories with a working tree. To create a bare
89+ repository, use the ` --bare ` flag:
7090
7191``` text
72- git clone project.git
92+ # creates a bare repository from a remote
93+ $ git clone --bare <repository-url>
7394
74- PROJECT/
75- │ readme.md # Working tree — your editable files
76- └───.git # Repository internals (same as bare)
77- ├───hooks # Event scripts
78- ├───info # Repository metadata
79- ├───objects # All Git objects
80- │ ├───info # Object storage metadata
81- │ └───pack # Compressed object packs
82- └───refs # Named references
83- ├───heads # Branch tips
84- └───tags # Tag references
95+ # creates a new bare repository locally
96+ $ git init --bare <directory-name>
8597```
8698
87- The ` .git ` folder contains the same structure as a bare repository.
88- The difference is that a non-bare repository also has a working tree
89- next to it — the place where you do your actual work.
90-
9199### Why bare repositories exist
92100
93101Imagine two developers — Alice and Bob — working on the same project
@@ -102,46 +110,48 @@ his remote and sends changes directly into her `.git/` directory.
102110 │ files from A │ │ │
103111 │ + uncommitted │ │ │
104112 ├──────────────────┤ ├──────────────────┤
105- │ .git/ │ git push │ .git/ │
106- │ main → B ───────│◄────────────│ main → B │
113+ │ .git/ │ git push │ .git/ │
114+ │ main → B ───────│◄───────────── │ main → B │
107115 │ (moved by push) │ │ │
108116 └──────────────────┘ └──────────────────┘
109117 ⚠ OUT OF SYNC
110118 branch says B, files say A
111119```
112120
113- The problem: when Bob sends his changes, Git updates the branch
114- inside Alice's ` .git/ ` to point to Bob's latest commit. But Alice's
115- working tree is ** not** updated — her files still reflect the old
116- commit, plus whatever edits she has in progress. Alice's branch and
117- her working tree are now out of sync. If she commits at this point,
118- she unknowingly ** reverts Bob's changes** — because her files do not
119- contain them.
120-
121- Git prevents this by refusing to accept changes sent to a non-bare
122- repository that has the target branch checked out.
121+ The problem: when Bob pushes his changes, Git updates the branch
122+ inside Alice's ` .git/ ` to point to Bob's latest commit immediately. But Alice's
123+ working tree is ** not** updated — her files still reflect the old commit, plus
124+ whatever edits she has in progress. Alice's branch and her working tree are
125+ now out of sync. If she commits at this point, she unknowingly ** reverts Bob's
126+ changes** — because her files do not contain them. Git prevents this by
127+ refusing to accept a push to a non-bare repository that has the target
128+ branch checked out.
123129
124- The solution is to place a ** bare repository** between the two
125- developers. A bare repository has no working tree — it holds only
126- objects and references. Because nobody edits files in it, updating a
127- branch is always safe.
130+ A popular solution to this kind of synchronization problem is to decouple the
131+ direct push/pull between two developers and introduce an intermediary
132+ repository that both developers push to and pull from.
128133
129134``` text
130135 Alice (non-bare) Shared hub (bare) Bob (non-bare)
131136 ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
132137 │ Working Tree │ │ │ │ Working Tree │
133- │ │ │ objects + refs │ │ │
134- ├──────────────────┤ │ no working tree │ ├──────────────────┤
138+ │ │ │ objects + refs │ │ │
139+ ├──────────────────┤ │ no working tree │ ├──────────────────┤
135140 │ .git/ │ │ │ │ .git/ │
136141 │ │◄───│ │◄───│ │
137142 └──────────────────┘ └──────────────────┘ └──────────────────┘
138143 pull push
139144 (when ready)
140145```
141146
147+ This is called a ** shared hub** . The shared hub is a bare repository — it has no
148+ working tree, only the Git internals. Its purpose is to hold commits and
149+ references, not to be edited directly. Because nobody edits files in it,
150+ updating a branch is always safe.
151+
142152With a bare repository in the middle, each developer works
143153independently. Bob sends his changes to the bare repository whenever
144- he is ready. Alice commits her own work first, then downloads Bob's
154+ he is ready. Alice commits her own work first, then pulls Bob's
145155changes from the bare repository when ** she** is ready. No one
146156reaches into anyone else's working tree. This is exactly how
147157hosting services like GitHub and GitLab work — every repository on
0 commit comments