Советы по переводу ~ под контроль исходного кода


77

Я хочу поставить свой домашний каталог (~) под контроль исходного кода (в данном случае git), так как у меня есть много файлов настроек (.gitconfig, .gitignore, .emacs и т. Д.), Которые я хотел бы переносить на разные машины, и иметь их в Git было бы неплохо для их извлечения.

Моим основным компьютером является мой MacBook, и при настройке OS X есть много папок, которые я хочу игнорировать (Documents, Downloads, .ssh). Есть также папки, которые уже используют Git (.emacs.d).

Я думал просто добавить все эти каталоги в мой файл .gitignore, но это кажется утомительным и может привести к непредвиденным последствиям. Моей следующей мыслью было периодически копировать файлы, которые я хочу сохранить, в какую-то домашнюю папку, а затем фиксировать эту папку. Проблема с этим будет в том, что я должен помнить, чтобы переместить их перед фиксацией.

Есть ли чистый способ сделать это?


Вы также можете создать скрипт, выполняющий фиксацию нужных вам папок и вызывая его через cronjobs.
Шадок

Обратите внимание, что файловая система 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 переходили в git. Выше, как я этого добиваюсь.

Редактировать: добавлены косые черты в начало всех путей. Это позволяет сопоставлять шаблоны игнорирования в верхней части репозитория ($ HOME), а не в любом месте. Например, если !lib/был шаблон (не игнорируйте все в каталоге lib) и вы добавляете файл .gitignore, ранее шаблон ( !.gitignore) соответствовал этому. С ведущей косой чертой ( !/.gitignore) он будет совпадать только .gitignoreв моем домашнем каталоге, а не в каких-либо подкаталогах.

Я не видел случая, чтобы это имело практическое значение с моим списком игнорирования, но мне кажется, что оно более технически точно.


1
Мне кажется, что того же можно достичь гораздо более простым способом .
Ник Волынкин

24

Что мне делать ? (С теми же целями), чтобы поместить мои файлы конфигурации в подкаталоге ~/libи имеют символические ссылки в моей домашней директории, например, .emacs -> lib/emacs/dot.emacs. Я храню только файлы конфигурации, которые я написал явно, под контролем версий; Мой домашний каталог содержит множество автоматически созданных точечных файлов, которые не находятся под контролем версий. Таким образом, ~/libнаходится под контролем версий, а мой домашний каталог - нет.

У меня есть скрипт, который создает символические ссылки из файлов в ~/lib. Когда я создаю учетную запись на новом компьютере, я заполняю ее, проверяя ~/libи выполняя этот скрипт.

Мой опыт работы с CVS, а не с git, так что это не на 100%. Одна из причин, по которой я не поместил свой домашний каталог непосредственно в CVS, заключается в том, что ~/.cvsignoreэто относится ко всем моим проверкам CVS, а не только к моему домашнему каталогу; У мерзости нет этой проблемы. Недостатком этого подхода по сравнению с наличием домашнего каталога под управлением версиями является то, что вы не можете использовать git statusдля разграничения файла, который вы явно решили игнорировать (который будет указан в файле игнорирования, поэтому не отображается), и файл, о котором у вас нет мнения (который будет отображаться с ?).

Некоторые файлы должны быть разными на разных машинах. Я помещаю их в каталог с именем ~/Local/SITENAME/libи создаю для них также символические ссылки, или (для форматов файлов, которые его поддерживают) в файле есть директива include ~/lib. У меня также есть символическая ссылка ~/Here -> ~/Local/SITENAME. Поскольку git, в отличие от CVS, предназначен для поддержки, в основном, аналогичных, но не идентичных репозиториев, может существовать лучший способ управления файлами, специфичными для компьютера. Некоторые из моих точечных файлов на самом деле не являются символическими ссылками, но автоматически генерируются из содержимого в ~/libи ~/Here.


Может быть, у вас есть core.excludesfile = ~/.gitignore. Без такой конфигурации файл не применяется ни к одному хранилищу, кроме одного, хранящегося в нем ~/.git(даже в этом случае он не будет применяться к вложенным хранилищам). Я использую core.excludefile =, ~/.git-user-excludesчтобы избежать конфликта между исключениями, которые я хочу применить ко всем моим репозиториям Git (независимо от местоположения), и исключением, которое я хочу применить к репозиторию, который содержит (части) моего домашнего каталога.
Крис Джонсен

