Search code examples
gitwebsite-deployment

git checkout -f results in modified, unstaged files


For my website I have a bare repository (where I push to) and a clone with working directory which serves as document root.

In the bare repository I've setup a post-receive hook to auto-update the website:

#!/bin/sh
WEB_DIR=/var/www/www.mysite.com

# remove any untracked files and directories
git --work-tree=${WEB_DIR} clean -fd

# force checkout of the latest deploy
git --work-tree=${WEB_DIR} checkout --force

Unfortunately, after a push to the bare repository the changes do show up in the documentroot, but as but they show as unstaged changes. I then have to clean everything up by doing a git checkout -- <files> followed by a git pull.

Obviously the idea is that this works out of the box, if I have to do the cleanup+pull manually I might as well remove the post-receive hook.

I read it's better to use checkout in the post receive than a pull in various locations so I don't know if that would be a good change...

I'm not a git expert so I'm hoping someone can tell me what I'm missing? The solution does seem to work for a lot of people as I've found it in several tutorials out there.


Solution

  • That's confusing

    So right now what you've got is (e.g.):

    /repos
        /mysite
            /.git 
                ...
    /var
        /www
            /www.mysite.com
                /.git
                    ...
                index.htm
                ...
    

    Nothing strange there. However the hook in use is mis-matching things leaving the working copy's git repository out of sync with the checked-out files:

    /repos
        /mysite
            /.git <- This git dir
                ...
    /var
        /www
            /www.mysite.com <- This working copy
                index.htm
                ...
    

    The git directory for the working copy is ignored. That makes things quite confusing - the working copy files are checked out to match the bare repository's state ignoring whatever is the working copy's own git info.

    Make it simple

    Instead of that do something like the following:

    #!/bin/sh
    # see http://serverfault.com/q/107608/108287
    # for why you can't just run git pull with no arguments
    
    WEB_DIR=/var/www/www.mysite.com
    
    cd $WEB_DIR
    
    # Remove the comments after verifying that it works to reduce noise
    git --git-dir $WEB_DIR/.git fetch # > /dev/null
    git --git-dir $WEB_DIR/.git checkout --force # > /dev/null
    git --git-dir $WEB_DIR/.git clean -fd # > /dev/null
    

    I.e. push to the bare repository and then simulate exactly what you'd do manually, change directory pull and clean. That will update the working copy's files and git repository such that things are in sync.