Git
file permissions
directory permissions
restore permissions
version control

How can I restore the permissions of files and directories within Git if they have been modified?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Permission drift in a Git repository is confusing because Git tracks only limited mode information. For normal files, Git mainly stores executable-bit changes, while directory permissions are managed by the filesystem and not fully versioned. Restoring permissions correctly requires combining Git commands with OS-level normalization.

What Git Tracks and What It Does Not

Git mode tracking for common file types is narrow:

  • regular non-executable file mode
  • regular executable file mode
  • symlink mode

Git does not preserve detailed directory permission bits in commit history. That means directory mode restoration cannot come from git checkout or git restore alone.

Restore Tracked File Modes from Commit

For tracked files, restore content and executable-bit state from HEAD.

bash
git restore path/to/file

To restore all tracked files in working tree:

bash
git restore .

Legacy equivalent:

bash
git checkout -- path/to/file

These commands are safe first steps when accidental mode changes are mixed with content edits.

Inspect Permission Changes Explicitly

Before and after restoration, inspect mode-only changes.

bash
git diff --summary
git diff --cached --summary

Look for mode transitions such as 100644 and 100755. This isolates executable-bit drift without scanning full file diffs.

Set Executable Policy Intentionally

If certain scripts must remain executable, enforce that state in Git index.

bash
git update-index --chmod=+x scripts/deploy.sh
git update-index --chmod=+x scripts/release.sh
git update-index --chmod=-x docs/readme.txt

Then commit the normalization so future clones inherit expected executable flags.

Normalize Directory Permissions with OS Tools

Because Git does not track directory permission bits, use filesystem commands to reset directories and files.

bash
find . -type d -exec chmod 755 {} +
find . -type f -exec chmod 644 {} +

After broad normalization, reapply executable bits for known scripts:

bash
chmod +x scripts/deploy.sh
chmod +x scripts/release.sh

Always review mode summary before committing.

Practical End-to-End Cleanup Workflow

A repeatable sequence helps avoid mistakes:

bash
1git diff --summary
2git restore .
3find . -type d -exec chmod 755 {} +
4find . -type f -exec chmod 644 {} +
5chmod +x scripts/deploy.sh scripts/release.sh
6git add -A
7git diff --cached --summary

This separates Git-tracked mode restoration from filesystem-wide normalization.

Cross-Platform Considerations

On some systems, especially Windows environments, mode behavior may differ depending on filesystem and Git settings. Check:

bash
git config core.fileMode

If set to false, Git may ignore local mode changes. That can reduce noise locally but may hide executable-bit drift that matters for Linux deploy targets.

Team Practices to Prevent Repeat Drift

Preventive policy reduces repeated cleanup work:

  1. document which files must be executable
  2. avoid blanket chmod at repository root unless planned
  3. review mode-only diffs in pull requests
  4. add CI guard for unexpected mode changes

Example CI guard:

bash
1if git diff --summary origin/main...HEAD | grep -q 'mode change'; then
2  echo "Unexpected mode changes detected"
3  exit 1
4fi

This gives early feedback before mode churn reaches release branches.

Recovery from Mistakes

If you accidentally committed unwanted mode changes, you can still recover by creating a follow-up normalization commit. For shared branches, avoid rewriting history unless team policy allows it.

For local accidental changes, stash or backup branch before bulk permission commands to keep a safe rollback point.

Common Pitfalls

  • Expecting Git to restore detailed directory permission bits from history.
  • Running broad chmod commands and forgetting to reapply executable scripts.
  • Committing permission noise without checking git diff --summary.
  • Using inconsistent executable policy across teams and platforms.
  • Assuming core.fileMode behavior is identical in all environments.

Summary

  • Git mainly tracks executable-bit state for files, not full permission metadata.
  • Use git restore for tracked file-mode restoration.
  • Use git update-index --chmod to enforce executable policy explicitly.
  • Normalize directory permissions with filesystem tools when needed.
  • Add team conventions and CI checks to prevent recurring permission drift.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions