Bagaimana saya bisa membuat git mengabaikan revisi file yang akan datang?

140

Saya telah membuat versi standar dari file yang termasuk dalam repositori git. Sangat penting bahwa ketika seseorang mengkloning repositori, mereka mendapatkan salinan file ini. Namun, saya ingin mengatur git sehingga mengabaikan perubahan pada file ini nanti. .gitignorehanya berfungsi pada file yang tidak dilacak.

Motivasi saya adalah bahwa file ini berisi informasi spesifik mesin. Saya ingin memberikan nilai-nilai default, sementara memungkinkan orang untuk membuat perubahan lokal yang tidak akan didorong kembali ke repositori asal, menciptakan konflik gabungan ketika kita menarik perubahan baru.

Kami umumnya cukup malas dan git add .banyak menggunakan , jadi saya cukup yakin jika saya tidak dapat memberitahu git untuk mengabaikan file ini, perubahan pada file tersebut akan berakhir dengan komitmen dan dorongan.

Untuk meringkas,

  1. Saya ingin membuat file, sebut saja default_values.txtyang ditambahkan ke repositori git saya dan disertakan ketika seseorang mengkloning repositori itu.
  2. git add .seharusnya tidak menambah default_values.txtkomit.
  3. Perilaku ini harus diteruskan ke klon repositori mana pun.
Marc
sumber
1
Bisakah Anda menggunakan kait git untuk memiliki kait pra-komit yang akan membatalkan komit jika file yang diubah adalah default_values.txt (katakanlah)?
sateesh
1
Git purists akan mengatakan jangan malas dan menggunakan area pementasan dengan benar, itu untuk apa.
Xint0
Git puritan akan mengatakan menggunakan skrip smudge / clean. Itu solusi yang paling bisa dipertahankan.
Adam Dymitruk
1
Xint0: benar. tetapi bagaimana Anda mencegah orang lain dari tidak sengaja check-in?
Alan
kemungkinan duplikat dari File Konfigurasi Khusus Mesin yang Berkomitmen
Senseful

Jawaban:

115

Seperti yang banyak orang lain katakan, solusi modern yang baik adalah:

git update-index --skip-worktree default_values.txt

Itu akan mengabaikan perubahan pada file itu, baik lokal maupun upstream, hingga Anda memutuskan untuk mengizinkannya lagi dengan:

git update-index --no-skip-worktree default_values.txt

Anda bisa mendapatkan daftar file yang ditandai dilewati dengan:

git ls-files -v . | grep ^S

Perhatikan bahwa tidak seperti itu --skip-worktree, --assume-unchangedstatus akan hilang setelah perubahan hulu ditarik.

moodboom
sumber
2
Jika orang lain menarik repo dan mengedit file, apakah perubahan dalam direktori mereka diabaikan? Saya berharap mereka harus mengetik --no-skip-worktreeuntuk menambahkan perubahan mereka.
neaumusic
3
Apa yang dilakukan dengan perubahannya dikendalikan oleh mereka. Dengan kata lain, mereka harus mengatur skip-worktree pada file dalam repo mereka jika mereka tidak ingin perubahan mereka didorong. Jika itu adalah file yang dimaksudkan untuk dikirim ke semua orang dan kemudian semua perubahan berikutnya diabaikan, semua orang harus mengikuti instruksi yang sama.
moodboom
3
Perhatikan bahwa Anda mungkin harus membatalkan --skip-worktreestatus file sebelum Anda dapat beralih cabang, jika file yang sama dilacak di cabang lain.
moodboom
3
hmm, itu berfungsi ... setelah saya melakukan beberapa perubahan pada file itu tidak ditampilkan git status, tetapi ketika saya mencoba untuk checkout ke cabang yang berbeda, saya punya error: Your local changes to the following files would be overwritten by checkout: , bahkan -f tidak membantuerror: Entry 'wix-stores-merchant-app/demo/credentials.js' not uptodate. Cannot merge.
ykravv
1
Saya memiliki ini alias git ignoredan git unignore.
Michael
48

Apa yang Anda cari adalah git update-index --assume-unchanged default_values.txt.

Lihat dokumen untuk detail lebih lanjut: http://www.kernel.org/pub/software/scm/git/docs/git-update-index.html

tamasd
sumber
11
ini tidak bekerja. meskipun itu membuat git add. abaikan file pada cabang lokal, klon dari arsip tidak memiliki perilaku ini (jika Anda mengubah default_values.txt dalam arsip yang dikloning, itu akan ditambahkan ke komit dengan "git add.")
Marc
6
Ya, karena Anda mengaturnya hanya untuk repo lokal. Anda tidak dapat mendorong informasi semacam ini.
tamasd
8
@Indradhanush - solusi ini tidak memenuhi kriteria 3 - "perilaku harus diteruskan ke klon repositori" - itulah sebabnya saya tidak menerimanya. Bukan berarti itu bukan jawaban yang baik.
Marc
Saya tidak pernah memperhatikan kriteria ke-3. Karena saya tidak mencarinya. :)
Indradhanush Gupta
3
Untuk file konfigurasi lokal dengan pengaturan aplikasi pribadi, Anda mungkin ingin menggunakan skip-worktreealih-alih assume-unchangedlebih banyak info stackoverflow.com/questions/13630849/…
Aaron Hoffman
22

Pendekatan yang saya lihat pada umumnya adalah membuat file dengan nama yang berbeda, misalnya: default_values_template.txt dan meletakkan default_values.txt di .gitignore Anda. Instruksikan orang untuk menyalin default_values_template.txt ke default_values.txt di ruang kerja lokal mereka dan buat perubahan seperlunya.

Laurence Gonsalves
sumber
hmmm ... mungkin saya bisa menulis sebuah kail untuk secara otomatis menyalin default_values_template ke default_values ​​jika default_values ​​tidak ada?
Marc
2
Ini adalah cara paling umum untuk menyelesaikan ini dalam pengalaman saya. Itu cukup banyak jalan resistensi setidaknya karena "hanya berfungsi", dan Anda dapat dengan mudah membuat kode Anda memeriksa apakah file konfigurasi lokal ada dan memberikan kesalahan bermanfaat jika tidak.
Jani Hartikainen
Saya pikir solusinya memang untuk melakukan sesuatu seperti ini, lebih disukai dengan skrip dieksekusi setiap kali Anda menarik atau mengkloning. Satu ide adalah bahwa segala sesuatu dengan ekstensi tertentu (katakanlah. Basefile) akan disalin ke file dengan ekstensi yang dijatuhkan dan kemudian nama file akan ditambahkan ke .gitignore di direktori itu. Jadi saya akan membuat file default_values.txt.basefile dan melakukan itu. Saya tidak memiliki git atau perl chops untuk melakukan ini, tetapi saya akan bertanya kepada seorang teman yang melakukannya dan memberi tahu Anda bagaimana hasilnya.
Marc
1
@AdamDymitruk: Ya, clean / smudge dapat digunakan dalam kasus ini, tetapi jauh dari jelas bahwa itu adalah pilihan terbaik. Sebagai contoh, ini akan membuatnya agak sulit jika orang benar - benar ingin mengubah file, karena noda / noda akan menghalangi. Saya sebenarnya lebih suka pendekatan yang dijelaskan di sini.
sleske
1
Saya mengambil isyarat dari git itu sendiri (khususnya kait git) dan menggunakan .sampleakhiran. Jadi dalam kasus Andadefault_values.txt.sample
tir38
5

Lihatlah skrip smudge / clean. Dengan cara ini Anda dapat mengontrol versi file tetapi ketika diperiksa, Anda akan "noda" dengan mengganti data generik / tempat-pemegang dengan data spesifik mesin dalam file.

Saat Anda mengkomitnya, Anda akan "membersihkannya" dengan mengganti informasi spesifik mesin dengan informasi umum atau tempat-dudukan.

Naskah noda / bersih harus bersifat deterministik karena menerapkannya berkali-kali, dalam urutan yang berbeda akan sama dengan hanya menjalankan yang terakhir dalam urutan.

Hal yang sama dapat diterapkan dengan kata sandi jika Anda perlu mengekspos repositori Anda tetapi isinya mungkin berisi informasi sensitif.

