What is the difference between "git init" and "git init --bare"?

GitVersion Control

Git Problem Overview


What is the different between git init and git init --bare? I found that a lot of blog post requires --bare for their Git server?

From the man page, it said: > --bare > Create a bare repository. If GIT_DIR environment is not set, it is set to the current working directory

But what does it actually mean? Is it required to have --bare for the Git server setup?

Git Solutions


Solution 1 - Git

Non-Bare Git Repo

This variant creates a repository with a working directory so you can actually work (git clone). After creating it you will see that the directory contains a .git folder where the history and all the git plumbing goes. You work at the level where the .git folder is.

Bare Git Repo

The other variant creates a repository without a working directory (git clone --bare). You don't get a directory where you can work. Everything in the directory is now what was contained in the .git folder in the above case.

Why You Would Use One vs. the Other

The need for git repos without a working directory is the fact that you can push branches to it and it doesn't manage what someone is working on. You still can push to a repository that's not bare, but you will get rejected as you can potentially move a branch that someone is working on in that working directory.

So in a project with no working folder, you can only see the objects as git stores them. They are compressed and serialized and stored under the SHA1 (a hash) of their contents. In order to get an object in a bare repository, you need to git show and then specify the sha1 of the object you want to see. You won't see a structure like what your project looks like.

Bare repositories are usually central repositories where everyone moves their work to. There is no need to manipulate the actual work. It's a way to synchronize efforts between multiple people. You will not be able to directly see your project files.

You may not have the need for any bare repositories if you are the only one working on the project or you don't want/need a "logically central" repository. One would prefer git pull from the other repositories in that case. This avoids the objections that git has when pushing to non-bare repositories.

Hope this helps

Solution 2 - Git

Short answer

A bare repository is a git repository without a working copy, therefore the content of .git is top-level for that directory.

Use a non-bare repository to work locally and a bare repository as a central server/hub to share your changes with other people. For example, when you create a repository on github.com, it is created as a bare repository.

So, in your computer:

git init
touch README
git add README
git commit -m "initial commit"

on the server:

cd /srv/git/project
git init --bare

Then on the client, you push:

git push username@server:/srv/git/project master

You can then save yourself the typing by adding it as a remote.

The repository on the server side is going to get commits via pull and push, and not by you editing files and then commiting them in the server machine, therefore it is a bare repository.

Details

You can push to a repository that is not a bare repository, and git will find out that there is a .git repository there, but as most "hub" repositories do not need a working copy, it is normal to use a bare repository for it and recommended as there is no point in having a working copy in this kind of repositories.

However, if you push to a non bare repository, you are making the working copy inconsistent, and git will warn you:

remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.

You can skip this warning. But the recommended setup is: use a non-bare repository to work locally and a bare repository as a hub or central server to push and pull from.

If you want to share work directly with other developer's working copy, you can pull from each other repositories instead of pushing.

Solution 3 - Git

When I read this question some time ago, everything was confusing to me. I just started to use git and there are these working copies (which meant nothing at that time). I will try to explain this from perspective of the guy, who just started git with no idea about terminology.

A nice example of the differences can be described in the following way:

--bare gives you just a storage place (you can not develop there). Without --bare it gives you ability to develop there (and have a storage place).

git init creates a git repository from your current directory. It adds .git folder inside of it and makes it possible to start your revision history.

git init --bare also creates a repository, but it does not have the working directory. This means that you can not edit files, commit your changes, add new files in that repository.

When --bare can be helpful? You and few other guys are working on the project and use git . You hosted the project on some server (amazon ec2). Each of you have your own machine and you push your code on ec2. None of you actually develop anything on ec2 (you use your machines) - you just push your code. So your ec2 is just a storage for all your code and should be created as --bare and all your machines without --bare (most probably just one, and other will just clone everything). The workflow looks like this:

enter image description here

Solution 4 - Git

A default Git repository assumes that you will be using it as your working directory. Typically, when you are on a server, you have no need to have a working directory. Just the repository. In this case, you should use the --bare option.

Solution 5 - Git

A non-bare repository is the default. It is what is created when you run git init, or what you get when you clone (without the bare option) from a server.

When you work with a repository like this, you can see and edit all of the files that are in the repository. When you interact with the repository - for example by committing a change - Git stores your changes in a hidden directory called .git.

When you have a git server there is no need for there to be working copies of the files. All you need is the Git data that's stored in .git. A bare repository is exactly the .git directory, without a working area for modifying and committing files.

When you clone from a server Git has all the information it needs in the .git directory to create your working copy.

Solution 6 - Git

Another difference between --bare and Working Tree repositories is that in the first case no lost commits are stored, but only commits that belong to a branch track are stored. On the other hand, Working Tree keeps all commits forever. See below...

I created the first repository (name: git-bare) with git init --bare. It's the server. It's on the left side, where there are no remote branches because this is the remote repository itself.

I created the second repository (name: git-working-tree) with git clone from the first. It's on the right. It has local branches linked to remote branches.

(The texts 'first', 'second', 'third', 'fourth', 'alpha', 'beta' and 'delta' are the commit comments. The names 'master' and 'greek' are branch names.)

Local and remote repositories

Now I will delete the branch named 'greek' both in git-bare (command: git push --delete origin greek) and locally in git-working-tree (command: git branch -D greek). Here's how the tree looks:

The git-bare repository deletes what is no longer referenced

The git-bare repository deletes both the branch and all referenced comits. In the picture we see that its tree was reduced for this reason.

On the other hand, the git-working-tree repository, which is equivalent to a commonly used local repository, does not delete commits, which can now only be referenced directly by your hash with a git checkout 7fa897b7 command. That is why its tree does not have its modified structure.

IN BRIEF: Commits are never dropped in working-tree repositories, but are deleted in bare repositories.

In practical terms, you can only recover a deleted branch on the server if it exists in a local repository.

But it is very strange that the size of the bare repository does not decrease in disk size after deleting a remote branch. That is, the files are still there somehow. To dump the repository by deleting what is no longer referenced or what can never be referenced (the latter case) use the git gc --prune command

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTheOneTeamView Question on Stackoverflow
Solution 1 - GitAdam DymitrukView Answer on Stackoverflow
Solution 2 - GitduncanView Answer on Stackoverflow
Solution 3 - GitSalvador DaliView Answer on Stackoverflow
Solution 4 - GitSandro MundaView Answer on Stackoverflow
Solution 5 - GitAndrewView Answer on Stackoverflow
Solution 6 - GitSergio CabralView Answer on Stackoverflow