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 Repository
A 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.
Similar Reads
What Is a GIT Repository? The repositories of Github act as essential places for storing the files with maintaining the versions of development. By using GitHub repositories developers can organize, monitor, and save their changes of code to their projects in remote environments. The files in the GitHub repository are import
10 min read
Managing Git Repositories with GitLab GitLab is a powerful platform for managing Git repositories, offering a list of features that provide collaboration, code review, continuous integration/continuous deployment (CI/CD), and more. This guide will walk you through Managing Git Repositories with GitLab. Table of Content How to Access Git
3 min read
Git- Setting up a Repository Git is a widely used version control system that helps developers manage and track changes in their codebase. Whether you are working on a personal project or collaborating with a team, setting up a Git repository is the first step to using Gitâs powerful features. This article will guide you throug
3 min read
How to Handle Big Repositories With Git? Git is a free and open-source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git relies on the basis of distributed development of software where more than one developer may have access to the source code of a specific ap
3 min read
Handling Repositories with Git Remote Git is a distributed version control system that allows multiple developers to collaborate on a project by working with repositories stored both locally and remotely. The git remote command enables users to manage remote repositories, synchronize changes, and collaborate efficiently.In this article,
3 min read