Come ripristinare i permessi di file e directory all'interno di git se sono stati modificati?


278

Ho un controllo git. Tutti i permessi dei file sono diversi da quelli che Git pensa che dovrebbero essere, quindi vengono visualizzati come modificati.

Senza toccare il contenuto dei file (voglio solo modificare le autorizzazioni) come posso impostare tutte le autorizzazioni dei file su ciò che git pensa che dovrebbero essere?


Risposte:


572

Git tiene traccia dell'ammissione dei file ed espone le modifiche alle autorizzazioni durante la creazione di patch mediante git diff -p. Quindi tutto ciò di cui abbiamo bisogno è:

  1. creare una patch inversa
  2. includere solo le modifiche alle autorizzazioni
  3. applica la patch alla nostra copia di lavoro

Come one-liner:

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

puoi anche aggiungerlo come alias alla tua configurazione 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'

... e puoi invocarlo tramite:

git permission-reset

Nota, se la tua shell è bash, assicurati di usare al 'posto delle "virgolette !git, altrimenti verrà sostituito con l'ultimo gitcomando che hai eseguito.

Grazie a @Mixologic per aver sottolineato che semplicemente usando -Ron git diff, il sedcomando ingombrante non è più necessario.


3
Sono in OS X, questo non funziona. Ho identificato il problema è nell'applicazione git. Non applica le modifiche alle autorizzazioni dei file.
pepper_chico,

15
Oh, ha funzionato, stavo cercando di applicare da una directory diversa dalla radice del repository. git apply funziona solo lì.
pepper_chico,

6
C'è qualche ragione per cui non faresti semplicemente "git diff -p -R" invece di fare le sed per farlo invertire?
Mixologic

6
@RobQuist le mie modifiche locali non sono state rimosse quando si utilizzava il comando muhqu
logion

17
Ricevofatal: unrecognized input
Tieme il

120

Provare git config core.fileMode false

Dalla git configpagina man:

core.fileMode

Se false, le differenze di bit eseguibili tra l'indice e la copia di lavoro vengono ignorate; utile su filesystem rotti come FAT. Vedi git-update-index (1) .

Il valore predefinito è true, tranne git-clone (1) o git-init (1) esaminerà e imposterà core.fileMode su false se appropriato quando viene creato il repository.


Grazie, questo è quello che ho finito per fare. Molto usato per i cv che non tengono traccia delle autorizzazioni, quindi funziona.
Dale Forester,

3
@shovas: sono contento che questo abbia aiutato. Ho riscontrato un problema simile durante la condivisione di repository tra Linux e Windows. A proposito: se questo ha risposto alla tua domanda, ti preghiamo di contrassegnare la risposta come corretta.
Tim Henigan,

È possibile che git checkout origin/masterimposta i permessi dei file assegnati al server sulla mia copia di lavoro locale? Perché ogni volta che creo V8 per ArangoDB, i permessi dei file vengono cambiati in modo tale da negare l'accesso all'intera cartella di compilazione (anche con diritti elevati; Windows 7+). Devo correggere tutte le autorizzazioni per i file locali prima di poter continuare il processo di compilazione. Puoi core.filemode falserisolvere anche quello? Sospetto che git imposti le autorizzazioni Linux sul mio computer Windows. Gli script di build potrebbero semplicemente conservarli e applicare le stesse autorizzazioni ai file appena creati ...
CodeManX

Im chiedendo se c'è qualche aspetto negativo di impostazione filemodea false!
kevoroid il

11

Git non memorizza permessi sui file diversi dagli script eseguibili. Valuta di usare qualcosa come git-cache-meta per salvare la proprietà e le autorizzazioni dei file.

Git può memorizzare solo due tipi di modalità: 755 (eseguibile) e 644 (non eseguibile). Se il tuo file fosse 444 git lo memorizzerebbe ha 644.


14
Siamo spiacenti, ma questo non è corretto. Git, infatti, tiene traccia delle autorizzazioni.
Sarà il

4
È approssimativamente preciso, vedi git.wiki.kernel.org/index.php/ContentLimitations . Le autorizzazioni esatte che vengono impostate sembrano basate sul server e possibilmente sul client umask, nonché su un'impostazione di configurazione, vedere stackoverflow.com/a/12735291/125150 .
Motti Strom,

12
@No, no. Non riesco a credere che il tuo commento abbia ricevuto così tanti voti.
Eis,

@Will, questo è approssimativamente corretto. Secondo i documenti ...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

funzionerà nella maggior parte dei casi ma se hai strumenti diff esterni come Meld installato devi aggiungere --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

era necessario nella mia situazione



0

Uso git di cygwin su Windows, la git applysoluzione non funziona per me. Ecco la mia soluzione, esegui chmodsu ogni file per reimpostarne le autorizzazioni.

#!/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 -pusato nella risposta di muhqu potrebbe non mostrare tutte le discrepanze.

  • ho visto questo in Cygwin per i file che non possedevo
  • i cambiamenti di modalità vengono ignorati completamente se core.filemodeè false(che è l'impostazione predefinita per MSysGit)

Questo codice legge invece direttamente i metadati:

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

Un liner non di produzione (sostituisce completamente le maschere):

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

(Il credito per "$ '\ 0'" va a http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html )


-2

La cosa più semplice da fare è semplicemente ripristinare le autorizzazioni. Come notato da @kroger, git tiene traccia solo dei bit eseguibili. Quindi probabilmente hai solo bisogno di correre chmod -x filenameper risolverlo (o +xse è quello che serve.


Ecco un esempio da 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 bit in grassetto ci sono i permessi dei file.
Conrado,

Anche questo mi è sembrato più facile. Sfortunatamente, ho riscontrato lo stesso problema di Conrado: non ho potuto cambiare l'autorizzazione da 100644a 100755. Non penso che meriti un voto negativo; Git dovrebbe essere sotto votato. È così rotto in così tanti modi a così tanti livelli diversi ...
jww

-2

Lo etckeeperstrumento può gestire le autorizzazioni e con:

etckeeper init -d /mydir

Puoi usarlo per altre directory diverse da /etc .

Installa usando il tuo gestore pacchetti o ottieni fonti dal link sopra.


4
Cosa imposta le autorizzazioni? Se non legge i metadati di Git o invoca Git, non fa ciò che l'OP ha richiesto.
ivan_pozdeev il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.