This maybe has been answered, but I didn't find a good answer.
I come from centralized repositories, such as SVN, where usually you only perform checkouts, updates, commits, reverts, merges and not much more.
Git is driving me crazy. There are tons of commands, but the most difficult to understand is why many things work as they do.
According to "What is a bare git repository?":
Repositories created with
git init --bare
are called bare repos. They are structured a bit differently from working directories. First off, they contain no working or checked out copy of your source files.
…
A bare repository created withgit init --bare
is for… sharing. …developers will clone the shared bare repo, make changes locally in their working copies of the repo, then push back to the shared bare repo to make their changes available to other users.
– Jon Saints, http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/
However, from the accepted answer to "what's the difference between github repository and git bare repository?":
Git repos on GitHub are bare, like any remote repo to which you want to push to [sic].
– VonC, https://stackoverflow.com/a/20855207
However, in GitHub there are source files. I can see them. If I create a bare repository, there are no source files, only the contents for .git
directory of a working repository.
How is this possible? What don't I understand?
Can you give an example about why I would need a bare repository and its motivation to work that way?
UPDATE
Edward Thomson's answer is, in part, what I wanted to know. Nevertheless, I will rephrase my question:
First link I posted states("What is a bare git repository?"):
they [bare repositories] contain no working or checked out copy of your source files.
VonC's answer:
Git repos on GitHub are bare
Both statements implies
Github has no working copy.
Edward Thomson says:
it renders the web page based on the data as you navigate through it – pulling the data directly out of the repo and out to your web browser, not writing it to a disk on the fileserver first
Somehow, a bare repository has to contain all data and source code. If not, it wouldn't be possible to render anything, because I can see all source code updated (commited), all branches (with their respective source), the whole log of a repo, etc.
Is there the whole data of a repository always within .git directory (or in a bare repo), in some kind of format which is able to render all files at any time? Is this the reason of bare repository, while working copy only has the files at a given time?
Best Answer
Yes, those files and their complete history are stored in
.git/packed-refs
and.git/refs
, and .git/objects.When you clone a repo (bare or not), you always have the
.git
folder (or a folder with a.git
extension for bare repo, by naming convention) with its Git administrative and control files. (see glossary)Git can unpack at any time what it needs with git unpack-objects.
The trick is:
From a bare repo, you can query the logs (
git log
in a git bare repo works just fine: no need for a working tree), or list files in a bare repo.Or show the content of a file from a bare repo.
That is how GitHub can render a page with files without having to check out the full repo.
I don't know that GitHub does exactly that, though, as the sheer number of repos forces GitHub engineering team to do all kind of optimization.
See for instance how they optimized cloning/fetching a repo.
With DGit, those bare repos are actually replicated across multiple servers.
For GitHub, maintaining a working tree would cost too much in disk space, and in update (when each user requests a different branch). It is best to extract from the unique bare repo what you need to render a page.
In general (outside of GitHub constraint), a bare repo is used for pushing, in order to avoid having a working tree out of sync with what has just been pushed. See "but why do I need a bare repo?" for a concrete example.
That being said:
But that would not be possible for GitHub, which cannot maintain one (or server) working tree(s) for each repo it has to store.
The article "Using a bare Git repo to get version control for my dot files" from Greg Owen, originally reported by aifusenno1 adds:
And Greg adds:
See Git repository layout:
A
<project>.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.With Git 2.38 (Q3 2022) introduces a
safe.bareRepository
configuration variable that allows users to forbid discovery of bare repositories.See commit 8d1a744, commit 6061601, commit 5b3c650, commit 779ea93, commit 5f5af37 (14 Jul 2022) by Glen Choo (
chooglen
).(Merged by Junio C Hamano --
gitster
-- in commit 18bbc79, 22 Jul 2022)git config
now includes in its man page:With Git 2.41 (Q2 2023), the tracing mechanism learned to notice and report when auto-discovered bare repositories are being used, as allowing so without explicitly stating the user intends to do so (with setting
GIT_DIR
for example) can be used with social engineering as an attack vector.See commit e35f202 (01 May 2023) by Glen Choo (
chooglen
).(Merged by Junio C Hamano --
gitster
-- in commit fa88934, 15 May 2023)With Git 2.44 (Q1 2024), batch 12, the "disable repository discovery of a bare repository" check, triggered by setting
safe.bareRepository
configuration variable to 'explicit', has been loosened to exclude the ".git/
" directory inside a non-bare repository from the check.So you can do "
cd .git && git cmd
" to run a Git command that works on a bare repository without explicitly specifying$GIT_DIR
now.See commit 45bb916 (20 Jan 2024) by Kyle Lippincott (
spectral54
).(Merged by Junio C Hamano --
gitster
-- in commit a8bf3c0, 30 Jan 2024)With Git 2.45 (Q2 2024), batch 10, users with
safe.bareRepository=explicit
can still work from within$GIT_DIR
of a secondary worktree (which resides at.git/worktrees/$name/
) of the primary worktree without explicitly specifying the$GIT_DIR
environment variable or the--git-dir=<path>
option.See commit 30b7c4b (09 Mar 2024) by Junio C Hamano (
gitster
).(Merged by Junio C Hamano --
gitster
-- in commit dc97afd, 21 Mar 2024)