2

Question: How do I push my local commits to my development server if that worktree is not bare?

My Situation:

  1. I set up git on my development server so that when I push local changes, they are added to a detached working tree (as described here and much like this post).
  2. I then experienced problems running git on the dev server (eg, git status) because git could not find the working tree.
  3. I asked around SO and got the tip off that I needed to set bare = false in my config file and specify the worktree. Sweet.

But now when I try to push my commits to the dev server I get this error:

$ git push origin master
xxxx@xxx.xxx.xxx.xxx's password:
Counting objects: 26, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (18/18), done.
Writing objects: 100% (18/18), 2.56 KiB, done.
Total 18 (delta 8), reused 0 (delta 0)

remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.

To ssh://xxxx@xxx.xxx.xxx.xxx/xxx/xxx/xxxxxx.git
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'ssh://xxxx@xxx.xxx.xxx.xxx/xxx/xxx/xxxxxx.git'

I see that this other user had the same problem. Unfortunately, the solution that worked for him was setting bare = true in his config, which would recreate the problem I was having in step 3 above.

The error message says

You can set 'receive.denyCurrentBranch' configuration variable to remote: error: 'ignore' or 'warn'

In my case, is it ok for me to do this? It sounds good to me, but I'm not familiar enough with git yet to recognize a bad idea when it comes around...

EDIT

Just to be clear, I have already added a post-receive hook and it's working smoothly. The problem is that I seem to have to choose between bare=true (and being able to push to the dev server) and bare=false (and being able to run git commands on the dev server).

Community
  • 1
  • 1
doub1ejack
  • 9,047
  • 15
  • 60
  • 110

4 Answers4

3

Why not:

  • pushing your commits to a bare repo
  • setting a post-receive hook on that dev repo which will then go to the non-bare dev repo and checkout the right branch, pulling the new commits from the bare repo?

That is what your link describes (with the detached working tree), but it sets the hook in a bare repo:

$ mkdir /var/www/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/var/www/www.example.org git checkout -f
$ chmod +x hooks/post-receive
VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
  • I have done this and it works pretty nicely. The problem is that I need to be able to log into this development server and (when it is in a stable position) use git to push the dev files up to a staging server where the client can see them. Like that 3rd bullet point said, I wasn't able to run any git commands on the dev server until I set bare=false. Thus my catch22. Any thoughts? – doub1ejack Jun 05 '12 at 19:59
  • @doub1ejack what if your post-receive hook would also, according a custom criteria, push to your staging repo (from the *bare* 'dev' repo)? – VonC Jun 05 '12 at 20:53
  • That might be a good option. I'm not sure what my options are in creating 'custom criteria' to initiate the push to staging though. Would this approach *require* a push from the localhost? Ideally, we wouldn't push from dev to staging until dev has been tested and is stable. And at that point we don't really want to push changes, we want to move a snapshot of that code to staging. – doub1ejack Jun 06 '12 at 13:35
0

Working with repositories is not what you want to do. You need a post-receive hook in the bare repository on your dev server that does a git checkout-index to your web server's directory. That way, it's just files. You don't have to worry about whether it's a bare repository, has a working tree, or anything else git-related.

Something like git checkout-index -f -a --prefix=/var/www/htdocs/mywebsite/ (note the trailing slash - it is important)

The -f flag will force an overwrite of any existing files and the -a flag will include all files.

wadesworld
  • 12,653
  • 12
  • 55
  • 90
0

You just need to be careful about what you are trying to do.

git status is used for telling you the status of your working tree. This should not be useful in your case.

On the other had, git push is perfectly valid on a bare repository. This should just work for you.

If you are wanting to look at changes, you can with git diff. You just need to specify both hashes git diff $oldref $newref

If you want to list the files changed in a specific commit use git show --pretty="format:" --name-only $newref.

If you want to list the contents of a file use git show $newref -- $filepath

Bevan
  • 1
  • Good points, thank you. Being relatively new to git, I thought I could use `git status` as a test to see if git was 'working', but obviously that's overly simplistic. – doub1ejack Jul 13 '12 at 14:06
0

I've worked out a solution that is acceptable, but not quite ideal. Basically, I am just circumventing the problem by editing my config file when I need to push dev changes to my live server.

Config file which allows developers to push local changes to dev:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = true

Config file when pushing dev changes to live:

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        worktree = /var/www/example.com/httpd/

Pros

  1. Works
  2. Once I have changed the config file to push to live, the repo is 'locked' and other developers cannot push changes
  3. Not a huge problem since I have to login to dev to handle database migration anyway

Cons: basically just that it's work that I'm sure could be automated, if I knew how to do it correctly.

Note: I like @vonC's suggestion of setting up the post-recieve hook to conditionally also push to the live server. Making the changes to the post-recieve hook is simple enough, but I do not understand what the trigger would be that the hook would respond to. I'd love to hear suggestions though : )

doub1ejack
  • 9,047
  • 15
  • 60
  • 110
  • Really? This is 1 year old now. I bet you've finally setup the bare repo. Probably should accept VonC's answer instead! :P – cregox Jul 11 '13 at 14:44