12

Much like this SO post, I have the following workflow that i would like to maintain with git:

  1. Multiple people develop locally
  2. Commit a few things
  3. Commit more things
  4. Push to Staging
  5. Test new code on Staging
  6. Push to Production

Our staging server serves many different sites. I would like to set up the repository for each in a different folder in a user's home directory. Each repository will have a post-receive hook (ala the Daniel Messier article) that checks out the changes into the web root for that site/repository.

It's number six that is giving me trouble.

When I try to run any git commands, I get the error "fatal: This operation must be run in a work tree". I get this error whether I am running 'git status' from the repository (/home/gituser/website1.git - which I don't believe should work anyway..) or from the web root (/var/www/website1).

However, if I specify the GIT_DIR and GIT_WORK_TREE, then I am able to run git commands. Both of these work:

$ git --git-dir /home/gituser/website1.git --work-tree /var/www/website1 status
$ GIT_DIR=/home/gituser/website1.git GIT_WORK_TREE=/var/www/website1 git status 

So I need:

  1. An alternative to typing the directory and work tree along with every command
  2. An alternative to setting them as persistent environment variables, because that would only work for website1, not website2, website3, etc

Am I going about this correctly? How can I get git the directory info it needs for each repository?

Community
  • 1
  • 1
doub1ejack
  • 10,627
  • 20
  • 66
  • 125

4 Answers4

18

If I understand correctly, you've got a different repository for each web root. If that's the case, you can set the work tree at the repository level (in the .git/config file): core.worktree. It won't work if the repo is configured as bare:

[core]
    bare = false
    worktree = /webroot/dir/for/this/repo

Once that's set, Git commands (like git status) should work from the repository folder again, and any commands that use the work tree (git status, git checkout, etc.) will use the core.worktree location. (Note that Git commands still won't work from the work tree location, because it's not a repository.)

ellotheth
  • 4,333
  • 2
  • 17
  • 29
4

Just a suggestion.

Implement a script file called "git" that is placed in a directory that preceeds the user's path before the git executable in /usr/bin. git, the shell script, is just a thin wrapper on top of /usr/bin/git. The first thing it does is detect what directory git is being called from and tries to auto-infer what repo it is working in. Perhaps by having a "my.config" file in the root of each repository that the script can read. Then the script calls "/usr/bin/git --git-dir" and sets GIT_DIR and GIT_WORK_TREE vars and then calls /usr/bin/git with the same command line params.

selbie
  • 100,020
  • 15
  • 103
  • 173
2

Three options:

1) Add a local alias:

$ git config alias.root '!pwd'

2) Add a global alias ($HOME/.gitconfig):

[alias]
 findroot = "!f () { [[ -d ".git" ]] && echo "Found git in [`pwd`]" && exit 0; cd .. && echo "IN `pwd`" && f;}; f"

3) A script, findgitroot.sh e.g

#!/bin/sh
f () { [[ -d ".git" ]] && echo "Found git in [`pwd`]" && exit 0; cd .. && f;}
f
FractalSpace
  • 5,577
  • 3
  • 42
  • 47
  • Sorry to be a total idiot here -- option 1, is that a snippet for .bash_profile or git config? Thanks again for providing some examples for this problem. – Rustavore Jan 10 '13 at 03:21
  • 1
    Option 1 will be for git config. However, since then, I have found many other better options: 3) git config alias.root '!pwd' (this will give you 'git root' command with desired results) 4) git rev-parse --show-toplevel – FractalSpace Jan 12 '13 at 17:44
  • Thanks! So for 3), you'd use `git root commit -am "Commit Msg"` instead of `git commit -am "Commit Msg"`. – Rustavore Jan 14 '13 at 05:14
  • Umm. no. You will use this new alias to just find where the root directly is, like this: '$ git root' or 'cd `git root` etc. – FractalSpace Jan 16 '13 at 20:13
1

You can always press up arrow to get all that info and then just delete the command and replace with another one. You shouldn't need to retype the whole thing.

If you've issued a number of other commands and don't want to "up arrow" through history too much, you can press CTRL-R and start typing "tree" or "work". You should get the point in history where one of these was run.

Otherwise, script setting those variables as already suggested.

Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141