12

I've used this 'tutorial' to set up a DSP environment: http://toroid.org/ams/git-website-howto (Yes, I don't have a T).

My workflow is very easy:

  1. Develop locally (D)
  2. Commit a few things
  3. Commit more things
  4. Push to Staging (and Github) (S)
  5. Test new code on Staging
  6. Push to Production (P)

My code contains CSS files that are minified by my code and then saved to 1 file: all.css. Locally, I've turned that option off, so I don't have to manually remove all.css all the time every time I change my CSS. On both Staging and Production, they should cache as soon as possible (so create all.css from the separate CSS files).

The problem is every time I push, I have to remove all.css (and all.js -- same exact story) to see the changes (and properly test).

From the tutorial I made a post-receive hook that checks out the changes into a certain folder (where Apache reads the code).

My current post-receive hook:

#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f

I want to reuse $GIT_WORK_TREE to remove two files within $GIT_WORK_TREE (being www/all.css and www/all.js), but I can't... There's no var $GIT_WORK_TREE on the next line.

So I changed it to this, but I don't like that, especially if I want to do more with it in the future:

#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
rm /var/www/www.example.org/www/all.css
rm /var/www/www.example.org/www/all.js

$GIT_WORK_TREE is NOT reused like this.

Things I've tried that don't work:

GIT_WORK_TREE=/var/www/www.example.org git checkout -f
rm $GIT_WORK_TREE/www/all.css
rm $GIT_WORK_TREE/www/all.js

rm: file doesn't exist etc (/www/all.css) ($GIT_WORK_TREE is empty)

GIT_WORK_TREE=/var/www/www.example.org
git checkout -f

fatal: this operation must be run in a work tree

GIT_WORK_TREE=/var/www/www.example.org
cd $GIT_WORK_TREE
git checkout -f

fatal: Not in a git repository (or any .....)

I guess my problem is as much with how Bash works as it is with how GIT works =)

Rudie
  • 52,220
  • 42
  • 131
  • 173

3 Answers3

27

There are a few problems with that you're trying at the moment. Perhaps it's best to explain what's wrong with each example you've tried in turn:

GIT_WORK_TREE=/var/www/www.example.org git checkout -f
rm $GIT_WORK_TREE/www/all.css
rm $GIT_WORK_TREE/www/all.js

The problem here is that if you define a variable directly before the command, the environment variable is only set in the environment of the command you're running - it's not set in the current shell. You can easily test this:

$ FOO=bar sh -c 'echo $FOO'            
bar
$ echo $FOO

$ 

Your next attempt was:

GIT_WORK_TREE=/var/www/www.example.org
git checkout -f

In this case, in order for the variable to be set in the environment of other commands you invoke in the script, you need to export it, for example with export GIT_WORK_TREE=/var/www/www.example.org instead of your first line.

Your last attempt was:

GIT_WORK_TREE=/var/www/www.example.org
cd $GIT_WORK_TREE
git checkout -f

This has the same problem as your previous attempt (i.e. that you need to export GIT_WORK_TREE) but it also has a more subtle problem. As I describe in this blog post, GIT_DIR is set to . (i.e. the current directory) in the post-receive script's environment. So, if you change directory to the top of the working tree, GIT_DIR will point to that directory, and not the .git directory! A couple of good rules of thumb are (a) that you should only set GIT_DIR and GIT_WORK_TREE together, and (b) if you do set them, you should set them both to absolute paths. So, I think the following hook will work in your case:

#!/bin/sh
export GIT_WORK_TREE=/var/www/www.example.org
export GIT_DIR=/var/www/www.example.org/.git
cd $GIT_WORK_TREE
git checkout -f
rm www/all.css
rm www/all.js
Mark Longair
  • 446,582
  • 72
  • 411
  • 327
  • Yeah, only my `GIT_DIR` isn't in my `GIT_WORK_TREE`. It's in an entirely different location. I don't think that matters though. I don't have to set `GIT_DIR`. I don't think the `cd` is necessary either. I just didn't know enough about bash to know you have to export a var (crazy!). Now I do =) I'm gonna try this. – Rudie Jul 09 '11 at 19:28
  • Works like a charm. Without the 2nd `export` and the `cd`. – Rudie Jul 09 '11 at 19:37
  • I'm glad to hear you've sorted that out. You're right, if you export `GIT_WORK_TREE` and don't `cd` then you don't need to set `GIT_DIR` either. I still maintain, however, that the best way to avoid potentially confusing edge cases is to follow the rules of thumb I mentioned above! – Mark Longair Jul 09 '11 at 19:55
7

why not use a variable for the path?

#!/bin/sh
work_tree=/var/www/www.example.org
GIT_WORK_TREE=$work_tree git checkout -f
rm $work_tree/www/all.css
rm $work_tree/www/all.js

then you don't need to export. This works perfect for me.

a1catraz
  • 71
  • 1
  • 1
  • Yeah, that's good too. Is exporting bad? What is the exporting anyway? Why is exporting unnecessary if its created on the same line as the git checkout? (I'm a bash noob.) – Rudie May 08 '12 at 21:18
1
GIT_WORK_TREE=....
export GIT_WORK_TREE
git ...
rm $GIT_WORK_TREE/...

should work and is safest (you don't always need to export your environment variables, but usually it doesn't harm :))

cdegroot
  • 1,765
  • 11
  • 12
  • 1
    So what would it be literally? I don't understand the line starting with `git ...`. I don't have a line like that. – Rudie Jul 09 '11 at 15:43