Jak przywrócić uprawnienia do plików i katalogów w git, jeśli zostały zmodyfikowane?

278

Mam kasę. Wszystkie uprawnienia do plików różnią się od tego, co git uważa, że ​​powinny być, dlatego wszystkie są wyświetlane jako zmodyfikowane.

Bez dotykania zawartości plików (po prostu chcę zmodyfikować uprawnienia) jak ustawić wszystkie uprawnienia do plików według tego, co według gita powinny być?

Dale Forester
źródło

Odpowiedzi:

572

Git śledzi uprawnienia do plików i ujawnia zmiany uprawnień podczas tworzenia łatek przy użyciu git diff -p. Wszystko czego potrzebujemy to:

  1. utwórz odwrotną łatkę
  2. uwzględnij tylko zmiany uprawnień
  3. zastosuj łatkę do naszej kopii roboczej

Jako jedna linijka:

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

możesz również dodać go jako alias do konfiguracji git ...

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'

... i możesz je wywołać za pomocą:

git permission-reset

Uwaga: jeśli używasz powłoki bash, upewnij się, że używasz 'zamiast "cudzysłowów wokół !git, w przeciwnym razie zostanie zastąpione ostatnim gituruchomionym poleceniem.

Dzięki @Mixologic za wskazanie, że po prostu używając -Ron git diff, kłopotliwe sedpolecenie nie jest już wymagane.

muhqu
źródło
3
Jestem w OS X, to nie działa. Stwierdziłem, że problem dotyczy git. Nie stosuje zmian uprawnień do plików.
pepper_chico
15
Och, zadziałało, starałem się aplikować z katalogu innego niż katalog główny repozytorium. git Apply działa tylko tam.
pepper_chico
6
Czy jest jakiś powód, dla którego nie zrobiłbyś po prostu „git diff -p -R” zamiast robić sed, aby odwrócić?
Mixologic
6
@RobQuist moje lokalne zmiany nie zostały usunięte podczas korzystania z polecenia muhqu
logion
17
Dostajęfatal: unrecognized input
Tieme
120

Próbować git config core.fileMode false

Ze strony podręcznika git config:

core.fileMode

W przypadku wartości false różnice w wykonywalnych bitach między indeksem a kopią roboczą są ignorowane; przydatne na uszkodzonych systemach plików, takich jak FAT. Zobacz git-update-index (1) .

Domyślnie jest to prawda, z wyjątkiem tego, że git-clone (1) lub git-init (1) sondują i ustawią core.fileMode na false, jeśli to właściwe, podczas tworzenia repozytorium.

Tim Henigan
źródło
Dzięki, to właśnie skończyłem. Bardzo przyzwyczajony do cvs nie śledzących uprawnień, więc to działa.
Dale Forester
3
@shovas: Cieszę się, że to pomogło. Wystąpił podobny problem podczas udostępniania repozytoriów między Linuxem a Windows. BTW: jeśli to odpowiedziało na twoje pytanie, proszę zaznaczyć odpowiedź jako poprawną.
Tim Henigan,
Czy to możliwe, że git checkout origin/masterustawia uprawnienia do pliku przypisane do serwera do mojej lokalnej kopii roboczej? Ponieważ za każdym razem, gdy buduję V8 dla ArangoDB, uprawnienia do plików są zmieniane, tak że odmawia się dostępu do całego folderu kompilacji (nawet z podwyższonymi prawami; to znaczy Windows 7+). Przed kontynuowaniem procesu kompilacji muszę naprawić wszystkie lokalne uprawnienia do plików. Czy core.filemode falseto też można naprawić? Podejrzewam, że git ustawia uprawnienia Linuksa na moim komputerze z systemem Windows. Skrypty kompilacji mogą je po prostu zachować i zastosować te same uprawnienia do nowo utworzonych plików ...
CodeManX
Im zastanawiasz się, czy jest jakiś minusem do ustawiania filemodesię false!
kevoroid
11

Git nie przechowuje uprawnień do plików innych niż skrypty wykonywalne. Zastanów się nad użyciem czegoś takiego jak git-cache-meta, aby zapisać własność pliku i uprawnienia.

Git może przechowywać tylko dwa typy trybów: 755 (plik wykonywalny) i 644 (plik wykonywalny). Jeśli plik miał 444, git zapisałby, że ma 644.

kroger
źródło
14
Przepraszam, ale to nieprawda. Git rzeczywiście śledzi uprawnienia.
Czy
4
Jest mniej więcej dokładny, zobacz git.wiki.kernel.org/index.php/ContentLimitations . Dokładne ustawione uprawnienia wydają się być oparte na serwerze i ewentualnie kliencie, umaska także na ustawieniach konfiguracyjnych, patrz stackoverflow.com/a/12735291/125150 .
Motti Strom
12
@ Nie, nie będzie. Nie mogę uwierzyć, że twój komentarz otrzymał tak wiele pozytywnych opinii.
eis
@Will, jest to mniej więcej poprawne. Per the docs ...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

będzie działać w większości przypadków, ale jeśli masz zainstalowane zewnętrzne narzędzia porównywania, takie jak meld, musisz dodać --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

był potrzebny w mojej sytuacji

zainengineer
źródło
0

Używam git z cygwin w systemie Windows, git applyrozwiązanie nie działa dla mnie. Oto moje rozwiązanie, uruchom chmodna każdym pliku, aby zresetować uprawnienia.

#!/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

alijandro
źródło
-1

git diff -pużyte w odpowiedzi muhqua mogą nie wykazywać wszystkich rozbieżności.

  • widziałem to w Cygwin dla plików, których nie posiadałem
  • zmiany trybu są całkowicie ignorowane, jeśli core.filemodejest false(co jest domyślnym ustawieniem MSysGit)

Zamiast tego kod odczytuje metadane bezpośrednio:

(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)

Jednowarstwowy materiał nieprodukcyjny (całkowicie zastępuje maski):

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

(Kredyt za „$ '\ 0” trafia na http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html )

ivan_pozdeev
źródło
-2

Najłatwiej jest po prostu zmienić uprawnienia z powrotem. Jak zauważył @kroger, git śledzi tylko bity wykonywalne. Prawdopodobnie musisz po prostu uruchomić, chmod -x filenameaby to naprawić (lub +xjeśli to jest to potrzebne.

Pat Notz
źródło
Oto przykład z 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 nieco pogrubioną czcionką są uprawnienia do plików.
Conrado
To też wydawało mi się najłatwiejsze. Niestety napotkałem ten sam problem co Conrado - nie mogłem zmienić uprawnień z 100644na 100755. Nie sądzę, żebyś zasłużył sobie na głos; Git powinien zostać odrzucony. Jest tak zepsuty na wiele sposobów na tak różnych poziomach ...
jww
-2

etckeeperNarzędzie może obsłużyć uprawnienia oraz z:

etckeeper init -d /mydir

Możesz użyć go do innych katalogów niż /etc.

Zainstaluj za pomocą menedżera pakietów lub pobierz źródła z powyższego linku.

MoreIT
źródło
4
Do czego ustawia uprawnienia? Jeśli nie odczytuje metadanych Gita lub nie wywołuje Git, nie robi tego, czego zażądał PO.
ivan_pozdeev