Bagaimana cara membuat Git abaikan perubahan mode file (chmod)?

2311

Saya punya proyek di mana saya harus mengubah mode file dengan chmodke 777 saat mengembangkan, tetapi yang seharusnya tidak berubah dalam repo utama.

Git mengambil chmod -R 777 .dan menandai semua file yang diubah. Apakah ada cara untuk membuat perubahan mode Abaikan Git yang telah dibuat ke file?

Marcus Westin
sumber
17
Ini sangat membantu ketika bekerja dengan git di Windows + Bash di Ubuntu di Windows
Elazar
4
Untuk siapa saja yang hanya ingin mengabaikan perubahan izin untuk permintaan khusus git diff, dan yang karenanya tidak ingin mengubah file konfigurasi Git mereka: Anda dapat menggunakan jawaban git diff -G.per Zed di sini .
sampablokuper

Jawaban:

3824

Mencoba:

git config core.fileMode false

Dari git-config (1) :

core.fileMode
    Tells Git if the executable bit of files in the working tree
    is to be honored.

    Some filesystems lose the executable bit when a file that is
    marked as executable is checked out, or checks out a
    non-executable file with executable bit on. git-clone(1)
    or git-init(1) probe the filesystem to see if it handles the 
    executable bit correctly and this variable is automatically
    set as necessary.

    A repository, however, may be on a filesystem that handles
    the filemode correctly, and this variable is set to true when
    created, but later may be made accessible from another
    environment that loses the filemode (e.g. exporting ext4
    via CIFS mount, visiting a Cygwin created repository with Git
    for Windows or Eclipse). In such a case it may be necessary
    to set this variable to false. See git-update-index(1).

    The default is true (when core.filemode is not specified
    in the config file).

The -cflag dapat digunakan untuk mengatur opsi ini untuk satu-off perintah:

git -c core.fileMode=false diff

Dan --globalbendera akan membuatnya menjadi perilaku default untuk pengguna yang masuk.

git config --global core.fileMode false

Perubahan pengaturan global tidak akan diterapkan ke repositori yang ada. Selain itu, git clonedan git initsecara eksplisit diatur core.fileModeke truedalam konfigurasi repo seperti yang dibahas dalam Git global core.fileMode palsu yang ditimpa secara lokal pada klon

Peringatan

core.fileModebukan praktik terbaik dan harus digunakan dengan hati-hati. Pengaturan ini hanya mencakup bit mode yang dapat dieksekusi dan tidak pernah bit baca / tulis. Dalam banyak kasus Anda merasa Anda perlu pengaturan ini karena Anda melakukan sesuatu seperti chmod -R 777, membuat semua file Anda dapat dieksekusi. Tetapi dalam kebanyakan proyek sebagian besar file tidak perlu dan tidak boleh dieksekusi karena alasan keamanan .

Cara yang tepat untuk menyelesaikan situasi semacam ini adalah dengan menangani izin folder dan file secara terpisah, dengan sesuatu seperti:

find . -type d -exec chmod a+rwx {} \; # Make folders traversable and read/write
find . -type f -exec chmod a+rw {} \;  # Make files read/write

Jika Anda melakukannya, Anda tidak perlu menggunakannya core.fileMode, kecuali di lingkungan yang sangat langka.

Greg Hewgill
sumber
203
Jika Anda melakukannya, git config --global core.filemode falseAnda hanya perlu melakukan ini sekali untuk semua repo.
Greg
13
ini tidak bekerja untuk saya sampai saya sudah memperbaiki case itu seharusnya filemode bukan filemode
tishma
8
@tishma: Bagian konfigurasi Git dan nama variabel tidak peka huruf besar-kecil sesuai dengan dokumentasi, lihat bagian KONFIGURASI FILE , jadi jika hal di atas tidak bekerja untuk Anda maka itu untuk alasan yang berbeda.
Greg Hewgill
11
@donquixote: git configPerintah menulis pengaturan ke file config yang benar ( .git/confighanya untuk repositori saat ini, atau ~/.gitconfigjika digunakan dengan --global).
Greg Hewgill
8
@ zx1986: Tidak masalah. Dari git config : "Nama-nama variabel tidak peka huruf besar-kecil, ..."
Greg Hewgill
277

batalkan perubahan mode di pohon kerja:

git diff --summary | grep --color 'mode change 100755 => 100644' | cut -d' ' -f7- | xargs -d'\n' chmod +x
git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7- | xargs -d'\n' chmod -x

Atau di mingw-git

