Як відновити дозволи на файли та каталоги в git, якщо вони були змінені?


278

У мене є заїдка. Усі дозволи на файли відрізняються від того, що git вважає, що має бути, тому вони відображаються як змінені.

Не торкаючись вмісту файлів (просто хочу змінити дозволи), як я можу встановити всі дозволи файлів на те, що git вважає, що вони повинні бути?


Відповіді:


572

Git відслідковує передачу файлів та викриває зміни дозволу під час створення патчів за допомогою git diff -p. Отже, все, що нам потрібно, це:

  1. створити зворотний патч
  2. включити лише зміни дозволу
  3. застосувати патч до нашої робочої копії

Як однолінійний:

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

ви також можете додати його як псевдонім до вашого git config ...

git config --global --add alias.permission-reset '!git diff -p -R --no-ext-diff --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply'

... і ви можете викликати його через:

git permission-reset

Зауважте, якщо ви маєте оболонку bash, не забудьте використати 'замість "лапок навколо !git, інакше вона буде замінена останньою gitкомандою, яку ви запустили.

Thx в @Mixologic для не вказуючи, що просто використовуючи -Rна git diff, громіздка sedкоманда більше не потрібно.


3
Я в OS X, це не працює. Я визначив проблему в застосуванні git. Він не застосовує зміни дозволів на файли.
pepper_chico

15
О, це спрацювало, я намагався застосувати з каталогу, відмінного від кореня сховища. git застосовується тільки працює там.
pepper_chico

6
Чи є якась причина, ви б просто не робили "git diff -p -R", а не робили sed, щоб зробити його зворотним?
Mixologic

6
@RobQuist мої локальні зміни не були видалені при використанні команди
muhqu

17
Я отримуюfatal: unrecognized input
Tieme

120

Спробуйте git config core.fileMode false

Із git configчоловічої сторінки:

core.fileMode

Якщо помилково, виконувані бітові відмінності між індексом та робочою копією ігноруються; корисно для зламаних файлових систем, таких як FAT. Див. Git-update-index (1) .

За замовчуванням вірно, за винятком випадків, коли git-clone (1) або git-init (1) зондує та встановить core.fileMode false, якщо це доречно, коли створено сховище.


Дякую, це я і закінчила. Дуже звичний для відеореєстраторів, які не відстежують дозволи, тому це працює.
Дейл Форестер

3
@shovas: Я радий, що це допомогло. У мене виникла подібна проблема, коли ділилися репостами між Linux та Windows. До речі: якщо це відповіло на ваше запитання, будь-ласка, позначте відповідь правильним.
Тім Геніган

Чи можливо git checkout origin/masterвстановити дозволи на файли, допущені до сервера, до моєї локальної робочої копії? Оскільки щоразу, коли я будую V8 для ArangoDB, дозволи на файли змінюються так, що доступ до всієї папки збирання (навіть із підвищеними правами; Windows 7+, що є) заборонено. Мені потрібно виправити всі дозволи локальних файлів, перш ніж я можу продовжувати процес збирання. Чи можна core.filemode falseце теж виправити? Я підозрюю, що Git встановлює дозволи на Linux на своїй машині Windows. Сценарії побудови можуть просто зберегти їх і застосувати ті ж дозволи до новостворених файлів ...
CodeManX

Їм цікаво , якщо є якийсь - або недолік установки filemodeна false!
кевороїд

11

Git не зберігає файлові дозволи, окрім виконуваних сценаріїв. Для збереження права власності на файли та дозволів рекомендується використовувати щось на зразок git-cache-meta .

Git може зберігати лише два типи режимів: 755 (виконуваний) та 644 (не виконується). Якщо ваш файл був 444 git, він зберігав би його 644.


14
Вибачте, але це неправильно. Дійсно, Git відстежує дозволи.
Буде

4
Це приблизно точно, див. Git.wiki.kernel.org/index.php/ContentLimitations . Точні дозволи, встановлені на основі сервера та, можливо, клієнта umask, а також налаштування конфігурації, див. Stackoverflow.com/a/12735291/125150 .
Мотті Стром

12
@ Ні, це не так. Не можу повірити, що ваш коментар отримав так багато відгуків.
ей

@ Добре, це приблизно правильно. За документами ...a mode of 100644, which means it’s a normal file. Other options are 100755, which means it’s an executable file; and 120000, which specifies a symbolic link. The mode is taken from normal UNIX modes but is much less flexible — these three modes are the only ones that are valid for files (blobs) in Git (although other modes are used for directories and submodules).
esmail

9
git diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply

буде працювати в більшості випадків, але якщо у вас встановлені зовнішні інструменти diff, наприклад meld, вам доведеться додати --no-ext-diff

git diff --no-ext-diff -p \
    | grep -E '^(diff|old mode|new mode)' \
    | sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
    | git apply

була потрібна в моїй ситуації



0

Я використовую git від cygwin у Windows, git applyрішення не працює для мене. Ось моє рішення, запустіть chmodкожен файл, щоб скинути його дозволи.

#!/bin/bash
IFS=$'\n'
for c in `git diff -p |sed -n '/diff --git/{N;s/diff --git//g;s/\n/ /g;s# a/.* b/##g;s/old mode //g;s/\(.*\) 100\(.*\)/chmod \2 \1/g;p}'`
do
        eval $c
done
unset IFS


-1

git diff -pвикористовуваний у відповіді Мухк може не показувати всіх розбіжностей.

  • бачив це в Cygwin для файлів, якими я не володів
  • зміни режиму повністю ігноруються, якщо core.filemodeє false(що за замовчуванням для MSysGit)

Цей код читає метадані безпосередньо:

(set -o errexit pipefail nounset;
git ls-tree HEAD -z | while read -r -d $'\0' mask type blob path
do
    if [ "$type" != "blob" ]; then continue; fi;
    case "$mask" in
    #do not touch other bits
    100644) chmod a-x "$path";;
    100755) chmod a+x "$path";;
    *) echo "invalid: $mask $type $blob\t$path" >&2; false;;
    esac
done)

Однокладова частина, що не відповідає виробництву (замінює маски повністю):

git ls-tree HEAD | perl -ne '/^10(0\d{3}) blob \S+\t(.+)$/ && { system "chmod",$1,$2 || die }'

(Кредит за "$ '\ 0" "йде на http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html )


-2

Найпростіше це просто змінити дозволи. Як @kroger відмітив, git відстежує лише виконувані біти. Тож вам, мабуть, просто потрібно запустити, chmod -x filenameщоб виправити це (або +xякщо це те, що потрібно.


Ось приклад з git show: diff --git a / OpenWatch / src / org / ale / openwatch / fb / FBUtils.java b / OpenWatch / src / org / ale / openwatch / fb / FBUtils.java index cd6fa6a..e5b0935 100644 That трохи жирним шрифтом є дозволи на файл.
Конрадо

Мені це здалося і найпростішим. На жаль, я зіткнувся з тією ж проблемою, що і з Конрадо - я не зміг змінити дозвіл 100644на 100755. Я не думаю, що ти заслуговуєш нагромадження; За Git слід голосувати. Це так розбито так багато способів на стільки різних рівнів ...
jww

-2

etckeeperІнструмент може обробляти дозволу і з:

etckeeper init -d /mydir

Ви можете використовувати його для інших брудів, ніж /etc.

Встановіть за допомогою менеджера пакунків або отримайте джерела зверху.


4
На що він встановлює дозволи? Якщо він не читає Git-метадані або не викликає Git, він не виконує те, про що вимагав ОП.
ivan_pozdeev
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.