0

I have a bare git repository on a server that is used as a central repository. I have installed a post-receive hook so that when a commit is pushed to this repository, the committed changes are deployed to a working directory on the same server with the following command:

git --git-dir=path-to-repository --work-tree=path-to-working-directory checkout -f

I realize that by setting the GIT_DIR and GIT_WORK_TREE environment variables as in the post-receive hook, I can also issue arbitrary Git commands from the command line. I am not suggesting that it is good development practice to modify files and commit the changes from this working directory, especially if this is my production environment, but am I doing anything illegal from a Git point of view?

Booboo
  • 38,656
  • 3
  • 37
  • 60

1 Answers1

1

... but am I doing anything illegal from a Git point of view?

No. It is, however, important to recognize a few things about this slightly odd state.

  1. Git has just one repository, and --git-dir tells it where to find that one repository.

  2. Git has just one work-tree,1 and --work-tree tells it where to find that one work-tree (and overrides the core.bare setting).

  3. Git has just one HEAD (but see footnote 1), and --git-dir tells it where to find that one HEAD file.

  4. Git has just one index,2 and ... --git-dir tells it where to find that one index, if not overridden by an environment variable setting.

It's these last bits that trip people up, mainly when using post-receive scripts to deploy some particular branches.

If you only deploy one branch to one work-tree, the one index is not a problem. If you start deploying two or more branches to two work-trees, the one index becomes a problem.

Similarly, the single HEAD file is usually not an issue, especially if you deploy only branch master when the bare repository was created in the usual way, with master as its current branch. (A bare repository still has a current branch, which is the one in its HEAD file.) When people clone the bare repository, their clones default to checking out whichever branch is current in the bare repository—so if you start deploying several different branches, people can get surprised by their clones starting out in repository QA or test or develop or whatever, instead of master.

(The HEAD thing just requires that people be aware that their default clone branch might surprise them, and they should check out the development branch if that's what they want. It's the single index file that causes real trouble, so see footnote 1.)


1If you use git worktree add, available in Git 2.5 and later, this is no longer true. The extra work-trees of course provide their own work-tree, but also provide their own separate HEAD, and also their own index.

You can provide your own index using the environment variable GIT_INDEX_FILE, which always overrides Git's normal calculations. This also provides a way to do multiple branch deployments: let one branch use the default index, and give the rest their own index file (one each).

Using multiple worktrees and the new updateInstead mode for push.denyCurrentBranch may be a better way to automate deployments, but I have not actually tested this.

2Recent versions of Git have introduced a "split index", in which very large index files are "split" into the parts that don't change much, and the parts that do, in an effort to make Git faster. The index splitting is slightly magic (though obviously deterministic and predictable in the end) and knows how to deal with alternate index files, so you don't really need to know anything about this, but it makes the "one index file" claim a bit suspect. In any case, added worktrees from git worktree add still get their own index file (or index-pair), since this is necessary.

torek
  • 448,244
  • 59
  • 642
  • 775