Adam Dymitruk
sumber
Apakah skrip Clean and Smudge lokal atau bagian dari repo?
Alan
Iya. :) ... yaitu, Anda dapat berbagi noda bersih melalui repo tetapi itu bukan ide yang baik ketika mengandung data sensitif seperti kata sandi produksi. Jika itu bukan masalah, git mengharuskan Anda untuk mengaktifkan skrip secara eksplisit. Kalau tidak, orang bisa melakukan hal-hal jahat melalui github dan repo bersama lainnya kepada pengguna lain.
Adam Dymitruk
Saya perlu membaca lebih banyak tentang ini. Pada dasarnya saya ingin mengatur proyek yang memiliki default user.jsonyang perlu ditimpa dengan setiap pengembang kredit, tetapi saya tidak ingin dev secara tidak sengaja memeriksa kredit mereka.
Alan
Saya akan google sekitar untuk skrip contoh noda bersih. Lihat apa yang muncul. Juga, melompat di ruang git irc di freenode. Anda akan segera mendapatkan bantuan.
Adam Dymitruk
3

Saya telah memecahkan ini dengan mendefinisikan filter "bersih" untuk hanya menyimpan isi file dalam indeks.

git show :path/to/myfile seharusnya hanya mencetak isi indeks untuk file yang ditentukan, jadi kita bisa menggunakannya dalam skrip untuk mengganti copy pekerjaan dengan salinan yang tidak tersentuh dalam indeks:

#! /bin/sh

git show :$1

Tetapkan itu sebagai filter "bersih" untuk file yang bersangkutan (dengan asumsi Anda telah memasukkannya ke "discard_changes"):

$ git config filter.ignore_myfile.clean "discard_changes path/to/myfile"
$ echo "path/to/myfile filter=ignore_myfile" >> .gitattributes

Sayangnya saya tidak dapat menemukan cara untuk membuat generalisasi ini ke banyak file, karena tidak ada cara untuk mengetahui file mana yang kami proses dari dalam skrip bersih. Tentu saja, tidak ada yang menghentikan Anda untuk menambahkan aturan filter yang berbeda untuk setiap file, tetapi ini agak tidak jelas.

CD Haddon.
sumber
1

Saya menemukan solusi yang berfungsi untuk tim saya. Kami membagikan githook kami melalui symlink dan setelah menambahkan file template ke git, saya menambahkan hook pre-commit yang memeriksa apakah file template telah dimodifikasi dan jika demikian saya git reset -- templatefile.txt. Jika itu satu-satunya file yang diubah saya juga membatalkan komit.

fruitcoder
sumber
-1

Saya sarankan melihat submodules. Jika Anda menempatkan file spesifik mesin dalam submodule, git add harus mengabaikannya.

ivanpro
sumber
ini adalah ide yang bagus, tetapi kemudian saya juga harus meletakkan repositori file tunggal pada server git juga, yang kurang optimal, hanya karena kita menggunakan github dan memiliki sejumlah repositori yang terbatas.
Marc
@Marc melihat Visual Studio Team Services, proyek pribadi gratis tanpa batas dan repositori git. Papan Kanban, item pekerjaan, dan pelacakan bug, kaitkan checkin dengan item kerja, kelola sprint jika Anda menyukai scrum atau jenis proyek lainnya. Selain itu ia memiliki alat membangun yang sangat baik untuk membangun terhadap berbagai platform, terlalu banyak hal untuk disebutkan yang semuanya gratis. Beberapa orang menimbunnya karena itu Microsoft, tetapi itu mengalahkan apa yang ditawarkan github dalam hal alat selain dari hanya hosting repositori. Ada batasan apa yang dapat Anda lakukan secara gratis tetapi saya jarang melampauinya.
Aran Mulholland
@Marc satu hal lagi yang menurut saya sangat berguna adalah saya dapat mengatur akun sebanyak yang saya inginkan, jadi jika saya menulis proyek untuk klien yang ingin memiliki kontrol sumber, saya dapat membuat akun, menggunakannya untuk merencanakan, mendesain, dan melaksanakan proyek dan ketika saya selesai, saya dapat meneruskan kepemilikan akun kepada klien.
Aran Mulholland