As a version control system designed for source code, Git provides specialized support for tracking and modifying file permissions. This allows collaborating developers to maintain the correct modes for security, script execution, logs, and more.

In this comprehensive guide, we will cover how Git handles permissions, best practices for repository files, advanced access options, and methods for checking and changing modes across platforms.

Understanding Unix File Permissions

Git repositories typically contain scripts, configurations, log files and other artifacts common in Linux/Unix environments. These operating systems represent file access using a simple yet flexible octal notation. Each digit defines the read, write, and execute permissions for the file owner, group members, and all other users.

Octal Permission Modes

Some common octal permission modes are:

700 - (rwx------) Owner has full access, others can‘t access  
755 - (rwxr-xr-x) Owner has full access, others can read and execute
644 - (rw-r--r--) Owner can modify, others have read-only access 
777 - (rwxrwxrwx) All users have full access

Setting scripts to 755 allows anyone to run them while protecting modification rights. Log files at 644 let multiple services append without overwriting. Strict 700 permissions on configuration files prevent tampering.

setuid, setgid, and Sticky Bits

The leftmost digit has three special permission settings:

4000 - (rwsrwsrwx) Set user ID on execution 
2000 - (rwxrwsrwx) Set group ID on execution
1000 - (rwxrxtrwx) Sticky bit

The setuid and setgid bits cause scripts/programs to execute as the owner and group respectively giving them enhanced permissions. This allows editors like vim to access restricted files.

Sticky bits protect directories like /tmp preventing file deletion except by the owner.

Access Control Lists (ACLs)

Permissions can be further customized using ACLs which define access rules for specific users and groups rather than broader categories. However ACLs are not tracked by Git directly and must be set independently per environment.

Enabling Git File Mode Tracking

By default Git tracks file contents but not permissions. To enable mode tracking include:

git config core.fileMode true

in the repository, user, global or system config. Now Git will record execute bits and other changes in commits allowing proper restoration on clone and checkout.

Tracking applies to all files in the repo root and sub directories. Additional configuration may be required for more complex scenarios like submodules.

Best Practices for Repository Permissions

Deciding appropriate file permissions for a repository depends on the types of files and collaboration approaches. Here are some common patterns:

Script Files (.sh, .py, etc)

Scripts should generally have 755 or even 777 permissions if needed for universal execution:

#!/bin/sh
# Helper script for build process 

echo "Building..."

However scripts dealing with sensitive information may warrant stricter 700 or 640 modes.

Configuration Files

App and system configurations often contain passwords, API keys and other secrets. These should use 600 or 640 protections:

# database.yml

database:
   username: appuser
   password: topsecret

Allowing modifications risks credentials leakage or service disruption.

Log Files

Log files require write access from related processes. Use 644 for simple cases:

# app.log 

WARNING Generated alarming report 
ERROR Out of memory during analysis

Or make a logging group and set 666 group-writeable permissions. Just ensure log files stay private.

User Content

Repositories also frequently contain user data like attachments and documents. Set 444 read-only or 555 if previewing is required. The principle of least privilege should apply.

Checking Permissions on Linux

On Linux systems, we can inspect permissions visually or via the command line.

ls -l Listing

Use ls -l for a persona friendly view including ownership:

$ ls -l
-rwxrwxr-x  1. john  dev      2990 Feb 12 09:51 build.sh*
-rw-r--r--  1. mary  analyst  1894 Feb 8 11:23 data.csv
drwxr-xr-x  2. bob   finance     0 Feb 2 16:04 reports/

The first character indicates file type, then a 10 character mode string, counts and owners.

stat Command

The stat tool provides exact permissions without other metadata:

$ stat -c %A build.sh
-rwxrwxr-x

Use %a for numeric and %A for symbolic formats.

find -perm

We can also search for specific permission sets across the whole filesystem or directory tree:

$ find . -perm 755 -type f -print
./build.sh
./scripts/deploy.sh 

Very useful for auditing and aligning modes.

Modifying Permissions on Linux

Linux provides the venerable chmod and chown commands for modifying file permissions and ownership.

chmod

Use chmod to set permission modes:

$ chmod 600 secret.txt
$ chmod 755 build.sh
$ chmod -R 444 docs/

This can accept either numeric or symbolic formats. Enable/disable execute bits with +x and -x respectively.

chown

Change file ownership with chown:

$ chown john:dev build.sh 
$ chown :admins secret.txt

Give user, group or both. Useful when transitioning teams or contractors.

umask

umask globally masks permissions by default which can help enforce conventions for new files without changing existing modes.

Checking Permissions on MacOS

