Skip to content

Instantly share code, notes, and snippets.

@jtdp
Last active January 24, 2024 08:59
Show Gist options
  • Star 72 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save jtdp/5443498 to your computer and use it in GitHub Desktop.
Save jtdp/5443498 to your computer and use it in GitHub Desktop.
Revert file permission changes in local git repository.. Very useful when you change permissions due to working on a samba share. Lifted from: http://stackoverflow.com/questions/2517339/git-how-to-recover-the-file-permissions-git-thinks-the-file-should-be
git diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply
@hadaytullah
Copy link

Thanks! appreciate the help.

@abilogos
Copy link

thanks. very helpful for me.
it just applies (revert) only file mode changes (diff|(old|new) mode).
Thanks a lot.

@RaphiStein
Copy link

Any ideas on how to filter out files that have changes in their content?
For example, I want all the files with permissions changes but not if they also have changes in their content

@bene20
Copy link

bene20 commented Mar 16, 2020

Excelent!
If you have configured an external diff tool, i recommend you to add the --no-ext-diff parameter to avoid it to open that tool a billion times:

git diff --no-ext-diff -p -R --no-color
| grep -E "^(diff|(old|new) mode)" --color=never
| git apply

@mariusvw
Copy link

mariusvw commented Jul 3, 2020

Seems to fail on deleted files, this resolve that

Command

git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E "^(diff|old mode|new mode)" | sed -e "s/^old/NEW/;s/^new/old/;s/^NEW/new/" | git apply

Git Alias

git config --global --add alias.permission-resetb '!git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E "^(diff|old mode|new mode)" | sed -e "s/^old/NEW/;s/^new/old/;s/^NEW/new/" | git apply'

@martynov-dm
Copy link

Seems to fail on deleted files, this resolve that

Command

git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E "^(diff|old mode|new mode)" | sed -e "s/^old/NEW/;s/^new/old/;s/^NEW/new/" | git apply

Git Alias

git config --global --add alias.permission-resetb '!git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E "^(diff|old mode|new mode)" | sed -e "s/^old/NEW/;s/^new/old/;s/^NEW/new/" | git apply'

Not working(

image

@neohunter
Copy link

What if it was commited and pushed? I've one commit with more than 3000 file permissions changed (mixed with real content changes). What I can do to revert the file permissions?

@neohunter
Copy link

I was able to restore permissions from a previous commit doing this:

git ls-tree -r  d3fb093 |while read mode _ _ fpath; do chmod "${mode:3}" "$fpath"; done

where d3fb093 is the last commit with the right permissions.

@BonBonSlick
Copy link

tahnks! ;)

@Goddard
Copy link

Goddard commented Sep 21, 2021

Awesome!

@pboling
Copy link

pboling commented Mar 3, 2023

If this solution does not work for you, I have found two possible causes -

  1. Your git clone is on an ExFAT formatted volume. There is no fix for this, and no commands will help. ExFAT doesn't support file permissions. You can only configure git to ignore file permissions, or reformat the drive using something more suitable.
  2. Your git clone is on a volume shared via Apple File Sharing and has an ACL at the root of the volume. If that's you, good luck, and I have no idea, but maybe this tip will send you in the right direction!

It isn't a solution, in that it doesn't change or fix file permissions, but if you are stuck with one of the above, it may ease the pain to set:

git config core.fileMode false

though using this setting is highly not recommended generally.

@cipri-tom
Copy link

@martynov-dm you should run git permission-resetb not git apply

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment