Kiat untuk menempatkan ~ di bawah kendali sumber

77

Saya ingin meletakkan direktori home saya (~) di bawah kontrol sumber (git, dalam hal ini), karena saya memiliki banyak file pengaturan (.gitconfig, .gitignore, .emacs, dll.) Di sana saya ingin membawa melintasi mesin, dan memiliki mereka di Git akan membuatnya bagus untuk mengambilnya.

Mesin utama saya adalah MacBook saya, dan cara mengatur OS X, ada banyak folder yang ingin saya abaikan (Dokumen, Unduhan, .ssh). Ada juga folder yang sudah menggunakan Git (.emacs.d).

Pikiran saya adalah menambahkan semua direktori ini ke file .gitignore saya, tapi itu agak melelahkan, dan berpotensi menyebabkan beberapa konsekuensi yang tidak terduga. Pikiran saya berikutnya adalah menyalin secara berkala file yang ingin saya simpan ke beberapa folder di rumah, kemudian melakukan folder itu. Masalahnya adalah saya harus ingat untuk memindahkan mereka sebelum melakukan.

Apakah ada cara bersih untuk melakukan ini?

Dan McClain
sumber
Anda juga dapat membuat skrip melakukan commit dari folder yang Anda inginkan dan memanggilnya melalui cronjobs.
Shadok
Perhatikan bahwa sistem file HFS + default pada Mac OS X tidak peka terhadap huruf besar-kecil (tetapi mempertahankan huruf besar-kecil) dan jalur file dikodekan dalam UTF-8 terurai secara kanonik di ruang pengguna! Untuk informasi lebih lanjut, lihat: <a href=" stackoverflow.com/questions/5581857/… dan masalah Umlaut di Mac OS X</a>

Jawaban:

60

Saya punya di $HOMEbawah git. Baris pertama file .gitignore saya adalah

