If Git reports that a file became executable—or stopped being executable—on your Mac, first find which layer changed: the working file, the staging index, or a commit. Compare those states before changing permissions or Git configuration. Git records regular files as mode 100644 (not executable) or 100755 (executable); an isolated change between them usually points to the executable bit, not changed file contents. Git’s diff documentation

1. Check whether the change is staged

In Terminal, go to the repository and inspect its status and both diffs:

git status --short
git diff --summary
git diff --cached --summary

git diff compares the working tree with the index; git diff --cached compares the index with HEAD. Git status distinguishes these same layers, so a staged change appears separately from an unstaged one. Git status documentation

Look for output such as mode change 100644 => 100755 path/to/file. If it appears only in git diff --summary, the working file differs from the index. If it appears in git diff --cached --summary, the mode change has been staged and could be committed. If both are empty but a teammate reports a committed change, inspect history next.

2. Compare the index with the Mac file

For a tracked path, inspect the index’s recorded mode and the file’s current permissions:

git ls-files --stage -- "scripts/build.sh"
ls -l "scripts/build.sh"

Replace scripts/build.sh with the exact repository-relative path; quote it so spaces and shell characters are treated literally. In the git ls-files --stage output, the first field is the mode stored in the index: 100644 means Git does not record the file as executable, while 100755 means it does. The ls -l output shows the local permission bits; an x in a permission triplet indicates execute permission for that class of user. Git ls-files documentation and Apple’s permissions guide explain the two views.

This comparison narrows the cause. If the index says 100644, but ls -l shows execute permission, the discrepancy is in the working file (or Git is configured to ignore file-mode differences). If the index says 100755, Git has already staged or checked out an executable mode, regardless of what you intended the file to be.

3. Find the commit that introduced the mode

If the change is already in history, examine the relevant file’s commit summaries:

git log --summary -- "scripts/build.sh"

Git’s patch format prints separate old mode and new mode headers when a file’s mode changes. Review the commit where those values switch, then compare its parent and the surrounding workflow: was the file deliberately made runnable, did an editor or script change permissions, or was the repository used on another filesystem or operating system? The commit identifies when Git recorded the change; it does not prove which application or person caused it. Git diff format documentation

A mode change across several unrelated files may indicate a broad permission-setting operation or a filesystem/environment transition. Git documents that some filesystems fail to preserve executable bits, and that a repository moved between environments can encounter different file-mode behavior. Treat this as a clue to investigate, not proof of a specific cause. Git configuration documentation

4. Check Git’s file-mode setting

Check the setting and where it comes from:

git config --show-origin --get core.filemode

core.filemode controls whether Git honors executable-bit differences in the working tree. Git defaults it to true when unspecified and may probe filesystem behavior when a repository is initialized or cloned. If the command prints false, Git may ignore local executable-bit changes; that setting does not explain a mode already recorded in a commit. If it prints nothing, the setting may be unset, in which case Git’s documented default applies. Git configuration documentation

Avoid setting this option to false just to hide one surprising diff. First confirm whether the repository is on a filesystem or shared setup that does not reliably preserve executable bits, and whether collaborators rely on mode tracking. Changing the setting changes Git’s handling of mode differences; it does not repair a wrongly recorded mode in the index or commit.

5. Repair only after identifying the intended mode

If the file should not be executable and the change is unstaged, restore the local permission with chmod:

chmod a-x "scripts/build.sh"
git diff --summary

If the intended mode is executable, use chmod a+x "scripts/build.sh" instead. On macOS, chmod changes the specified item’s permissions; choose the intended mode based on the file’s role and repository convention, not simply to make the diff disappear. Apple’s permissions guide

If an incorrect mode is staged, set the intended local permission, then stage that path again and review the staged summary:

chmod a-x "scripts/build.sh"
git add -- "scripts/build.sh"
git diff --cached --summary

Use a+x in place of a-x when the file should be executable. If the mode is wrong in an existing commit, a new corrective commit is generally clearer than rewriting shared history; coordinate before rewriting commits others may already use. In every case, inspect git diff and git diff --cached afterward so you do not overlook content edits alongside the permission change.

Sources