Bagaimana cara mengembalikan izin file dan direktori di dalam git jika sudah dimodifikasi?

278

Saya punya checkout git. Semua izin file berbeda dari apa yang menurut git mereka seharusnya karena itu mereka semua ditampilkan sebagai diubah.

Tanpa menyentuh konten file (hanya ingin memodifikasi izin) bagaimana cara mengatur semua file izin untuk apa yang menurut git seharusnya?

Dale Forester
sumber

Jawaban:

572

Git melacak filepermission dan mengekspos perubahan izin saat membuat tambalan menggunakan git diff -p. Jadi yang kita butuhkan adalah:

  1. buat tambalan terbalik
  2. hanya menyertakan perubahan izin
  3. terapkan tambalan ke copy pekerjaan kami

Sebagai satu-liner:

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

Anda juga dapat menambahkannya sebagai alias ke konfigurasi git Anda ...

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'

... dan Anda dapat memintanya melalui:

git permission-reset

Catatan, jika Anda shell bash, pastikan untuk menggunakan 'alih-alih "tanda kutip di sekitar !git, jika tidak maka akan diganti dengan gitperintah terakhir yang Anda jalankan.

Thx untuk @Mixologic untuk menunjukkan bahwa dengan hanya menggunakan -Rpada git diff, yang rumit sedperintah tidak lagi diperlukan.

muhqu
sumber
3
Saya di OS X, ini tidak berfungsi. Saya telah mengidentifikasi masalahnya ada di git berlaku. Itu tidak menerapkan perubahan izin file.
pepper_chico
15
Oh, berhasil, saya mencoba menerapkan dari direktori yang berbeda dari akar repositori. git hanya berlaku di sana.
pepper_chico
6
Apakah ada alasan mengapa Anda tidak hanya melakukan "git diff -p -R" daripada melakukan sed untuk membuatnya terbalik?
Mixologic
6
@RobQuist perubahan lokal saya tidak dihapus saat menggunakan perintah muhqu
logion
17
Saya mulaifatal: unrecognized input
Tieme
120

Mencoba git config core.fileMode false

Dari git confighalaman manual:

core.fileMode

Jika salah, perbedaan bit yang dapat dieksekusi antara indeks dan copy pekerjaan diabaikan; berguna pada sistem file yang rusak seperti FAT. Lihat git-update-index (1) .

Default-nya benar, kecuali git-clone (1) atau git-init (1) akan menyelidiki dan menetapkan core.fileMode salah jika sesuai ketika repositori dibuat.

Tim Henigan
sumber
Terima kasih, inilah yang akhirnya saya lakukan. Sangat digunakan untuk cvs tidak melacak izin sehingga ini berfungsi.
Dale Forester
3
@shovas: Saya senang ini membantu. Saya mengalami masalah serupa ketika berbagi repo antara Linux dan Windows. BTW: jika ini menjawab pertanyaan Anda, harap tandai respons tersebut benar.
Tim Henigan
Mungkinkah git checkout origin/mastermenetapkan izin file yang dikomit ke server ke copy pekerjaan lokal saya? Karena setiap kali saya membuat V8 untuk ArangoDB, izin file diubah sehingga akses ditolak ke seluruh folder build (bahkan dengan hak tinggi; Windows 7+). Saya perlu memperbaiki semua izin file lokal sebelum saya dapat melanjutkan proses pembuatan. Bisakah core.filemode falsememperbaikinya juga? Saya menduga git untuk mengatur izin Linux pada mesin Windows saya. Skrip build mungkin hanya menyimpannya dan menerapkan izin yang sama untuk file yang baru dibuat ...
CodeManX
Im bertanya-tanya apakah ada kerugian untuk pengaturan filemodeuntuk false!
kevoroid
11

Git tidak menyimpan izin file selain skrip yang dapat dieksekusi. Pertimbangkan untuk menggunakan sesuatu seperti git-cache-meta untuk menyimpan kepemilikan dan izin file.

Git hanya dapat menyimpan dua jenis mode: 755 (dapat dieksekusi) dan 644 (tidak dapat dijalankan). Jika file Anda adalah 444 git akan menyimpannya memiliki 644.

Kroger
sumber
14
Maaf, tapi ini tidak benar. Git memang melacak izin.
Will
4
Ini kira-kira akurat, lihat git.wiki.kernel.org/index.php/ContentLimitations . Izin tepat yang diatur tampaknya berdasarkan pada server & mungkin klien umaskserta pengaturan konfigurasi, lihat stackoverflow.com/a/12735291/125150 .
Motti Strom
12
@ Tidak, tidak. Tidak percaya komentar Anda mendapat begitu banyak upvotes.
eis
@ Akan, ini kira-kira benar. Per dokumen ...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

akan bekerja dalam banyak kasus tetapi jika Anda memiliki alat-alat eksternal seperti ter-instal meld Anda harus menambahkan --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

diperlukan dalam situasi saya

zainengineer
sumber
0

Saya menggunakan git dari cygwin di Windows, git applysolusinya tidak bekerja untuk saya. Inilah solusi saya, jalankan chmodpada setiap file untuk mengatur ulang izinnya.

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

git diff -pdigunakan dalam jawaban muhqu mungkin tidak menunjukkan semua perbedaan.

  • melihat ini di Cygwin untuk file yang bukan milik saya
  • perubahan modus diabaikan sepenuhnya jika core.filemodeadalah false(yang merupakan default untuk msysgit)

Kode ini membaca metadata secara langsung sebagai gantinya:

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

Lapisan satu tingkat non-produksi (menggantikan sepenuhnya topeng):

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

(Kredit untuk "$ '\ 0'" berlaku untuk http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html )

ivan_pozdeev
sumber
-2

Hal termudah untuk dilakukan adalah dengan hanya mengubah kembali izin. Seperti yang dicatat @kroger, git hanya melacak bit yang dapat dieksekusi. Jadi, Anda mungkin hanya perlu menjalankan chmod -x filenameuntuk memperbaikinya (atau +xjika itu yang diperlukan.

Pat Notz
sumber
Berikut ini adalah contoh dari git show: diff --git a / OpenWatch / src / org / ale / openwatch / fb / FBUtils.java b / OpenWatch / src / org / ale / openwatch / fb / index FBUtils.java cd6fa6a..e5b0935 100.644 Itu sedikit tebal ada izin file.
Conrado
Bagi saya ini juga tampak paling mudah. Sayangnya, saya mengalami masalah yang sama dengan Conrado - saya tidak dapat mengubah izin dari 100644ke 100755. Saya pikir Anda tidak pantas menerima downvote; Git harus turun suara. Sangat rusak dalam banyak hal di berbagai tingkatan ...
jww
-2

The etckeeperalat dapat menangani perizinan dan dengan:

etckeeper init -d /mydir

Anda dapat menggunakannya untuk dir selain /etc.

Instal dengan menggunakan manajer paket Anda atau dapatkan sumber dari tautan di atas.

MoreIT
sumber
4
Apa yang mengatur izin? Jika tidak membaca metadata Git atau memanggil Git, itu tidak melakukan apa yang diminta OP.
ivan_pozdeev