/*

Sisanya adalah pola untuk tidak mengabaikan menggunakan !pengubah. Baris pertama ini berarti defaultnya adalah mengabaikan semua file di direktori home saya. File-file yang ingin saya kontrol versi masuk .gitignoreseperti ini:

!/.gitignore
!/.profile
[...]

Pola rumit yang saya miliki adalah:

!/.ssh
/.ssh/*
!/.ssh/config

Artinya, saya hanya ingin versi .ssh/config- Saya tidak ingin kunci dan file lain di .ssh masuk ke git. Di atas adalah bagaimana saya mencapainya.

Sunting: Menambahkan garis miring untuk memulai semua jalur. Ini membuat pola abaikan cocok dari atas repositori ($ HOME) alih-alih di mana saja. Misalnya, jika !lib/suatu pola (jangan abaikan semua yang ada di direktori lib) dan Anda menambahkan file .gitignore, sebelumnya pola ( !.gitignore) cocok dengan itu. Dengan slash terkemuka ( !/.gitignore), itu hanya akan cocok .gitignoredi direktori home saya dan tidak di subdirektori mana pun.

Saya belum melihat kasus di mana ini membuat perbedaan praktis dengan daftar abaikan saya, tetapi bagi saya tampaknya lebih akurat secara teknis.

camh
sumber
1
Bagi saya tampaknya hal yang sama dapat dicapai dengan cara yang jauh lebih mudah .
Nick Volynkin
24

Apa yang saya lakukan (dengan tujuan yang sama) adalah meletakkan file konfigurasi saya di subdirektori ~/libdan memiliki tautan simbolik di direktori home saya, misalnya .emacs -> lib/emacs/dot.emacs,. Saya hanya menyimpan file konfigurasi yang saya tulis secara eksplisit di bawah kontrol versi; direktori rumah saya berisi banyak file dot yang dibuat secara otomatis yang tidak di bawah kontrol versi. Dengan demikian di ~/libbawah kontrol versi, dan direktori home saya tidak.

Saya memiliki skrip yang membuat tautan simbolik dari file di bawah ~/lib. Ketika saya membuat akun di mesin baru, saya mengisinya dengan memeriksa ~/libdan menjalankan skrip itu.

Pengalaman saya dengan CVS, bukan git, jadi tidak 100% dapat ditransfer. Salah satu alasan saya tidak menempatkan direktori home saya langsung di bawah CVS adalah itu ~/.cvsignoreakan berlaku untuk semua checkout CVS saya dan bukan hanya direktori home saya; git tidak memiliki masalah ini. Kelemahan dari pendekatan itu dibandingkan dengan memiliki direktori home di bawah kontrol versi adalah bahwa Anda tidak dapat menggunakan git statusuntuk membedakan antara file yang Anda secara eksplisit memutuskan untuk abaikan (yang akan tercantum dalam file abaikan, jadi tidak ditampilkan) dan file yang Anda tidak memiliki pendapat tentang (yang akan ditampilkan dengan a ?).

Beberapa file harus berbeda pada mesin yang berbeda. Saya menempatkan mereka di direktori yang disebut ~/Local/SITENAME/libdan baik membuat tautan simbolis untuk mereka juga atau (untuk format file yang mendukungnya) memiliki arahan sertakan dalam file di bawah ~/lib. Saya juga punya tautan simbolik ~/Here -> ~/Local/SITENAME. Karena git, tidak seperti CVS, dirancang untuk mendukung repositori yang sebagian besar mirip tetapi tidak identik, mungkin ada cara yang lebih baik untuk mengelola file khusus mesin. Beberapa file titik saya sebenarnya bukan tautan simbolis, tetapi secara otomatis dihasilkan dari konten di bawah ~/libdan ~/Here.

Gilles
sumber
Mungkin Anda memiliki core.excludesfile = ~/.gitignore. Tanpa konfigurasi seperti itu, file tidak diterapkan ke repositori apa pun kecuali yang disimpan di ~/.git(bahkan kemudian tidak akan berlaku untuk sub-repositori). Saya menggunakan core.excludesfile = ~/.git-user-excludesuntuk menghindari konflik antara pengecualian yang ingin saya terapkan ke semua repositori Git saya (terlepas dari lokasi) dan pengecualian yang ingin saya terapkan pada repositori yang menampung (sebagian) direktori home saya.
Chris Johnsen
@ Chris: Saya tahu sedikit tentang git. Saya mungkin salah paham kalimat ini di gitignorehalaman manual: "Pola membaca dari file .gitignore di direktori yang sama dengan path, atau di direktori induk mana pun (...)" Apakah itu sebenarnya berhenti pada akar checkout (yaitu di mana yang .gitdirektori)?
Gilles
1
Ya, pencarian ke atas .gitignorefile dibatasi oleh root dari pohon yang berfungsi. Kalimat yang Anda kutipkan berlanjut: "(hingga tingkat tertinggi pohon kerja)".
Chris Johnsen
@ Chris: versi halaman manual saya tidak memiliki kata-kata ini - sepertinya kata-katanya telah diklarifikasi. Saya sudah mengoreksi jawaban saya. Terima kasih!
Gilles
ini telah dibahas dalam obrolan baru
strugee
11

Kita dapat menggunakan kemampuan Git untuk melanjutkan melacak file walaupun mereka terdaftar .gitignore. Jadi, ini cukup untuk .gitignore:

$ cat .gitignore
/*

Untuk setiap file yang ingin Anda lacak, jalankan add -f( -fparameter menimpa mengabaikan keduanya di .gitignoredan .git/info/exclude):

git add -f .gitignore
git add -f .profile
git add -f .zshrc
git add -f .ssh/config

Setelah mengindeks file, Git akan melacak semua perubahan meskipun faktanya file tersebut diabaikan. Hal yang sama berfungsi untuk direktori, tetapi hanya untuk file yang benar-benar ada:

git add -f somedirname

Jika Anda ingin melacak seluruh direktori dengan semua file baru yang muncul di dalamnya, itu dapat dikecualikan dari .gitignoredengan cara, dijelaskan dalam jawaban oleh camh :

!/somedirname

Jika Anda ingin berhenti melacak file, perintah ini menghapus file dari indeks Git tetapi membiarkannya tidak tersentuh di hard drive:

git rm --cached .ssh/config
Nick Volynkin
sumber
1
Saya akan memberikan poin saya jika saya bisa. Jika perlu dicatat bahwa metode ini hanya dapat digunakan untuk melacak file, bukan direktori. Jika Anda ingin git melacak semua file dalam direktori, Anda masih harus mengabaikan direktori tersebut di .gitignore. Kalau tidak, file baru di direktori itu tidak akan muncul sebagai file baru.
camh
5

Saya menggunakan yang lama rcsuntuk itu.

Silahkan lihat pada halaman manual untuk ci, co, dan rcs. Situs-situs itu juga harus membantu:

Saya menggunakannya untuk versi yang mengontrol dotfiles saya misalnya:

ci -u .*vimrc

Dan jika saya ingin mengeditnya:

co -l .*vimrc

Saya sarankan membuat direktori bernama RCSdi Anda ~, Anda kemudian dapat dengan mudah membuat cadangan direktori itu di suatu tempat.

polemon
sumber
2
rcs sudah cukup kuno sekarang, dan git melakukan semua yang dilakukan rcs dan masih banyak lagi. Saya dulu menggunakan rcs untuk apa pun yang lokal di mana saya tidak ingin overhead mengatur repositori di server, tapi saya sudah benar-benar beralih ke git sekarang untuk jenis penggunaan. Saya bahkan menulis sebuah skrip yang membungkus cvs2git untuk mengkonversi hierarki direktori yang ada dengan file rcs di dalamnya menjadi git.
Neil Mayhew
1
Ya, saya tahu tanggalnya. Pertanyaannya adalah untuk tip tentang bagaimana melakukan itu. Saya baru saja memberi tahu orang ini bagaimana saya telah melakukannya selama bertahun-tahun ("berkencan", isyarat, isyarat). Itu tidak dimaksudkan dengan cara bahwa itu adalah satu-satunya cara yang masuk akal untuk melakukannya.
polemon
5

Saya memeriksa file konfigurasi saya $HOME/.conf/dari repositori BitBucket Mercurial. Repo GitHub juga bisa digunakan.

The ~/.confcheckout berisi file konfigurasi dan script shell untuk mengisi symlink di $HOMEsetiap file dalam ~/.conf. Untuk format config yang mendukung inklusi ( .bashrc, .inputrc, .vimrc, dll) saya termasuk ~/.conffile yang bukan link untuk itu, sehingga saya bisa melakukan menimpa lokal.

Untuk beberapa file konfigurasi, saya menyinkronkan ke file di folder Dropbox saya dan berbagi melalui dropbox.

Selama beberapa bulan saya mencoba menjaga $HOMEdirinya sendiri dalam kontrol versi, tapi saya lelah mengelola daftar abaikan besar-besaran, saya lelah memeriksa perubahan konfigurasi yang dibuat dengan menjalankan aplikasi, dan hasilnya bahkan bukan sesuatu yang ingin saya periksa di komputer lain. Dapatkah Anda membayangkan memperbaiki konflik ~/.gconfatau ~/.config/monitors.xml, atau melayani berbagai versi aplikasi desktop?

Saya merasa lebih mudah untuk melakukan symlink ke atau menyertakan daftar terbatas file konfigurasi yang telah saya sesuaikan secara pribadi dan ingin saya bagikan di seluruh mesin sebagai standar global.

Graham
sumber
3

Saya baru saja mulai menggunakan skrip Python Dotfiles berikut, yang merupakan alat praktis yang secara otomatis menautkan file untuk Anda: https://pypi.python.org/pypi/dotfiles

trojjer
sumber
1

Saya pikir firasat kedua Anda untuk memiliki folder yang tidak terkait di bawah kendali sumber baik.

Tambahkan saja 2 skrip shell di sana. Satu untuk menyalin file di bawah kendali Anda ke ~dan yang lain untuk mengumpulkan file dari ~dan menyalinnya kembali ke folder yang dikendalikan sumber dan komit.

Alexander Pogrebnyak
sumber
0

Ini adalah skrip ruby ​​kecil yang saya gunakan untuk mengatur mesin baru

#!/usr/bin/env ruby
# setup.rb

#list of dirs which you don't want to symlink
ignored = %w(.gitignore .gitmodules misc setup.rb readme)

current_dir = File.expand_path(Dir.pwd)
home_dir = File.expand_path("~")

links = `git ls-tree --name-only HEAD`.lines.map(&:strip).select {|x| !ignored.include?(x)  }

links.each do |link|
  link = File.join(current_dir, link)
  symlink = File.join(home_dir, File.basename(link))
  `ln -ns #{link} #{symlink}`
end
Khaja Minhajuddin
sumber