MacOS features a BSD style permission scheme very similar to Linux. Top level commands like ls and chmod work the same while some utilities have slight naming differences:

$ ls -le
-rwxrwxr-x  1 john  staff  2990 Feb 12 09:51 build.sh*
$ stat -f%A build.sh 
-rwxrwxr-x

Here we use ls -le for long listing and stat -f%A for permissions string. Ownership maps local users and groups.

Checking Permissions on Windows

Windows manages read-only attributes with file properties rather than distinct user/group/world permissions. Standard Git installations also run with Linux style modes internally.

Use Get-Acl in PowerShell to inspect permissions:

> Get-Acl file.txt | Format-List

Owner             : GIT_PROJECT\John
Access            : Git_Project-Operations
                  : FileSystemRights  : Modify, Synchronize
...

Modifications may require uninstalling/reinstalling Git or tweaking workspace config. Set all files read-only initially unless write access is required globally.

Using Git to Modify File Permissions

Once file tracking is enabled, Git can view and change permissions right from the repository. This helps distribute and retain correct modes across all copies.

Viewing Permission Modes

Use git ls-files with –stage to see indexed permissions:

$ git ls-files --stage
100644 c203acd README
100755 a2dc7f3 script.sh
100640 8ab687c database.yml

See exactly which files differ from default modes. Great baseline for evaluating changes.

Changing Specific File Modes

We can update modes for individual files with git update-index:

$ git update-index --chmod=755 script.sh 
$ git update-index --chmod=-x script.sh

Supports numeric, octal or symbolic formats. Relative changes work well like +x rather than full 775 value.

Committing Permission Changes

Once satisfied, commit the permission shifts alongside content changes:

$ git commit -m "Fix script permissions"
[master 0719832] Fix script permissions
 2 files changed, 4 insertions(+), 2 deletions(-)
 mode change 100755 => 100644 script.sh

Other clones and checkouts now get corrected modes.

We can also amend previous commits if adjusting existing files:

$ git commit --amend
$ git push --force origin main

But use caution amending published history.

Reverting Incorrect Modes

If a permission change causes issues, revert it with:

$ git diff HEAD^ HEAD
$ git update-index --chmod=644 script.sh
$ git commit -m "Revert script mode" 

Or restore previous commit state:

$ git reset HEAD~1 --hard

Git permits flexible permission management even after sharing commits.

Automating Permission Management

Manually running chmod and decoding numeric modes is tedious. Automation streamlines setting conventions across environments.

Git Hooks

Client-side Git hooks like pre-commit can trigger scripts to enforce policies before allowing commits:

#!/bin/sh 

# .git/hooks/pre-commit

files=$(git diff --name-only --cached)

for f in $files; do
  if ! stat -c "%a %n" "$f" | grep "644 $f"; then 
    echo "File $f must be 644"
    exit 1;
  fi
done  

This requires all updated files have 644 modes. Server-side hooks work similarly but allow blocking pushes.

Startup Scripts

User login scripts can initialize appropriate ownership and permissions at instance startup:

#!/bin/bash

# Set deployment user ownership
chown -R appuser:appuser /opt/app

# Ensure log files are writable 
chmod -R g+w /var/log/app

Helps consistency across ephemeral systems.

Configuration Management

Tools like Ansible, Puppet and Chef define file state including modes. Simply update manifest and re-deploy rather than manual chmod commands. Provides reproducibility and compliance for server infrastructure changes.

Using Containers for Portable Permissions

Container platforms like Docker and Kubernetes provide operating system level virtualization that abstracts underlying host files modes. This allows builds using consistent images that encapsulate needed permissions.

A Dockerfile may specify permissions explicitly:

FROM ubuntu:22.04

COPY script.sh /app/script.sh  
RUN chmod 755 /app/script.sh

USER appuser 

Or inherit defaults from the base image. Containers retain these through commits and deployments.

This simplifies permissions but requires containerization. Tradeoffs vs native compatibility must be evaluated. Network storage and datasets can also supply cross-environment file state.

Conclusion

File permissions are a keystone of Linux security models balancing access and control for multi-user environments. As one of the most prevalent tools for writing and distributing scripts, configurations and other code, Git is well positioned to assist managing modes consistently across repositories.

With core.fileMode tracking enabled, developers can use Git features for inspecting and modifying permissions while eliminating manual chmods. This expert guide covered common use cases, automation methods, and portability considerations for streamlining and scaling permissions with Git.

There are also many adjacent solutions like ACLs, containers and configuration management that intersect for complete governance. Understanding the range of options allows selectively applying the best approaches for particular repository types and team sizes while supporting vital security and operational safeguards.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *