Git: Restore file permissions
Git complains that files are changed, even if only the permissions are changed
Published on
Having a Git repository where some of the files have permissions changes, a git checkout may not be the solution if other changes have been made.
#!/bin/bash
# The script should run from the root of the Git repository
cd "$(git rev-parse --show-toplevel)" || exit 1
git diff --name-only --diff-filter=M -z |
while IFS= read -r -d '' file; do
oldmode=$(git ls-tree HEAD -- "$file" | awk '{print $1}')
# Safety check: skip the file if it is NOT in HEAD, or the output is empty
if [ -z "$oldmode" ]; then
continue
fi
# Process only regular files (those starting with 100)
if [[ "$oldmode" =~ ^100 ]]; then
# Extract the last 3 octal digits (the actual permissions, e.g., 644)
clean_mode="${oldmode:3}"
chmod "$clean_mode" "$file"
else
# display skipped file (symlinks, submodules, etc.)
echo "Skipped (not a regular file): $file (Mode: $oldmode)"
fi
done
maybe not the best (it calls git ls-tree HEAD for every file) but it handles spaces, tabs, backslashes and any valid Git filename. Also, this version does not parse human-readable output.
Built by me and ChatGPT. Improved by me with shellcheck and Gemini.