Bare Repositories in Git - GeeksforGeeks

29 Dec, 2019
Repositories in Git are a snapshot of the folder in which you are working on your project. You can track the progress and changes made to the project by making commits and also revert changes if not satisfactory.Repositories can be divided into two types based on the usage on a server. These are:
Non-bare Repositories
Bare Repositories
What is a Non-bare repository?A non-bare or default git repository has a .git folder, which is the backbone of the repository where all the important files for tracking the changes in the folders are stored. It stores the hashes of commits made in the branches and a file where the hash of the latest commit is stored.The file structure of the default repository should look something like this:

    -- Default_Repo* 
    |-- .git* 
    |          |-- hooks* 
    |          |-- info* 
    |          |-- logs* 
    |          |-- objects* 
    |          |-- refs* 
    |          |-- COMMIT_EDITMSG 
    |          |-- config 
    |          |-- description 
    |          |-- HEAD 
    |          |-- index 
    |-- example.txt 

*: Folders 
As you can see, the .git folder contains all the required files for tracking the project folder. The default repository is always used for local repositories. What is a bare repository?A bare repository is the same as default, but no commits can be made in a bare repository. The changes made in projects cannot be tracked by a bare repository as it doesn’t have a working tree. A working tree is a directory in which all the project files/sub-directories reside. Bare repository is essentially a .git folder with a specific folder where all the project files reside.Practically speaking everything in the repository apart from .git is a part of working tree. To create a bare repository, navigate to the chosen directory in bash (for linux users) or command prompt (for windows users) and type:
 
>mkdir FileName.git 
>cd FileName.git 
>git init –bare 

The file structure of the bare repository should look like this:
-- BareRepo.git* 
              |-- hooks* 
              |-- info* 
              |-- logs* 
              |-- objects* 
              |-- refs* 
              |-- COMMIT_EDITMSG 
              |-- config 
              |-- description 
              |-- HEAD 
              |-- index 

*: Folders 
Note: This is the exact same file structure of .git folder in non-bare repository
It is important to note that all bare repositories have .git extension (E.g. notice BareRepo.git). Since you cannot commit, or make changes to it, bare repositories are pretty useless on their own. But then why does it exist? When people collaborate to work on a project, they need a central repository where all the tracked changes are stored and prevent any conflict between the versions of the project on other’s computers. A central repository also means that any new contributor can clone the repository into a local one without getting any unsaved changes or conflicting work of others (in short, no mess). A central repository was strictly supposed to be something like a reference repository.
This requires one to use a remote repository as a central one, and initially, only Bare repositories could be used as remote repositories. With the latest changes in git, central repositories need not be bare, hence not many people know about it properly.The only possible operations on the Bare Repository are Pushing or Cloning. Using a Bare RepositoryA bare repository is linked with a local repository, hence the files in .git of local repo should match with the files in the bare repo. First, create a bare repository (See section for the code snippet).Then, create a local repository folder and clone the bare repository:
 
>cd C:/Users/example/repositories 
>git clone C:/Users/example/BareRepo.git 
Cloning into 'BareRepo'...
warning: You appear to have cloned an empty repository. 
done. 

Don’t worry about the warning. The cloned repository will have the same name as that of the Bare Repository, navigate to that folder and add project files and commit changes. Then push the changes to the bare repository:
>git add * 
>git commit -m “First commit” 
[master (root-commit) ffdf43f] First Commit 
 1 file changed, 1 insertion(+) 
 create mode 100644 example.txt 
>git push c:/users/example/BareRepo.git 
Enumerating objects: 3, done. 
Counting objects: 100% (3/3), done. 
Delta compression using up to 4 threads 
Compressing objects: 100% (2/2), done. 
Writing objects: 100% (3/3), 293 bytes | 97.00 KiB/s, done. 
Total 3 (delta 0), reused 0 (delta 0) 
To c:/users/example /BareRepo.git  
 * [new branch]      master -> master 

And thus, your local repo has been linked to the Bare Repository. In case you already have some files in the project directory, directly initialize the project folder as a git repository, then push its changes to a bare repository (make sure that the Bare repository is not linked to any other project or is newly created). Another way is to clone your working project repository into a bare one:
>cd “Central Repositories” 
>git clone –bare ../../..../Default_Repo 
Cloning into bare repository 'Default_Repo.git'... 
done. 

 Why is only Bare Repository used as a Central Repository for syncing work?Central Repositories use bare repositories only because git doesn’t allow you to push to a non-bare repository as the working tree will become inconsistent.To demonstrate why you can’t push to a non-bare repository:
>cd C:/Users/example/repositories 
>mkdir RepoTest 
>cd RepoTest 
>git init 
Initialized empty Git repository in C:/Users/example/repositories/RepoTest/.git/ 
>cd ../BareRepo 
>git push ../RepoTest 
Enumerating objects: 3, done. 
Counting objects: 100% (3/3), done. 
Delta compression using up to 4 threads 
Compressing objects: 100% (2/2), done. 
Writing objects: 100% (3/3), 293 bytes | 146.00 KiB/s, done. 
Total 3 (delta 0), reused 0 (delta 0) 
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: is denied, because it will make the index and work tree inconsistent 
remote: with what you pushed, and will require 'git reset --hard' to match 
remote: the work tree to HEAD. 
remote: 
remote: You can set the 'receive.denyCurrentBranch' configuration variable 
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into 
remote: its current branch; however, this is not recommended unless you 
remote: arranged to update its work tree to match what you pushed in some 
remote: other way. 
remote: 
remote: To squelch this message and still keep the default behaviour, set 
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'. 
To ../RepoTest 
 ! [remote rejected] master -> master (branch is currently checked out) 
error: failed to push some refs to '../RepoTest'

But if you still want to be stubborn about it, you can read the warning and go to the non-bare repository where you wish to push and set receive.denyCurrentBranch to ignore and then push the changes.
>cd ../RepoTest 
>git config receive.denyCurrentBranch ignore 
>cd ../Default_Repo 
>git push ../RepoTest 
Enumerating objects: 3, done. 
Counting objects: 100% (3/3), done. 
Delta compression using up to 4 threads 
Compressing objects: 100% (2/2), done. 
Writing objects: 100% (3/3), 293 bytes | 146.00 KiB/s, done. 
Total 3 (delta 0), reused 0 (delta 0) 
To ../RepoTest 
 * [new branch]      master -> master 

But, using this will give you more problems, as you keeping pushing to remote repo, you’ll notice that only the commit head points to keeps changing (along with other files in .git), but your working tree will remain the same. The only way to remove the inconsistency of index and working tree is by using the command:
>git reset –hard 
Unless you want to do this every time you push changes to the remote repository, it is recommended to use a bare repository.A bare repository takes much less space to store the same information along with the tracked changes than a non-bare repository. Hence, its storage consumption is the most efficient. Therefore, only a bare repository is suited to serve as a remote or central repository.
Git
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
How to Set Git Username and Password in GitBash?
Difference Between Git Push Origin and Git Push Origin Master
How to Undo a Commit in Git ?
Using GitHub with SSH (Secure Shell)
How to Push Git Branch to Remote?
How to Export Eclipse projects to GitHub?
How to Clone Android Project from GitHub in Android Studio?
What is README.md File?
Top 10 GitHub Alternatives That You Can Consider
GIT | An Introduction to Github