0

I read Pro Git book up to Git on the Server chapter, where it shows how to make a Git server: it says that (page 94):

In order to initially set up any Git server, you have to export an existing repository into a new bare repository — a repository that doesn’t contain a working directory

Once the server was done, I realized that no working directory means no code: if I got this right, no code is stored in our server.

My principal asked me to set up a Git server in our company network to store the most recent production code, but he wants the code to be there: he thinks of this server both as Git server and updates server.

This means that our Git server, with no code inside, should provide updates with the code we developers make.

Is this actually possible or should I give different advices about the updates, splitting the jobs between storing code (with Git server) and providing updates (with another server)?

elmazzun
  • 1,066
  • 2
  • 18
  • 44

2 Answers2

1

No working directory does not mean no code. The code history is stored in the database, and that is the primary purpose of a bare repository.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • I explored all the directories in `project.git` in our remote Git server but I don't see the databse you are talking about. By `database` you mean the collection of `objects`? – elmazzun Feb 07 '18 at 15:29
  • In general, the git database can contain "loose" objects (`objects/##/######################################`) and pack files (`objects/pack/pack-########################################.idx` and `objects/pack/pack-########################################.pack`). Only pack files are sent between repos during fetch and push, so a bare repo will not have loose objects. – Mark Adelsberger Feb 07 '18 at 16:06
1

As Mark Adelsberger noted, the database (the .git/objects/ and .git/objects/pack/ directories, in a non-bare repository) stores everything.

The point of Git is to store commits, generally forever. These commits aren't files, although they do (indirectly) contain files. The objects—files, which Git calls blobs; commits, and two more internal object types called trees and annotated tags—are all stored in a special, compressed (sometimes very compressed), Git-only format. These are only useful to Git itself, in general.

In order for you, or the rest of your computer, to work with files, they need to be in ordinary format, not some special Git-only format. Git lets you do this in an area where you will do your own work: a work-tree.

If you have a work-tree, though, you are likely to use it to do work. If a Git repository is supposed to receive and act upon push requests, what happens to the in-progress work in some poor fellow's work-tree when, out of the blue, bam! someone pushes new stuff into his repository? Bad things happen, is what.

The obvious solution is the one Git uses: if you're going to receive pushes, eliminate the work-tree. Now there's nowhere to put in-progress work, so there is never anything that gets overwritten. That's what a --bare repository is: it eliminates the work-tree, so that there's no place to do work, so it can't be abruptly overwritten by someone else.

There are a number of ways to compromise, but like most compromises, they tend to have various problems. The bare repository can receive pushes to take commits in, and can accept fetch connection requests to send commits out, and the ony thing that gets overwritten by a push request is the bare repository's idea of which commit any particular branch name means—ideally, in a "fast forward" manner so that this merely adds new commits to the set of commits reachable from the name. (Remember that in Git, a branch name is just a moveable pointer to one specific commit. See also What exactly do we mean by "branch"?)

torek
  • 448,244
  • 59
  • 642
  • 775
  • You said that a non-bare repository stores that stuff and that a bare repository stores no working-tree: since a Git server is set up with a bare repo, is not my point still valid? __No code on a Git server, it just sends commits to some production server__ – elmazzun Feb 08 '18 at 09:25
  • While the bare repository has no work-tree, you can still use Git commands to extract objects from commits. These are not particularly *convenient*, but they do work. You can also run `git --work-tree= ` to temporarily (for one Git command) supply a work-tree. This is one of the compromise techniques I mentioned. But *you* must decide how to work with this. Finally, note that you can simply clone the bare repository to a *non*-bare repository on the same machine; now you have a non-bare repo with a work-tree. – torek Feb 08 '18 at 15:07
  • 1
    (It's still not at all clear to me what *you* mean by "no code". You can have whatever code you like, including code you supply as Git hooks. You just have no *work-tree*, in a bare repository.) – torek Feb 08 '18 at 15:13
  • I was just to write I found out that from a bare repository in Git server a hook can get code with `git checkout -f`. – elmazzun Feb 08 '18 at 15:16
  • Yes. Be sure you write each hook carefully, after reading and understanding (1) when it is run, (2) what input(s) it is given, (3) what effect it will have when it is run on (e.g.) a `git push --delete` operation. There are a lot of sloppy post-receive hooks that just run `git --work-tree= checkout -f` (with or without additional arguments) that cause people surprises later. – torek Feb 08 '18 at 15:20
  • After Basic Branching and Git on a Server, I should get used to `--work-tree` because I still don't get it. With that knowledge, I can start designing our Git server with a planned Git workflow. – elmazzun Feb 08 '18 at 15:33