git diff --summary | grep  'mode change 100755 => 100644' | cut -d' ' -f7- | xargs -e'\n' chmod +x
git diff --summary | grep  'mode change 100644 => 100755' | cut -d' ' -f7- | xargs -e'\n' chmod -x
yoda
sumber
42
Pada OS X Lion, hilangkan -d'\n'bagian dari xargskarena ini merupakan argumen ilegal (dan tidak diperlukan).
Pascal
9
Anda dapat mengabaikan kesalahan apa pun tentang "chmod: operan yang hilang setelah` + x '"
Casey Watson
5
apakah ini terbaru? Saya mendapatkan 'chmod: terlalu sedikit argumen' di mingw
hammett
7
@Pascal @pimlottc The -d menentukan pembatas menjadi baris baru dan bukan spasi putih apa pun. BSD xargs tidak memiliki opsi itu, tetapi Anda dapat mem-pipe output melalui tr '\n' '\0'dan kemudian menggunakan -0arg to xargs untuk menggunakan NUL sebagai pembatas.
Mark Aufflick
10
Keren, trmasalahnya berhasil! Inilah perintah lengkap untuk OSX:git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7-|tr '\n' '\0'|xargs -0 chmod -x
K.-Michael Aye
135

Jika Anda ingin mengatur opsi ini untuk semua repo Anda, gunakan --globalopsi ini.

git config --global core.filemode false

Jika ini tidak berhasil, Anda mungkin menggunakan versi git yang lebih baru, jadi coba --addopsi.

git config --add --global core.filemode false

Jika Anda menjalankannya tanpa opsi - global dan direktori kerja Anda bukan repo, Anda akan mendapatkannya

error: could not lock config file .git/config: No such file or directory
adrien
sumber
5
Sepertinya penggunaan GIT nanti --add, seperti digit config --add --global core.filemode false
mgaert
14
Jika konfigurasi lokal repo sudah memiliki filemode = true maka mengubah konfigurasi global tidak akan membantu karena konfigurasi lokal akan menimpa konfigurasi global. Harus mengubah konfigurasi lokal dari setiap repo mesin sekali
Rakib
3
TOLONG: Perbarui jawaban ini dengan peringatan syedrakib! Semuanya terasa gila sebelum saya menemukannya, dan masuk akal setelah itu.
jerclarke
88

Jika

git config --global core.filemode false

tidak bekerja untuk Anda, lakukan secara manual:

cd into yourLovelyProject folder

cd ke dalam folder .git:

cd .git

edit file konfigurasi:

nano config

ubah true menjadi false

[core]
        repositoryformatversion = 0
        filemode = true

->

[core]
        repositoryformatversion = 0
        filemode = false

simpan, keluar, pergi ke folder atas:

cd ..

pasang kembali git

git init

kamu selesai!

Sinan Eldem
sumber
11
Alih-alih mengedit .git/config, sederhana git config core.fileMode falsedi root proyek Anda sudah cukup. Jika Anda mengedit file konfigurasi, Anda lebih baik menghapus direktif sepenuhnya, sehingga yang global diambil.
Felix
6
-1 jika git config - global tidak berfungsi itu berarti Anda tidak memiliki izin untuk melakukannya di tingkat sistem, menghapus globalopsi melakukan hal yang persis sama dengan mengedit secara manual. Git / config
CharlesB
@CharlesB salah - jawab memberikan solusi dengan menempatkan opsi langsung di proyek, membuatnya spesifik untuk proyek. Ini tidak akan bekerja dengan proyek git lain yang Anda buat / checkout di masa depan, tetapi bekerja untuk proyek yang sedang Anda kerjakan. (mari kita pastikan kita tidak ambigu ~/.gitconfig, dan ~/project/.git/config)
ddavison
Setelah ini berjalan, git initharuskah kita mengatur filemode kembali ke true?
Jordan
53

Menambahkan ke jawaban Greg Hewgill (menggunakan core.fileModevariabel config):

Anda dapat menggunakan --chmod=(-|+)xopsi git update-index (versi rendah dari "git add") untuk mengubah mengeksekusi izin dalam indeks, dari mana ia akan diambil jika Anda menggunakan "git commit" (dan bukan "git commit -a ").

Jakub Narębski
sumber
2
Ini seharusnya diedit menjadi jawaban Greg Hewgill daripada ditambahkan sebagai jawaban terpisah, sehingga menciptakan satu jawaban tertinggi dengan satu representasi yang tidak ambigu.
Greg
6
@Reg: Seseorang perlu memiliki cukup poin untuk mengedit bukan jawaban sendiri; Saya pikir saya tidak punya cukup untuk mengedit izin pada saat itu.
Jakub Narębski
1
@ Yakub Saya pikir Anda memiliki reputasi yang cukup sekarang :) Seperti apa perintah ini untuk file contoh?
Alex Hall
38

