2

I am receiving the "[remote rejected] master branch is currently checked out" error - essentially the same problem as the OP at this post (Git push error '[remote rejected] master -> master (branch is currently checked out)'), and following is what I have done so far to fix it, but now it seems I have a choice between having the above-stated problem or a new one - the "missing work-tree" error, and as explained below, this is where I am currently stuck.

Please also note that I have a different requirement than the other question. I do NOT want two repos, one bare and one non-bare - just the single repo (origin/remote), from which the local machines will be pulling/pushing code - and which is a live web server. The other post did not specify any requirement along these lines (and this option was not addressed there), but my needs are very specific, hence this question.

Also note that it is unavoidable that sometimes there may be direct edits to this directory's files on the server (albeit still using Git), rather than being pushed from a local workstation to the server (remote).

First I reset the repo, setting it to to bare (the developer who originally set Git up on the server only used the git init command when he set up the repo):

    git init --bare    

Then, because all my server files were already present (it is not an empty directory), I did an initial commit, by this method (the usual):

    git add .
    git commit -m "initial commit"

Then I edited the .git/config file thusly:

    git config receive.denyCurrentBranch ignore    

My current server .git/config file looks like this:

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

[receive]
        denyCurrentBranch = false

I am able to push commits successfully, BUT if I try to then apply this:

    git checkout -f

as suggested above (presumably to accept all the commits and reset the HEAD to include all my changes?), I receive the following fatal error:

    fatal: This operation must be run in a work tree

Do I need to set the worktree to this directory? If so, how do I do that? And if I do that, will the result still be in keeping with my stated goal (again, no separate bare and non-bare repos - just the single directory, which is ALSO serving a live web site and is located in the web root)?

Is there anything else I need to do that I am missing?

I have read widely on stackoverflow on this topic, including: Git init --bare - Not Working on working tree fatal: This operation must be run in a work tree Difference between HEAD / Working Tree / Index in Git The Pro-Git book (esp here: http://git-scm.com/book/ch2-2.html) Git-Flow (nvie): http://nvie.com/posts/a-successful-git-branching-model/

All help and comments greatly appreciated. Thank you!

Community
  • 1
  • 1
Kelly Bell
  • 31
  • 1
  • 7
  • I think you're referring to another question. Can you post the link to that question ? Without that it is not quite clear what you're trying to achieve. – Tuxdude Mar 27 '13 at 18:34
  • I added the original post reference to my question above, but here it is again, just in case: http://stackoverflow.com/questions/2816369/git-push-error-remote-rejected-master-master-branch-is-currently-checked/15630603#15630603 – Kelly Bell Mar 27 '13 at 18:47
  • And to clarify, all the other answers I have found here are always about using two separate branches (one checked out and another not checked out, for example), which CANNOT be my case (I have no control over this part of the situation - we MUST be able to push directly into the files being served by the server). – Kelly Bell Mar 27 '13 at 18:50
  • I think what I may be missing is a hook that copies our latest commits to the working directory... am I on the right track? – Kelly Bell Mar 27 '13 at 19:13
  • Look at my answer, yes you're right you missed out the post-receive hook and you need to separate the bare git repo and the work-tree. – Tuxdude Mar 27 '13 at 19:18
  • But that's the essence of my question - I want to do this WITHOUT separating into bare and non-bare branches. I want them to be the same directory. In the other post I saw a reliable response which stated that it is NOT required that they be separate (but the "hook" info I need was not in that answer). So I need the answer that puts the hook update with them being in the same directory, NOT separate. Am I being clear? – Kelly Bell Mar 28 '13 at 03:28
  • Also I would be grateful if someone can explain why `git reset --hard` fixes the problem (though it's not a "solution"). I need this workflow to work WITHOUT having to do any followup commands on the server. – Kelly Bell Mar 28 '13 at 03:33

1 Answers1

3

You've created a bare git repository (which does not by itself have a working tree). A bare git repository is the recommended way to go when you want to push changes.

And from your question, I understand that you have some sort of server setup, and everytime you do a git push, you want the files on the server to be updated to reflect the newly pushed changes.

Yes it is do-able, but you need to separate the bare repo and work-tree. The work-tree location should correspond to the location where your files need to be deployed on the server. Let's just assume it is /foor/bar. By setting up a post-receive hook, you can deploy the new files to this worktree location, after every push automatically.

These are the steps for this setup:

  1. Create the work-tree directory if it does not exist already.

    mkdir -p /foo/bar
    
  2. Create the following script and copy it in as bare-repo's hooks/post-receive

    #! /bin/sh
    GIT_WORK_TREE=/foo/bar git checkout -f
    
  3. Mark this script as executable:

    chmod +x hooks/post-receive
    

That's all that will be required. Now try a git push and your new changes will be automatically deployed onto /foo/bar location.

A note of caution: git checkout -f clobbers all local changes in any of the tracked files and any such changes in /foo/bar will be lost on a new checkout -f. Any files that are not tracked in git but created/generated under /foo/bar, should not be affected.

Also I would suggest to get rid of the changes you've made in the .git/config, especially for receive.denyCurrentBranch.

Your config should look like this IMO:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = true
    logallrefupdates = true
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • @KellyBell - is there a reason why that is the case ? Do you plan to work on the server's work-tree directly as well ? The reason I'm asking is, you got to choose one or the other, otherwise you would end up with the exact issue you're facing right now. – Tuxdude Mar 28 '13 at 00:30
  • Hi Tuxdude - thank you for replying! The thing is, I want the work-tree to be the SAME as the repo itself. I don't want two directories, just the one. I was trying to be specific about that, in my question above. Is there some way to make the work-tree and the bare repo the same directory? I have a human factor not under my control here, and if there are two directories present (in ftp), there is danger of direct copying instead of using git to manage the files. I am trying to lock it down so there can't be any extra directories that would allow git to be defeated. – Kelly Bell Mar 28 '13 at 00:34
  • Yes, the work-tree on the server is sometimes being edited directly by a person very new to git, and I frequently have to go back in and manage his commits, for example (he does as well; he is learning). But he belongs with the client, so I can't do more than gently suggest and do the best I can with the system itself. It's a delicate "soft-skills" problem. – Kelly Bell Mar 28 '13 at 00:37
  • So, @Tuxdude, and thank you for all your help, but I still have two unanswered questions. 1. How do I set the work tree to the SAME directory (without separating the two - I just want ONE directory on the web server)? And 2. What (in git logic terms) is the `git reset --hard` command doing such that it's (sort of) fixing my problem? – Kelly Bell Mar 28 '13 at 03:42
  • 1
    If you have not initialized the repo as a `bare` repo (i.e. bare=false), the work-tree should already be created in the repo. If not, git is not going to create a default work-tree. `git reset --hard` over-writes all local changes in the worktree and replaces all the files being tracked with the ones from the commit being pointed by `HEAD` - which will ideally be the tip of the default branch `master`. – Tuxdude Mar 28 '13 at 04:32
  • Thanks @Tuxdude. That helps me a lot. So what can I do to keep things just as they are (working fine), except WITHOUT having to execute the `git reset --hard` on the server after every push? Specifically, without having to execute ANYTHING on the server, after each push? – Kelly Bell Mar 28 '13 at 14:52
  • I would love to mark your answer as THE answer, @Tuxdude, but my basic question remains unanswered. Does anyone out there have an answer for me, to the above? **So what can I do to keep things just as they are (working fine), except WITHOUT having to execute the git reset --hard on the server after every push? Specifically, without having to execute ANYTHING on the server, after each push?** – Kelly Bell Apr 05 '13 at 09:30