Git is changing my file's permissions when I push to server

23,092

Solution 1

This thread post offers a very good explanation:

This is by design. While the git data structure can technically store unix mode bits in its trees, it was found early on in git's history that respecting anything beyond a simple executable bit ended up being more cumbersome for git's normal use cases (i.e., people storing code or other shared files in a repository).

We could add in a config option to respect file modes, but it has generally been seen as not worthwhile. It solves only a part of the general metadata problem, as it omits owner and group names or ids, as well as extended metadata like ACLs.

If modes are important to you, the suggested fixes are one of:

  1. Use a tool like "metastore" that can be called from git hooks, and will save and restore file permissions in a file that is tracked in the repository. Do note that when using such a tool there is a race condition in protecting files (i.e., git will create your file as 644, and then metastore will correct it to 600; in the meantime, somebody could read your file).

  2. Depending on exactly what you're storing, it may make sense to keep your repository in another directory, protected by permissions, and then use a separate tool to deploy your files from the repository to their ultimate location (e.g., a Makefile or other install tool).

Solution 2

To extend the comment of @ThomasReggi that serves as a solution to the problem of changing permissions when deploying through git, I leave my implemented solution. You can add a command in the hooks / post-receive file (or whatever hook you are using)

Before the line with the git command --work-tree = (line that performs the deploy) Add some "echo" and the display of the current umask, the setting to the umask necessary to perform the deployment correctly and again the display of the current umask to confirm the change. (This way it can be seen (debug) when performing the deploy)

echo "Ref $ ref received. Deploying $ {BRANCH} branch to production ..."
# SHOW current uMask
echo "Current uMASK:"
umask
echo "Set uMASK to 0022"
umask 0022
echo "New uMASK seted to ..."
umask
echo "end umask conf"

# deploy
HUB_VERBOSE = 1
git --work-tree = $ TARGET --git-dir = $ GIT_DIR checkout -f

This way the umask is only changed for the current session, without affecting the rest of the ssh connections. And also the files are deployed with the necessary permissions from their creation / modification, instead of using a command after the deployment to re-set the necessary permissions, causing your application to fail during the time it takes to apply the appropriate permissions.

If your permission problem affects your php application, it seems that this problem has to do with how you run php (DSO, suPHP, suEXEC) because each of them needs different permission settings to run correctly. If you migrated from server, or changed the php handler it is problem that you will experience this problem.

Share:
23,092

Related videos on Youtube

ThomasReggi
Author by

ThomasReggi

Updated on July 15, 2022

Comments

  • ThomasReggi
    ThomasReggi almost 2 years

    I am using git to manage a website on a server.

    I have a local repository shown below

    local@workstation:myapp$ ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o ",k);print}'
    total 16
    755 drwxr-xr-x@ 18 thomas  staff   612 Jun 13 15:35 application
    755 drwxr-xr-x@ 11 thomas  staff   374 Jun 12 16:25 assets
    644 -rw-r--r--@  1 thomas  staff  6399 Jun 22 11:45 index.php
    755 drwxr-xr-x@ 10 thomas  staff   340 May 14 15:22 system
    

    I have a bare repository on the server that uses post-receive to point the repo in front of apache. Apache's public folders contents are below -not the bare repository.

    root@server:/srv/public/myapp# ls -l | awk '{k=0;for(i=0;i<=8;i++)k+=((substr($1,i+2,1)~/[rwx]/)*2^(8-i));if(k)printf("%0o ",k);print}'
    total 20
    700 drwx------ 15 root root 4096 Jun 27 11:31 application
    700 drwx------ 10 root root 4096 Jun 27 11:31 assets
    600 -rw-------  1 root root 6399 Jun 27 11:31 index.php
    700 drwx------  8 root root 4096 Jun 27 11:31 system
    

    This is causing mayhem to my code on the webserver.

    How can I fix this? I'm using gitolite if that makes any difference.

    git server config file

    [core]
            repositoryformatversion = 0
            filemode = true
            bare = true
    
    • geforce
      geforce almost 12 years
      Have you checked the umask for the user used for creating /srv/public/myapp repo? What's in the git config? Anything related with file mode changed there?
    • ThomasReggi
      ThomasReggi almost 12 years
      I've been messing with file mode and I had it working at one point, now it is true. Not sure what "the unmask" is. I have a git user that I setup with gitolite. I updated post.
    • vergenzt
      vergenzt almost 12 years
  • ThomasReggi
    ThomasReggi almost 12 years
    As it is on the web and I need persistant permissions. Can I just add a line to my post-receive hook that changes all files and folders in the working directory (not the bare repository) to the correct permissions, folders 755 and files 644.
  • vergenzt
    vergenzt almost 12 years
    If that suits your needs, then yes. The key point is that Git won't do it for you. If you want specific permissions, you'll need to do it manually.
  • Jannie Theunissen
    Jannie Theunissen about 9 years
    @ThomasReggi you could set umask 022 in your .profile script to apply 755 and 644 when new files are created, like pulling files from Git