Anda dapat mengonfigurasinya secara global:

git config --global core.filemode false

Jika hal di atas tidak bekerja untuk Anda, alasannya mungkin konfigurasi lokal Anda menimpa konfigurasi global.

Hapus konfigurasi lokal Anda untuk membuat konfigurasi global berlaku:

git config --unset core.filemode

Atau, Anda dapat mengubah konfigurasi lokal Anda ke nilai yang benar:

git config core.filemode false

Tyler Long
sumber
4
Jika jawaban utama tidak membantu Anda - coba yang ini. Jika Anda ingin memeriksa konfigurasi lokal Anda tanpa memodifikasinya, periksa git config -l(daftarkan konfigurasi saat ini - baik lokal maupun global)
Krzysztof Bociurko
23

Jika Anda telah menggunakan perintah chmod maka periksa perbedaan file, Ini menunjukkan mode file sebelumnya dan mode file saat ini seperti:

mode baru: 755

mode lama: 644

atur mode lama semua file menggunakan perintah di bawah ini

sudo chmod 644 .

sekarang atur core.fileMode ke false dalam file konfigurasi baik menggunakan perintah atau secara manual.

git config core.fileMode false

lalu terapkan perintah chmod untuk mengubah izin semua file seperti

sudo chmod 755 .

dan sekali lagi atur core.fileMode menjadi true.

git config core.fileMode true

Untuk praktik terbaik, jangan selalu membuat core.fileMode salah.

Kishor Vitekar
sumber
Apakah Anda mengatakan bahwa seluruh proyek (dalam pengembangan, pementasan, dan produksi) harus 755?
Daniel
@Daniel Feb: Tidak. Ubah mode file yang diperlukan saja.
Kishor Vitekar
For best practises don't Keep core.fileMode false alwaysapa maksudmu, kau harus menjelaskan itu.
bg17aw
For best practises don't Keep core.fileMode false always.Beberapa sistem file (FAT misalnya) tidak mendukung izin file, sehingga OS akan melaporkan nilai default (766 pada sistem saya). Dalam hal ini, core.filemodesangat diperlukan dalam konfigurasi lokal, kecuali jika Anda ingin
membengkak
Juga, mengapa Anda repot-repot mengubah perms kembali sama sekali? Jika Anda mengatur core.filemode=falsemaka git akan mengabaikan eksekusi perubahan bit, tidak perlu mengubah izin lokal. Kecuali jika Anda sudah menambahkan perubahan izin ke indeks, dalam hal ini Anda melewatkan langkah di mana Anda perlu git addsetelah Anda mematikan core.filemode.
KevinOrr
18

Dengan mendefinisikan alias berikut (dalam ~ / .gitconfig) Anda dapat dengan mudah menonaktifkan sementara perintah fileMode per git:

[alias]
nfm = "!f(){ git -c core.fileMode=false $@; };f"

Ketika alias ini diawali dengan perintah git, perubahan mode file tidak akan muncul dengan perintah yang akan menunjukkannya. Sebagai contoh:

git nfm status
Ville
sumber
14

Jika Anda ingin mengatur filemode ke false dalam file konfigurasi secara rekursif (termasuk submodul): find -name config | xargs sed -i -e 's/filemode = true/filemode = false/'

dryobs
sumber
5
Ini tidak akan berfungsi jika baris itu tidak ada dalam file konfigurasi. Jika Anda ingin mengubahnya untuk submodula, coba ini:git submodule foreach git config core.fileMode false
courtlandj
4

Solusi sederhana:

Tekan perintah sederhana ini di folder proyek ( itu tidak akan menghapus perubahan asli Anda) ... itu hanya akan menghapus perubahan yang telah dilakukan saat Anda mengubah izin folder proyek

perintah di bawah ini:

git config core.fileMode false

Mengapa semua file yang tidak perlu ini dimodifikasi: karena Anda telah mengubah izin folder proyek dengan memuji sudo chmod -R 777 ./yourProjectFolder

kapan Anda akan memeriksa perubahan apa yang tidak Anda lakukan? Anda menemukan seperti di bawah ini saat menggunakan nama file git diff

old mode 100644
new mode 100755
Shashwat Gupta
sumber
1

Ini bekerja untuk saya:

find . -type f -exec chmod a-x {} \;

atau mundur, tergantung pada sistem operasi Anda

find . -type f -exec chmod a+x {} \;
Martin Volek
sumber
1
Ini akan mengubah izin file, tetapi tidak membuat git mengabaikan izin file dari file tersebut.
domdambrogia
Yah, Anda benar, itu tidak menyelesaikan masalah mengabaikan git.
Martin Volek