Bisakah saya 'git melakukan' file dan mengabaikan perubahan kontennya?

355

Setiap pengembang di tim saya memiliki konfigurasi lokal mereka sendiri. Informasi konfigurasi itu disimpan dalam file yang disebut devtargets.rbyang digunakan dalam tugas rake build kami. Saya tidak ingin para pengembang saling menghancurkan file devtargets masing-masing.

Pikiran pertama saya adalah memasukkan file itu ke dalam .gitignoredaftar sehingga tidak berkomitmen untuk git.

Lalu saya mulai bertanya-tanya: apakah mungkin untuk melakukan file, tetapi mengabaikan perubahan pada file? Jadi, saya akan melakukan versi standar file dan kemudian ketika seorang pengembang mengubahnya di mesin lokal mereka, git akan mengabaikan perubahan dan itu tidak akan muncul dalam daftar file yang diubah ketika Anda melakukan status git atau git melakukan .

Apakah itu mungkin? Pasti akan menjadi fitur yang bagus ...

Derick Bailey
sumber
1
Lihat juga stackoverflow.com/questions/3318043/… pada topik serupa.
VonC
kemungkinan duplikat dari File Konfigurasi Khusus Mesin yang Berkomitmen
Senseful

Jawaban:

458

Tentu, saya melakukan ini dari waktu ke waktu menggunakan

git update-index --assume-unchanged [<file> ...]

Untuk membatalkan dan mulai melacak lagi (jika Anda lupa file apa yang tidak dilacak, lihat pertanyaan ini ):

git update-index --no-assume-unchanged [<file> ...]

Dokumentasi yang relevan :

- [no-] menganggap-tidak berubah
Ketika bendera ini ditentukan, nama-nama objek yang direkam untuk jalur tidak diperbarui. Sebagai gantinya, opsi ini mengeset / membatalkan bit "asumsikan tidak berubah" untuk jalur. Ketika bit "asumsi tidak berubah" aktif, pengguna berjanji untuk tidak mengubah file dan memungkinkan Git untuk berasumsi bahwa file pohon kerja cocok dengan apa yang dicatat dalam indeks. Jika Anda ingin mengubah file tree yang berfungsi, Anda perlu menghapus bit untuk memberi tahu Git. Ini kadang-kadang membantu ketika bekerja dengan proyek besar pada sistem file yang memiliki lstat(2)system call yang sangat lambat (misalnya cifs).

Git akan gagal (anggun) jika perlu memodifikasi file ini dalam indeks misalnya ketika menggabungkan komit; dengan demikian, jika file yang diasumsikan tidak dirubah diubah ke hulu, Anda perlu menangani situasi secara manual.

Gagal dengan anggun dalam hal ini berarti, jika ada perubahan di bagian hulu ke file tersebut (perubahan yang sah, dll.) Saat Anda melakukan penarikan, akan muncul tulisan:

$ git pull
…
From https://github.com/x/y
   72a914a..106a261  master     -> origin/master
Updating 72a914a..106a261
error: Your local changes to the following files would be overwritten by merge:
                filename.ext

dan akan menolak untuk bergabung.

Pada titik itu, Anda dapat mengatasinya dengan mengembalikan perubahan lokal Anda, berikut ini caranya:

 $ git checkout filename.ext

kemudian tarik lagi dan modifikasi ulang file lokal Anda, atau dapat diatur –no-assume-unchangeddan Anda dapat melakukan simpanan dan penggabungan normal, dll. pada saat itu.

Rob Wilkerson
sumber
10
apakah perintah ini melakukan tugasnya secara lokal di dalam folder .git? Maksud saya, jika saya menjalankan perintah ini untuk file config.php, apakah ini akan menyebar ke pengguna lain yang menggunakan repo?
Magus
16
@Magus: Tidak. Ini hanya akan berlaku untuk Anda.
Rob Wilkerson
3
Dan segera Anda akan ingin tahu bagaimana menentukan apakah file diasumsikan tidak berubah: stackoverflow.com/questions/2363197/…
Ciro Santilli 郝海东 冠状 病 六四 六四 事件 法轮功
10
Perubahan pada file yang diabaikan dengan cara ini hilang ketika "git stash" digunakan. Apakah ada jalan keluarnya?
Alexis
5
Ini bukan untuk apa git update-index --assume-unchanged. public-inbox.org/git/…
jsageryd
97

Cara yang disukai untuk melakukan ini adalah menggunakan git update-index --skip-worktree <file>, seperti yang dijelaskan dalam jawaban ini :

