问题
Question: How do I push my local commits to my development server if that worktree is not bare?
My Situation:
- 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).
- I then experienced problems running git on the dev server (eg,
git status
) because git could not find the working tree. - 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).
回答1:
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
回答2:
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.
回答3:
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
回答4:
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
- Works
- Once I have changed the config file to push to live, the repo is 'locked' and other developers cannot push changes
- 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 : )
来源:https://stackoverflow.com/questions/10902551/managing-website-using-git-post-receive-hook-error-pushing-changes