@ Крис: я знаю очень мало о мерзавце. Возможно, я неправильно понял это предложение на gitignoreстранице руководства : «Шаблоны, считанные из файла .gitignore в том же каталоге, что и путь, или в любом родительском каталоге (…)». Останавливается ли это на самом деле в корне извлечения (т. Е. Где .gitкаталог)?
Жиль "ТАК - перестань быть злым"

1
Да, поиск .gitignoreфайлов вверх ограничен корнем рабочего дерева. Приведенное вами предложение продолжает: «(до верхнего уровня рабочего дерева)».
Крис Джонсен

@Chris: моя версия справочной страницы не содержит этих слов - похоже, формулировка прояснена. Я исправил свой ответ. Спасибо!
Жиль "ТАК - перестать быть злым"


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
Я бы дал вам свои очки, если бы мог. Следует отметить, что этот метод можно использовать только для отслеживания файлов, а не каталогов. Если вы хотите, чтобы git отслеживал все файлы в каталоге, вам все равно нужно игнорировать этот каталог в .gitignore. В противном случае новые файлы в этом каталоге не будут отображаться как новые файлы.
Съемка

5

Я использую старое rcsдля этого.

Посмотрите на страницах руководства для ci, coи rcs. Эти сайты также должны быть полезны:

Я использую это для контроля версий моих файлов точек, например:

ci -u .*vimrc

И если я хочу редактировать их:

co -l .*vimrc

Я рекомендую создать каталог с именем RCSв вашем ~, вы можете легко создать резервную копию этого каталога где-нибудь.


2
rcs довольно устарел, и git делает все, что делает rcs, и многое другое. Раньше я использовал rcs для всего локального, где я не хотел накладных расходов на установку репозитория на сервере, но теперь я полностью переключился на git для этого типа использования. Я даже написал скрипт, который оборачивает cvs2git для преобразования существующей иерархии каталогов с файлами rcs в нее в git.
Нил Мэйхью

1
Да, я знаю, что это от. Вопрос был о том, как это сделать. Я только что рассказал этому парню, как я делал это много, много лет («датировано», подсказка, подсказка). Это не означает, что это единственный разумный способ сделать это.
Полемон

5

Я $HOME/.conf/извлекаю свои файлы конфигурации из репозитория BitBucket Mercurial. Репозиторий GitHub будет работать так же хорошо.

Оформление ~/.confзаказа содержит файлы конфигурации и сценарий оболочки для заполнения символических ссылок $HOMEна каждый файл в ~/.conf. Для форматов конфигурации , которые поддерживают включение ( .bashrc, .inputrc, .vimrcи т.д.) я включаю ~/.confфайл , а не ссылку на него, так что я могу сделать местное переопределение.

Для некоторых конфигурационных файлов я символическую ссылку на файл в моей папке Dropbox и делиться через Dropbox.

В течение нескольких месяцев я пытался держать $HOMEсебя в управлении версиями, но мне надоело управлять огромными списками игнорирования, я устал проверять изменения конфигурации, сделанные при запуске приложений, и в результате я даже не захотел проверить это на другом компьютере. Можете ли вы представить, как разрешать конфликты ~/.gconfили ~/.config/monitors.xmlили предлагать разные версии настольных приложений?

Мне проще найти символическую ссылку или включить ограниченный список конфигурационных файлов, которые я лично настроил и хочу использовать на разных компьютерах в качестве глобальных настроек по умолчанию.


3

Я только начал использовать следующий скрипт Python Dotfiles, который является удобным инструментом, который автоматически связывает файлы для вас: https://pypi.python.org/pypi/dotfiles


1

Я думаю, что ваша вторая догадка о том, что несвязанная папка находится под контролем исходного кода, хороша.

Просто добавьте туда 2 сценария оболочки. Один для копирования файлов, находящихся под вашим контролем, ~а другой для сбора файлов ~и их копирования обратно в папку, контролируемую исходным кодом, и фиксации.


0

Вот небольшой скрипт ruby, который я использую для настройки новой машины

#!/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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.