274

I've been reading about the bare and non-bare / default repositories in Git. I haven't been able to understand quite well (theoretically) the differences between them, and why I should "push" to a bare repository. Here's the deal:

Currently, I'm the only one working on a project on 3 different computers, but there will be more people involved in it later, so I'm using Git for the version control. I clone the bare repo on all computers, and when I finish my modifications on one of them, I commit and push the changes to the bare repo. From what I've read, the bare repository does NOT have a "working tree", so if I clone the bare repo, I won't have a "working tree".

I'm guessing that the working tree stores the commit information, branches, etc. from the project. That wouldn't appear in the bare repo. So it seems better for me to "push" the commits to the repo with the working tree.

Then, why should I use the bare repository and why not? What's the practical difference? That would not be beneficial to more people working on a project, I suppose.

What are your methods for this kind of work? Suggestions?

Vlad L.
  • 154
  • 1
  • 9
AeroCross
  • 3,969
  • 3
  • 23
  • 30
  • 4
    AeroCross, you *can* clone a bare repository to create a non-bare repository (that is, one which has a workspace). So, using `git clone` you can freely convert between bare and non-bare repositories. – Derek Mahar Apr 04 '11 at 16:52
  • @Derek I knew that I could clone a non-bare to a bare, but not the other way around. Excellent little tip. – AeroCross Apr 04 '11 at 18:18
  • 18
    @AeroCross: It's not about converting; it doesn't matter what's on the other end. If you run `git clone --bare` you'll get a bare repo, and if you run `git clone`, you'll get a non-bare one. Every public project that you've ever cloned (hosted on github, for example) is a bare repository on the other end. – Cascabel Apr 04 '11 at 18:43
  • 1
    Jefromi, I was correcting AeroCross' point, "so if I clone the bare repo, I won't have a "working tree"", so it is a kind of conversion. And not every public project must be a bare repository. It's just the typical choice because a bare repository is more space efficient since it has no working tree (it's as space efficient as any repository that has no working tree, though). – Derek Mahar Apr 04 '11 at 18:55
  • 3
    @Derek: But the point is that, as soon as it finds the .git directory, fetching is wholly unaware of whether the remote is bare or not. It doesn't convert. It just fetches what it needs from the remote, and puts it where it should go. There's nothing to convert. That's what I was trying to emphasize to the OP. And I'm well aware that public projects don't have to be bare, but because people aren't stupid, they essentially all are. I think I made an acceptable generalization. – Cascabel Apr 05 '11 at 06:02
  • Jefromi, I used the term conversion as a metaphor to help AeroCross understand that Git can clone a bare repository. I understand that the repository itself (the contents of `.git`) does not undergo any conversion unless you count packing free objects for efficiency as a structural conversion. Certainly, Git does not convert the commit and other repository objects during cloning. – Derek Mahar Apr 05 '11 at 11:05
  • 2
    See [Push to non-bare repository](http://stackoverflow.com/questions/1764380/push-to-non-bare-repository) which gives another excellent explanation of bare repository usage. – Craig McQueen May 02 '14 at 00:24
  • Please see this article, very well explanation: I use a working directory created with git init or git clone when I want to add, edit and delete files in myproject locally on my dev machine. When I am ready, I share my local changes with a git push to a bare repository myproject.git (usually on a remote server like github.com) so other developers can access my local changes. [http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/] – longbkit May 21 '18 at 08:11
  • Read Here, http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/ – John Aug 04 '20 at 11:44

11 Answers11

119

Another difference between a bare and non-bare repository is that a bare repository does not have a default remote origin repository:

~/Projects$ git clone --bare test bare
Initialized empty Git repository in /home/derek/Projects/bare/
~/Projects$ cd bare
~/Projects/bare$ git branch -a
* master
~/Projects/bare$ cd ..
~/Projects$ git clone test non-bare
Initialized empty Git repository in /home/derek/Projects/non-bare/.git/
~/Projects$ cd non-bare
~/Projects/non-bare$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

From the manual page for git clone --bare:

Also the branch heads at the remote are copied directly to corresponding local branch heads, without mapping them to refs/remotes/origin/. When this option is used, neither remote-tracking branches nor the related configuration variables are created.

Presumably, when it creates a bare repository, Git assumes that the bare repository will serve as the origin repository for several remote users, so it does not create the default remote origin. What this means is that basic git pull and git push operations won't work since Git assumes that without a workspace, you don't intend to commit any changes to the bare repository:

~/Projects/bare$ git push
fatal: No destination configured to push to.
~/Projects/bare$ git pull
fatal: /usr/lib/git-core/git-pull cannot be used without a working tree.
~/Projects/bare$ 
Enlico
  • 23,259
  • 6
  • 48
  • 102
Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • I think this is the most detailed answer I can find around. IMO, this is the most significant difference between the bare and non-bare repository, and the answer clears up perfectly the working scheme I'm using. Thanks a lot! – AeroCross Apr 04 '11 at 18:16
  • 3
    Yes, I agree that this is arguably the most significant difference between bare and non-bare Git repositories. The fact that a non-bare repository has a workspace, but a bare repository does not is an important difference, but `git clone --no-checkout` can create a non-bare repository with no workspace files, too. – Derek Mahar Apr 04 '11 at 18:38
  • 14
    A non-bare repository doesn't necessarily have a default remote "origin", either. – mipadi Apr 04 '11 at 18:43
  • 1
    mipadi, how do yo create such a repository using `git clone`? As far as I understand, unless you specify `--bare`, `git clone` always creates the default remote origin. I agree, however, that after you clone a repository, you can delete the remote origin in the clone. – Derek Mahar Apr 04 '11 at 18:47
  • 3
    You can create a Git repository simply with `git init`, which will create a non-bare repo with no remote specified. – mipadi Apr 04 '11 at 18:52
  • 3
    mipadi, this is true, but it's also not a clone. – Derek Mahar Apr 04 '11 at 18:59
  • 3
    This is incorrect. A repository will have a default origin if it has been `clone`ed. If it has been `init`ed locally, it will not have such an origin. This has nothing to do with whether it is bare or not. – Noufal Ibrahim Oct 07 '11 at 09:49
  • Noufal, this is what mipadi stated a few comments before yours. I stated in a comment to mipadi's answer that you can create a non-bare repository without a checked-out working tree and both you and mipadi pointed out that you can create a non-bare repository without an origin. So what, then, is a key difference between a bare and non-bare repository? – Derek Mahar Oct 07 '11 at 22:45
  • Great explanation of bare and non-bare repository @Derek Mahar. – Jyotsna Saroha Jul 31 '14 at 09:56
  • Now the question is how to change a bare repo into non-bare (e.g., because the original bare repo was a mirror of a remote hg repo and by cloning I would loose all information in `.git/hg`)? – mcepl Oct 16 '14 at 17:38
  • @DerekMahar What do you mean by default remote origin? As stated `git init` is non-bare and obviously has no origin (same for --bare). I would think that **all** cloning has an origin. Shouldn't you be checking for the origin with `git remote show origin`? `git clone --bare ` clones the repo as a bare repo, meaning it is the .git directory and good notation would be instead `git clone --bare `. If you check a clone, either --bare or not, it has an origin. Bares by default rather do not allow pulling from origin (or anywhere), as stated since they have no working tree. – Novice C Aug 25 '16 at 21:54
  • @NoviceC A default remote origin is a reference in the repository to the clone source. According to my example (this may have changed in later versions of Git), `git clone --bare` does not create a default remote origin. – Derek Mahar Aug 25 '16 at 22:37
  • 1
    Anyway, I'm not sure why the OP accepted this answer. I was trying to provide another difference between bare and non-bare repositories. @mipadi made a good point that a new Git repository created with `git init` also doesn't have default remote origin. The question didn't require that the bare repository be created only with `git clone`. – Derek Mahar Aug 25 '16 at 22:42
  • @DerekMahar, if I create a repo via `git clone --bare originalrepo barerepo`, and then issue `git remote -v` while in `barerepo` directory, I obtain `origin /full/path/of/orignalrepo (fetch)` and `origin /full/path/of/orignalrepo (push)`; so I'd say `barerepo` has got the `origin` remote. Could you elaborate on this? Maybe it's about `git` version? – Enlico Jan 24 '19 at 08:56
  • @DerekMahar, oh, btw, when I do `git clone --bare originalrepo barerepo` the output on stdout is `Cloning into bare repository 'barerepo'...` and not `Initialized empty Git repository in /full/path/of/barerepo/`. – Enlico Jan 24 '19 at 08:58
99

5 years too late, I know, but no-one actually answered the question:

Then, why should I use the bare repository and why not? What's the practical difference? That would not be beneficial to more people working on a project, I suppose.

What are your methods for this kind of work? Suggestions?

To quote directly from the Loeliger/MCullough book (978-1-449-31638-9, p196/7):

A bare repository might seem to be of little use, but its role is crucial: to serve as an authoritative focal point for collaborative development. Other developers clone and fetch from the bare repository and push updates to it... if you set up a repository into which developers push changes, it should be bare. In effect, this is a special case of the more general best practice that a published repository should be bare.

EML
  • 9,619
  • 6
  • 46
  • 78
89

The distinction between a bare and non-bare Git repository is artificial and misleading since a workspace is not part of the repository and a repository doesn't require a workspace. Strictly speaking, a Git repository includes those objects that describe the state of the repository. These objects may exist in any directory, but typically exist in the .git directory in the top-level directory of the workspace. The workspace is a directory tree that represents a particular commit in the repository, but it may exist in any directory or not at all. Environment variable $GIT_DIR links a workspace to the repository from which it originates.

Git commands git clone and git init both have options --bare that create repositories without an initial workspace. It's unfortunate that Git conflates the two separate, but related concepts of workspace and repository and then uses the confusing term bare to separate the two ideas.

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • 3
    Really Good point you bring up. Would it be correct to say "A Nonbare git repository has a supplemental workspace directory tree( but A bare git repository does Not )" ? – crazyTech Jul 08 '21 at 20:01
80

A bare repository is nothing but the .git folder itself i.e. the contents of a bare repository is same as the contents of .git folder inside your local working repository.

  • Use bare repository on a remote server to allow multiple contributors to push their work.
  • Non-bare - The one which has working tree makes sense on the local machine of each contributor of your project.
Deepak Sharma
  • 943
  • 6
  • 9
  • 2
    Can't multiple contributors push their work anyway? There's no need for a bare repository. Anyway with a normal repository as well lots of people can work parallely. – Mugen Oct 06 '21 at 13:53
  • @Mugen, with non bare repository you'll get an error message on your local machine trying to push to the checkouted branch. – Andrew Anderson Nov 18 '22 at 15:36
  • 1
    @Deepak, then what's the point of the term bare repo? Why not just call it the normal thing with everything but the .git folder deleted? or the normal thing's .git subfolder? – Pacerier Apr 24 '23 at 22:16
41

A default/non-bare Git repo contains two pieces of state:

  1. A snapshot of all of the files in the repository (this is what "working tree" means in Git jargon)
  2. A history of all changes made to all the files that have ever been in the repository (there doesn't seem to be a concise piece of Git jargon that encompasses all of this)

The snapshot is what you probably think of as your project: your code files, build files, helper scripts, and anything else you version with Git.

The history is the state that allows you to check out a different commit and get a complete snapshot of what the files in your repository looked like when that commit was added. It consists of a bunch of data structures that are internal to Git that you've probably never interacted with directly. Importantly, the history doesn't just store metadata (e.g. "User U added this many lines to File F at Time T as part of Commit C"), it also stores data (e.g. "User U added these exact lines to File F").

The key idea of a bare repository is that you don't actually need to have the snapshot. Git keeps the snapshot around because it's convenient for humans and other non-Git processes that want to interact with your code, but the snapshot is just duplicating state that's already in the history.

A bare repository is a Git repository that does not have a snapshot. It just stores the history.

Why would you want this? Well, if you're only going to interact with your files using Git (that is, you're not going to edit your files directly or use them to build an executable), you can save space by not keeping around the snapshot. In particular, if you're maintaining a centralized version of your repo on a server somewhere (i.e. you're basically hosting your own GitHub), that server should probably have a bare repo (you would still use a non-bare repo on your local machine though, since you'll presumably want to edit your snapshot).

If you want a more in-depth explanation of bare repos and another example use case, I wrote up a blog post here: https://stegosaurusdormant.com/bare-git-repo/

Greg Owen
  • 947
  • 8
  • 19
  • 1
    The "non-bare" repo also contains the staging area https://stackoverflow.com/questions/49228209/whats-the-use-of-the-staging-area-in-git needed for ongoing development – qneill Mar 23 '22 at 15:16
  • 4
    This answer was the most useful in understanding the difference. Thanks – mynameistechno Sep 15 '22 at 17:46
22

A non-bare repository simply has a checked-out working tree. The working tree does not store any information about the state of the repository (branches, tags, etc.); rather, the working tree is just a representation of the actual files in the repo, which allows you to work on (edit, etc.) the files.

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • So that means that I can add branches, tags, etc. to the bare repository then pull from the bare to the non-bare / production repository? – AeroCross Apr 04 '11 at 16:05
  • 3
    mipadi, a non-bare repository may not have a checked-out tree. This is the case if you create a non-bare repository with `git clone --no-checkout`. In this case, the non-bare repository has a location for the workspace, but Git doesn't checkout any files into that workspace. – Derek Mahar Apr 04 '11 at 18:35
21

A bare repository has benefits in

  • reduced disk usage
  • less problems related to remote push (since no working tree is there to get out of synch or have conflicting changes)
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 3
    So the bare repository is the best / recommended way to work with several people with no access to THEIR repositories? (Kinda like SVN?) – AeroCross Apr 04 '11 at 16:07
  • 2
    AeroCross, I'd say a bare repository is a good choice for that scenario. – Derek Mahar Apr 04 '11 at 16:41
  • I thought "n commits ahead" message was related to branches (i.e. refs) and not related to working trees. – aderchox Jul 29 '20 at 08:01
  • @aderchox Yes, Nothing here contradicts that? – sehe Jul 29 '20 at 12:01
  • I mean if a developer makes a push to the remote repository, then all other contributors will be out of sync anyways, whether the remote is a bare or non-bare repository. Maybe I don't quite understand the meaning of "sync" in your answer. – aderchox Jul 29 '20 at 12:06
  • 1
    @aderchox If the remote repo isn't bare, it _would_ cause the worktree to get out of sync with a checked out HEAD as well. This is why it wouldn't be allowed, and thus the advantage of having a bare repo (basically, just don't have a worktree) – sehe Jul 29 '20 at 12:09
17

Non bare repository allows you to (into your working tree) capture changes by creating new commits.

Bare repositories are only changed by transporting changes from other repositories.

Nitin
  • 326
  • 4
  • 11
  • That makes sense, as the developer's workstation would have a non-bare repository & changes are git pushed into a bare repository on a server. – Clomp Jun 27 '22 at 05:32
14

I'm certainly not a Git "expert". I have used TortoiseGit for a while and wondered what it was talking about when it asked me if I wanted to make a "bare" repo whenever I created one. I was reading this tutorial: https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init and it addresses the issue, but I still was not quite understanding the concept. This one helped a lot: http://bitflop.com/tutorials/git-bare-vs-non-bare-repositories.html. Now, the first one makes sense too!

According to these sources, in a nutshell, a "bare" repo is used on a server where you want to set up a distribution point. It's not intended for use on your local machine. You generally push commits from your local machine to a bare repo on a remote server, and you and/or others pull from that bare repo to your local machine. So your GitHub, Assembla, etc. remote storage/distribution repo is an example where a "bare" repo is created. You would make one yourself if you were setting up your own analogous "sharing center".

Vlad L.
  • 154
  • 1
  • 9
BuvinJ
  • 10,221
  • 5
  • 83
  • 96
  • Note: The BitFlop link no longer exists in 2022. That domain is up for sale. However, the Atlassian Bitbucket tutorial is still a useful link! – Clomp Jun 27 '22 at 05:19
4

This is not a new answer, but it helped me to understand the different aspects of the answers above (and it is too much for a comment).

Using Git Bash just try:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init
Initialized empty Git repository in C:/Test/.git/

me@pc MINGW64 /c/Test (master)
$ ls -al
total 20
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:35 .git/

me@pc MINGW64 /c/Test (master)
$ cd .git

me@pc MINGW64 /c/Test/.git (GIT_DIR!)
$ ls -al
total 15
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 ../
-rw-r--r-- 1 myid 1049089 130 Apr  1 11:35 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:35 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:35 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 objects/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:35 refs/

Same with git --bare:

me@pc MINGW64 /c/Test
$ ls -al
total 16
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089 0 Apr  1 11:11 ../

me@pc MINGW64 /c/Test
$ git init --bare
Initialized empty Git repository in C:/Test/

me@pc MINGW64 /c/Test (BARE:master)
$ ls -al
total 23
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 ./
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:11 ../
-rw-r--r-- 1 myid 1049089 104 Apr  1 11:36 config
-rw-r--r-- 1 myid 1049089  73 Apr  1 11:36 description
-rw-r--r-- 1 myid 1049089  23 Apr  1 11:36 HEAD
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 hooks/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 info/
drwxr-xr-x 1 myid 1049089   0 Apr  1 11:36 objects/
Christoph
  • 6,841
  • 4
  • 37
  • 89
3

$ git help repository-layout

A Git repository comes in two different flavours:

  • a .git directory at the root of the working tree;
  • a .git directory that is a bare repository (i.e. without its own working tree), that is typically used for exchanging histories with others by pushing into it and fetching from it.
Community
  • 1
  • 1
MichK
  • 3,202
  • 3
  • 29
  • 33