เคล็ดลับสำหรับการวาง ~ ภายใต้การควบคุมของแหล่งที่มา


77

ฉันต้องการวางโฮมไดเร็กตอรี่ของฉัน (~) ภายใต้การควบคุมของแหล่งที่มา (git, ในกรณีนี้), เนื่องจากฉันมีไฟล์การตั้งค่ามากมาย (.gitconfig, .gitignore, .emacs, ฯลฯ ) ที่นั่นฉันอยากจะพกพาข้ามเครื่อง และการมี Git จะทำให้การดึงพวกเขาดีขึ้น

เครื่องหลักของฉันคือ MacBook ของฉันและวิธีการตั้งค่า OS X มีหลายโฟลเดอร์ที่ฉันต้องการข้าม (เอกสาร, ดาวน์โหลด, .ssh) นอกจากนี้ยังมีโฟลเดอร์ที่ใช้ Git (.emacs.d) อยู่แล้ว

ความคิดของฉันคือการเพิ่มไดเรกทอรีเหล่านี้ทั้งหมดไปยังไฟล์. gitignore ของฉัน แต่ดูเหมือนว่าจะน่าเบื่อและอาจทำให้เกิดผลที่คาดไม่ถึง ความคิดต่อไปของฉันคือการคัดลอกไฟล์ที่ฉันต้องการจัดเก็บลงในโฟลเดอร์บางโฟลเดอร์ในบ้านเป็นระยะ ๆ จากนั้นส่งมอบโฟลเดอร์นั้น ปัญหาที่เกิดขึ้นคือฉันต้องจำให้ย้ายพวกเขาก่อนที่จะกระทำ

มีวิธีที่สะอาดในการทำเช่นนี้หรือไม่?


นอกจากนี้คุณยังสามารถสร้างสคริปต์ที่ดำเนินการในโฟลเดอร์ที่คุณต้องการและเรียกมันผ่าน cronjobs
Shadok

โปรดทราบว่าระบบไฟล์ HFS + เริ่มต้นบน Mac OS X นั้นไม่ตรงตามตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (แต่จะต้องคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่) และพา ธ ของไฟล์นั้นจะถูกเข้ารหัสใน UTF-8 ที่ย่อยสลายตามมาตรฐานในพื้นที่ผู้ใช้! สำหรับข้อมูลเพิ่มเติมโปรดดูที่: <a href=" stackoverflow.com/questions/5581857/…และปัญหา Umlaut บน Mac OS X</a>

คำตอบ:


60

ฉันมี$HOMEภายใต้คอมไพล์ บรรทัดแรกของไฟล์. gitignore ของฉันคือ