assume-unchangeddirancang untuk kasus-kasus di mana mahal untuk memeriksa apakah sekelompok file telah dimodifikasi; ketika Anda mengatur bit, git (tentu saja) mengasumsikan file yang sesuai dengan bagian indeks tersebut belum dimodifikasi dalam copy pekerjaan. Jadi itu menghindari kekacauan panggilan stat. Bit ini hilang setiap kali entri file dalam indeks berubah (jadi, ketika file diubah hulu).

skip-worktreelebih dari itu: bahkan ketika git tahu bahwa file telah dimodifikasi (atau perlu diubah dengan reset --hard atau sejenisnya), itu akan berpura-pura belum, menggunakan versi dari indeks sebagai gantinya. Ini berlanjut sampai indeks dibuang.

Untuk membatalkan ini, gunakan git update-index --no-skip-worktree <file>

Sejak git versi 2.25.1, ini bukan lagi cara yang disarankan, dengan mengutip:

Pengguna sering mencoba menggunakan bit asumsi-tidak berubah dan lewati-worktree untuk memberitahu Git untuk mengabaikan perubahan pada file yang dilacak. Ini tidak berfungsi seperti yang diharapkan, karena Git masih dapat memeriksa file pohon kerja terhadap indeks saat melakukan operasi tertentu. Secara umum, Git tidak menyediakan cara untuk mengabaikan perubahan pada file yang dilacak, sehingga solusi alternatif disarankan.

Sebagai contoh, jika file yang ingin Anda ubah adalah semacam file konfigurasi, repositori dapat menyertakan sampel file konfigurasi yang kemudian dapat disalin ke nama yang diabaikan dan diubah. Repositori bahkan dapat menyertakan skrip untuk memperlakukan file sampel sebagai templat, memodifikasi dan menyalinnya secara otomatis.

1615903
sumber
Apakah ini berfungsi di semua pengguna yang checkout repositori? Apakah mereka akan mendapatkan file tertentu tetapi tidak lagi dapat menambahkan perubahan, secara tidak sengaja, kecuali secara eksplisit mengatakannya?
mmm
2
@momomo bendera disimpan dalam indeks jadi tidak, itu hanya untuk satu pengguna. Lihat jawaban erjiang untuk sesuatu yang bekerja di semua pengguna.
1615903
Saya mencoba mencari tahu apa isi file tersebut. Saya mengomentari jawaban yang Anda sebutkan, tetapi tidak mendapat jawaban. Di mana letaknya seharusnya dan apa isinya? Apakah anda tahu
mmm
Saya tidak mengikuti. Perintah ini digunakan untuk mengabaikan satu file tertentu yang Anda tentukan dalam perintah. Isi file itu tidak relevan.
1615903
1
The dokumentasi Git secara khusus mengatakan tidak menggunakan git update-index --skip-worktreeuntuk tujuan ini.
bk2204
43

Praktik umum tampaknya adalah membuat devtargets.default.rbdan mengkomitnya, dan kemudian menginstruksikan setiap pengguna untuk menyalin file itu devtargets.rb(yang ada di daftar .gitignore). Sebagai contoh, CakePHP melakukan hal yang sama untuk file konfigurasi database-nya yang secara alami berubah dari mesin ke mesin.

erjiang
sumber
6
Anda tidak dapat .gitignore file yang sedang dilacak. .gitignore hanya memiliki efek untuk file yang tidak ada dalam indeks.
CB Bailey
1
saya berusaha menghindari melakukan ini, meskipun saya benar-benar tidak memiliki alasan yang baik kami melakukannya sekarang dan saya pikir itu menyakitkan untuk diingat bahwa saya perlu membuat versi saya sendiri tanpa ".default" dalam nama.
Derick Bailey
11
@DerickBailey Tapi untuk bersikap adil, lebih mudah untuk mengingat untuk menyalin file daripada mengingat menggunakan --assume-unchangedopsi untuk semua orang yang mengkloning repositori.
Dan
1
@DerickBailey Anda juga dapat mengatur rake build Anda ke default devtargets.default.rbjika devtargets.rbtidak ada.
Luke
@erjang apa yang ada di file devtargets.default.rb itu? Sebuah contoh?
mmm
2

Untuk pengguna IntelliJ IDEA: Jika Anda ingin mengabaikan perubahan untuk file (atau file) Anda dapat memindahkannya ke yang berbeda Change Set.

  • Buka Local Changes( Cmd + 9)
  • Pilih file yang ingin Anda abaikan
  • F6 untuk memindahkan mereka ke yang lain Change Set
Eugene
sumber