/*

ส่วนที่เหลือเป็นรูปแบบที่จะไม่เพิกเฉยโดยใช้!ตัวปรับแต่ง บรรทัดแรกนี้หมายถึงค่าเริ่มต้นคือละเว้นไฟล์ทั้งหมดในโฮมไดเร็กตอรี่ของฉัน ไฟล์ที่ฉันต้องการควบคุมเวอร์ชันจะเป็น.gitignoreดังนี้:

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

แบบแผนที่ฉันมีคือ:

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

นั่นคือฉันต้องการรุ่นเท่านั้น.ssh/config- ฉันไม่ต้องการให้คีย์และไฟล์อื่น ๆ ใน. ssh เข้าสู่ระบบคอมไพล์ ด้านบนเป็นวิธีการที่ฉันประสบความสำเร็จ

แก้ไข: เพิ่มเครื่องหมายทับเพื่อเริ่มต้นเส้นทางทั้งหมด สิ่งนี้ทำให้รูปแบบการเพิกเฉยตรงกับด้านบนของที่เก็บ ($ HOME) แทนที่จะเป็นที่ใดก็ได้ ตัวอย่างเช่นถ้า!lib/เป็นรูปแบบ (อย่าเพิกเฉยทุกอย่างในไดเรกทอรี lib) และคุณเพิ่มไฟล์.gitignoreก่อนหน้านี้รูปแบบ ( !.gitignore) นั้นตรงกับที่ ด้วยเครื่องหมายทับ ( !/.gitignore) มันจะจับคู่.gitignoreในไดเรกทอรีบ้านของฉันเท่านั้นและไม่อยู่ในไดเรกทอรีย่อยใด ๆ

ฉันไม่ได้เห็นกรณีที่สิ่งนี้สร้างความแตกต่างในทางปฏิบัติกับรายการเพิกเฉยของฉัน แต่ดูเหมือนว่าฉันจะมีความแม่นยำทางเทคนิคมากกว่า


1
สำหรับผมแล้วดูเหมือนว่าสามารถทำได้ในวิธีที่ง่ายกว่ามาก
Nick Volynkin

24

สิ่งที่ฉันทำ (มีวัตถุประสงค์เดียวกัน) คือการใส่แฟ้มการกำหนดค่าของฉันในไดเรกทอรีย่อยและมีการเชื่อมโยงสัญลักษณ์ในไดเรกทอรีบ้านของฉันเช่น~/lib .emacs -> lib/emacs/dot.emacsฉันเก็บเฉพาะไฟล์คอนฟิกูเรชันที่ฉันเขียนไว้อย่างชัดเจนภายใต้การควบคุมเวอร์ชัน โฮมไดเร็กตอรี่ของฉันมีไฟล์จุดที่สร้างขึ้นโดยอัตโนมัติซึ่งไม่อยู่ภายใต้การควบคุมเวอร์ชัน ดังนั้นจึง~/libอยู่ภายใต้การควบคุมเวอร์ชันและไดเรกทอรีบ้านของฉันไม่

ฉันมีสคริปต์ที่สร้างลิงก์สัญลักษณ์จากไฟล์ด้าน~/libล่าง เมื่อฉันสร้างบัญชีบนเครื่องใหม่ฉันเติมโดยการตรวจสอบ~/libและเรียกใช้สคริปต์นั้น

ประสบการณ์ของฉันอยู่กับ CVS ไม่ใช่ git ดังนั้นจึงไม่สามารถถ่ายโอนได้ 100% หนึ่งในเหตุผลที่ฉันไม่ได้ใส่ไดเร็กตอรี่โฮมของฉันโดยตรงภายใต้ CVS คือนั่น~/.cvsignoreจะใช้กับการชำระเงิน CVS ทั้งหมดของฉันและไม่ใช่แค่ไดเร็กตอรี่โฮมของฉัน; git ไม่มีปัญหานี้ ข้อเสียของวิธีการนั้นเมื่อเทียบกับการมีโฮมไดเร็กตอรี่ภายใต้การควบคุมเวอร์ชันคือคุณไม่สามารถใช้git statusแยกความแตกต่างระหว่างไฟล์ที่คุณตัดสินใจที่จะเพิกเฉยได้อย่างชัดเจน (ซึ่งจะแสดงอยู่ในไฟล์ละเว้น ไฟล์ที่คุณไม่มีความคิดเห็นเกี่ยวกับ (ซึ่งจะแสดงด้วย?)

ไฟล์บางไฟล์จำเป็นต้องแตกต่างกันไปในเครื่องที่แตกต่างกัน ฉันใส่ไว้ในไดเรกทอรีที่เรียกว่า~/Local/SITENAME/libและสร้างการเชื่อมโยงสัญลักษณ์สำหรับพวกเขาเช่นกันหรือ (สำหรับรูปแบบไฟล์ที่สนับสนุนมัน) ~/libมีการรวมคำสั่งในไฟล์ที่อยู่ภายใต้ ~/Here -> ~/Local/SITENAMEฉันยังมีการเชื่อมโยงสัญลักษณ์ เนื่องจาก git ซึ่งแตกต่างจาก CVS ได้รับการออกแบบมาเพื่อรองรับที่เก็บข้อมูลที่คล้ายกัน แต่ไม่เหมือนกันส่วนใหญ่อาจมีวิธีที่ดีกว่าในการจัดการไฟล์เฉพาะเครื่อง ไม่กี่ไฟล์จุดของฉันในความเป็นจริงไม่เชื่อมโยงสัญลักษณ์ แต่สร้างขึ้นโดยอัตโนมัติจากเนื้อหาภายใต้และ~/lib~/Here


บางทีคุณอาจมีcore.excludesfile~/.gitignore = หากไม่มีการกำหนดค่าดังกล่าวไฟล์จะไม่ถูกนำไปใช้กับที่เก็บใด ๆ ยกเว้นที่เก็บไว้ใน~/.git(แม้จะไม่สามารถใช้กับที่เก็บย่อย) ฉันใช้core.excludesfile = ~/.git-user-excludesเพื่อหลีกเลี่ยงความขัดแย้งระหว่างการแยกที่ฉันต้องการนำไปใช้กับที่เก็บ Git ทั้งหมดของฉัน (โดยไม่คำนึงถึงสถานที่) และการยกเว้นที่ฉันต้องการนำไปใช้กับที่เก็บที่มีไดเรกทอรีของบ้านของฉัน
Chris Johnsen

@ Chris: ฉันรู้น้อยมากเกี่ยวกับคอมไพล์ ฉันอาจเข้าใจผิดประโยคนี้ในgitignoreหน้า man:“ รูปแบบที่อ่านจากไฟล์. gitignore ในไดเรกทอรีเดียวกันกับเส้นทางหรือในไดเรกทอรีหลัก (…)” อันที่จริงแล้วมันหยุดที่รากของเช็คเอาต์หรือไม่.gitไดเรกทอรี)?
Gilles

1
ใช่การค้นหา.gitignoreไฟล์ขึ้นไปนั้นถูก จำกัด โดยรูทของแผนผังการทำงาน ประโยคที่คุณยกมานั้นยังคงดำเนินต่อไป:“ (จนถึงส่วนบนของแผนผังการทำงาน)”
Chris Johnsen

@Chris: หน้า man version ของฉันไม่มีคำเหล่านี้ - ดูเหมือนว่าถ้อยคำได้รับการชี้แจงแล้ว ฉันแก้ไขคำตอบของฉันแล้ว ขอบคุณ!
Gilles

เรื่องนี้ถูกกล่าวถึงในการแชทเมื่อไม่นานมานี้
ย้ายถิ่นฐาน

11

เราสามารถใช้ความสามารถของ Git ในการติดตามไฟล์ต่อไปแม้ว่าจะอยู่ในรายการ.gitignoreก็ตาม ดังนั้นนี่เพียงพอสำหรับ.gitignore:

$ cat .gitignore
/*

สำหรับแต่ละไฟล์ที่คุณต้องการติดตามให้รันadd -f( -fพารามิเตอร์แทนที่ไม่สนใจทั้งใน.gitignoreและ.git/info/exclude):

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

เมื่อทำการจัดทำดัชนีไฟล์แล้ว Git จะติดตามการเปลี่ยนแปลงทั้งหมดแม้จะถูกเพิกเฉยก็ตาม การทำงานแบบเดียวกันสำหรับไดเรกทอรี แต่สำหรับไฟล์ที่มีอยู่จริงเท่านั้น:

git add -f somedirname

หากคุณต้องการติดตามทั้งไดเรกทอรีด้วยไฟล์ใหม่ทั้งหมดที่ปรากฏอยู่ในไดเรกทอรีดังกล่าวคุณสามารถยกเว้นได้.gitignoreในลักษณะที่อธิบายไว้ในคำตอบโดย camh :

!/somedirname

หากคุณต้องการหยุดการติดตามไฟล์คำสั่งนี้จะลบไฟล์ออกจากดัชนีของ Git แต่จะไม่ถูกแตะต้องบนฮาร์ดไดรฟ์:

git rm --cached .ssh/config

1
ฉันจะให้คะแนนถ้าคุณทำได้ หากควรสังเกตว่าวิธีนี้สามารถใช้เพื่อติดตามไฟล์เท่านั้นไม่ใช่ไดเรกทอรี หากคุณต้องการให้คอมไพล์ติดตามไฟล์ทั้งหมดในไดเรกทอรีคุณจะต้องยกเลิกการเพิกเฉยไดเรกทอรีนั้นใน. gitignore มิฉะนั้นไฟล์ใหม่ในไดเรกทอรีนั้นจะไม่ปรากฏเป็นไฟล์ใหม่
camh

5

ฉันใช้ของเก่าrcsสำหรับสิ่งนั้น

มีลักษณะที่ manpages สำหรับci, และco rcsเว็บไซต์เหล่านั้นควรมีประโยชน์เช่นกัน:

ฉันใช้สิ่งนั้นสำหรับเวอร์ชันที่ควบคุม dotfiles ของฉันเช่น:

ci -u .*vimrc

และถ้าฉันต้องการแก้ไข:

co -l .*vimrc

ฉันขอแนะนำให้สร้างไดเรกทอรีRCSในชื่อของ~คุณจากนั้นคุณสามารถสำรองข้อมูลไดเรกทอรีนั้นได้อย่างง่ายดาย


2
rcs เป็นวันที่สวยตอนนี้และคอมไพล์ทำทุกอย่าง rcs และอื่น ๆ อีกมากมาย ฉันเคยใช้ rcs สำหรับทุก ๆ ที่ที่ฉันไม่ต้องการค่าใช้จ่ายในการตั้งค่าพื้นที่เก็บข้อมูลบนเซิร์ฟเวอร์ แต่ฉันได้เปลี่ยนไปใช้คอมไพล์อย่างสมบูรณ์สำหรับการใช้งานประเภทนั้น ฉันยังเขียนสคริปต์ที่ล้อม cvs2git เพื่อแปลงลำดับชั้นไดเรกทอรีที่มีอยู่กับไฟล์ rcs ในนั้นเพื่อ git
Neil Mayhew

1
ใช่ฉันรู้ว่ามันเป็นวันที่ คำถามคือเคล็ดลับในการทำเช่นนั้น ฉันเพิ่งบอกผู้ชายคนนี้ว่าฉันได้ทำมาหลายปีแล้ว ("วันที่" คำใบ้คำใบ้) มันไม่ได้มีความหมายในทางที่เป็นวิธีเดียวที่สมเหตุสมผลที่จะทำ
polemon

5

ฉันตรวจสอบไฟล์กำหนดค่าของฉัน$HOME/.conf/จากที่เก็บ BitBucket Mercurial repo ของ GitHub ก็ใช้ได้เช่นกัน

~/.confเช็คเอาต์มี config ไฟล์และเชลล์สคริปต์เพื่อเติม symlinks ในแต่ละแฟ้มใน$HOME ~/.confสำหรับรูปแบบการตั้งค่าที่สนับสนุนการรวม ( .bashrc, .inputrc, .vimrcฯลฯ ) ผมรวมถึง~/.confไฟล์แทนที่จะเชื่อมโยงไปเพื่อที่ฉันสามารถทำแทนที่ท้องถิ่น

สำหรับไฟล์ config บางตัวฉัน symlink ไปยังไฟล์ในโฟลเดอร์ Dropbox ของฉันและแชร์ผ่านดรอปบ็อกซ์

เป็นเวลาหลายเดือนที่ฉันพยายามรักษา$HOMEตัวเองในการควบคุมเวอร์ชัน แต่ฉันเบื่อกับการจัดการรายการเพิกเฉยขนาดใหญ่ฉันเบื่อที่จะตรวจสอบการเปลี่ยนแปลงการกำหนดค่าที่เกิดขึ้นจากการเรียกใช้แอพและผลลัพธ์ก็ไม่ได้เป็นอย่างที่ฉันต้องการ คุณนึกภาพการแก้ไขข้อขัดแย้ง~/.gconfหรือ~/.config/monitors.xmlหรือจัดเลี้ยงแอพเดสก์ท็อปเวอร์ชันที่แตกต่างกันหรือไม่

ฉันพบว่าการ symlink ไปยังหรือรวมรายการกำหนดค่าของไฟล์กำหนดค่าที่ฉันกำหนดเองเป็นการส่วนตัวและต้องการแชร์ข้ามเครื่องเป็นค่าเริ่มต้นระดับโลก


3

ฉันเพิ่งเริ่มใช้สคริปต์ Python Dotfiles ต่อไปนี้ซึ่งเป็นเครื่องมือที่มีประโยชน์ที่เชื่อมโยงไฟล์ให้คุณโดยอัตโนมัติ: https://pypi.python.org/pypi/dotfiles


1

ฉันคิดว่าลางสังหรณ์ที่สองของคุณที่จะมีโฟลเดอร์ที่ไม่เกี่ยวข้องภายใต้การควบคุมแหล่งที่ดี

เพียงเพิ่ม 2 เชลล์สคริปต์ที่นั่น หนึ่งในการคัดลอกไฟล์ภายใต้การควบคุมของคุณไปยัง~และอื่น ๆ เพื่อรวบรวมไฟล์จาก~และคัดลอกกลับไปที่โฟลเดอร์ควบคุมแหล่งที่มาและกระทำ


0

นี่คือสคริปต์ทับทิมเล็ก ๆ ที่ฉันใช้ในการตั้งค่าเครื่องใหม่

#!/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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.