Как ни странно, я только недавно познакомился с VCHS — надстройкой над Git, призванной облегчить резервирование конфигурационных файлов, расположенных в домашней директории (Version control system for $HOME
— один из вариантов расшифровки аббревиатуры). Очень жаль, что этого не произошло раньше, и бэкап конфигов делался нерегулярно, кое-как, с изобретением различных костылей. Но, всё это в прошлом! Итак, что же представляет собой VCSH и как ей пользоваться?
Сильные стороны VCSH
Первое преимущество использования VCSH по сравнению с чистым git — конфиги остаются лежать в домашней директории, а история их изменений хранится отдельно в каталоге ${HOME}/.config/vcsh/repo.d
, что позволяет группировать файлы конфигов в разные наборы, хранящиеся в отдельных репозиториях и не зависящие друг от друг. Зачем это нужно? Таким способом можно синхронизировать на нескольких машинах только нужные везде конфиги, не таская лишние настройки повсюду. Например — иметь одинаковые настройки Vim и bash на локальной и удаленной машинах, не перенося конфиг mplayer на сервер, где и самого-то плеера нет. Еще плюс — $HOME
является для VCSH рабочей директорией, что позволяет при помощи git status
получить информацию об изменении существующих или появлении новых файлов в $HOME
(кроме перечисленных в .gitignore), например — сведения о конфигах, созданных в процессе установки какой-то программы.
Установка, настройка
Установка в Debian элементарна, места VCSH требует совсем немного:
dimio@ibm $ sudo aptitude install vcsh
Следующие НОВЫЕ пакеты будут установлены:
libio-pty-easy-perl{a} libio-pty-perl{a} mr{a} myrepos{a} vcsh
0 пакетов обновлено, 5 установлено новых, 0 пакетов отмечено для удаления, и 0 пакетов не обновлено.
Необходимо получить 121 kB архивов. После распаковки 434 kB будет занято.
Как видно из списка устанавливаемых пакетов, VCSH в работе использует perl с библиотеками для создания псевдотерминалов и утилиту для массового управления репозиториями — myrepos. Сам git у меня уже стоит, потому он и его зависимости — отсутствуют в списке устанавливаемых пакетов.
Также перед началом работы имеет смысл сделать резервную копию всех конфигов, расположенных в домашней директории:
find ${HOME} -maxdepth 1 -name ".?*" ! \( -name .thumbnails \) -exec tar zcfv dotfiles_dotdirs_backup.tgz {} +
В этот архив попадут, конечно, не только конфиги, но и разнообразный мусор (типа кэша, файлов предпросмотра, временных файлов и т.п.), который из-под контроля git нужно будет исключить.
Начало работы с VCSH
Теперь можно приступить к работе непосредственно с VCSH — для начала — инициализировать новый репозиторий, расположенный в ${HOME}
и содержащий в себе все файлы и каталоги с настройками, найденные в домашней директории:
$ cd # переход в $HOME
# инициализация нового репозитория
# (название, конечно, стоит поменять на своё)
# опция -v указана для более подробного вывода
$ vcsh -v init dimio_ibm_dotfiles_all
verbose mode on
vcsh 1.20141026
vcsh: verbose: attempting to create ‘/home/dimio/.config/vcsh/repo.d’
vcsh: verbose: attempting to create ‘/home/dimio/.gitignore.d’
vcsh: verbose: init begin
Initialized empty shared Git repository in /home/dimio/.config/vcsh/repo.d/dimio_ibm_dotfiles_all.git/
vcsh: verbose: init end, exiting
Стоит сразу же настроить правила для невключения посторонних файлов в новый репозиторий — создать .gitinore для него: vcsh write-gitignore dimio_ibm_dotfiles_all
и отредактировать (vim ~/.gitignore.d/dimio_ibm_dotfiles_all
), внеся следующие изменения (исключенные с помощью .gitinore файлы и директории git обрабатывать не будет, проверять действие правил можно при помощи git status
):
## Ignore all files/dirs
*
# but not dotfiles/dotdirs
!.*
!.*/**
## Programs
.wine/
.gnupg/
.python-eggs/
.tor/
# Ignore some vcsh dirs/files
.config/vcsh/**/objects/
.config/vcsh/**/info/
.config/vcsh/**/index
.config/vcsh/**/refs/
.config/vcsh/**/COMMIT_EDITMSG
# Ignore maildir
.Mail/
# Ignore chromium dirs
# but not settings, passwords, bookmarks etc
.config/chromium/*
!.config/chromium/Default/
.config/chromium/Default/*
!.config/chromium/Default/Bookmarks
!.config/chromium/Default/Login Data
.pki/
# same for elinks
.elinks/*
!.elinks/bookmarks
!.elinks/elinks.conf
# Ignore all vim files
.vim/*
.vim/view/*
# but not self made
!.vim/filetype.vim
!.vim/ftdetect/
!.vim/mojo.vim
!.vim/perl-support/codesnippets/
!.vim/sessions/
!.vim/syntax/conkyrc.vim
## Games
# Ignore all games dirs
# (see dimio_ibm_games repo)
.snes96_snapshots/
.wesnoth/
.freeciv*
.exult*
.abuse/
.gens/
.s9x/
.scummvm/
## Temporary, logs, auto backups etc
*.tmp
*.temp
t?mp/
tmp.*
*~
~*
*.bak
*.log
*.lock
*history
*cookie?
*.so
# Ignore "chache" files/dirs
**/*[Cc]ache
# Ignore lib, log etc dirs
**/lib
**/logs
**/packages
**/share
## Media
*.png
*.jpeg
*.jpg
*.ogg
*.mp[34]
*.mpeg
*.mpg
*.jpg
*.flv
*.ttf
**/[Ff]avicon*
**/icons
.gstreamer-*/
# Ignore all thumbnails dirs
?thumbnails/
# Ignore flash player dirs
.adobe/
.macromedia/
## Unnecessary files
.cabal/*
!.cabal/config
.config/enchant/
.config/menus/
.config/pulse/
Синтаксис .gitignore простой: # - комментарий, ! - инверсия правила (не игнорировать подпавшие под правило файлы/каталоги), * - 0 или больше любых символов, ** - любой уровень вложенности каталога
(подробней тут).
После проверки репозитория на предмет попадания в него лишнего, правила игнорирования можно будет уточнить и дополнить.
Теперь нужно перейти в рабочий режим оболочки vcsh, который обеспечивает применение команд git непосредственно к «загруженному» в данный момент репозиторию, добавить в репозиторий нужные файлы/директории и сохранить их текущее состояние:
$ vcsh enter dimio_ibm_dotfiles_all
# добавить к отслеживанию всю рабочую область
# текущего репозитория
git add :/
# сделать начальный коммит
git commit -m 'Initial commit'
Для сброса внесенных изменений можно использовать git reset
, также может быть полезным в работе сравнение режимов работы git add
в разных сочетаниях и для разных версий git.
Выход из режима оболочки vcsh — по нажатию Ctrl+D
или по команде exit
.
Размещение репозитория с конфигами на удаленной машине
Копию репозитория имеет смысл разместить на удаленной машине, получив и резервирование, и возможность легко перенести настройки куда-то ещё. Основной репозиторий со всеми конфигами я решил разместить на BitBucket, так как он бесплатно предоставляет возможность использования приватного репозитория (напомню, что сам репозиторий для начала следует создать через веб-интерфейс BitBucket, а затем подставить его адрес в команду ниже; еще нужно не забыть добавить ключ для доступа к BitBucket при помощи ssh-add
).
git remote add origin 'git@bitbucket.org:dimio/my_new_repo_name.git'
git push origin master
Однако, перед передачей файлов на удаленный сервер, было бы неплохо зашифровать их, так как репозиторий может содержать приватную информацию, например — настройки браузера (среди которых могут быть сохраненные пароли) или логи чатов pidgin и т.п. Да и сами ключи шифрования, если не исключить их через .gitignore специально, тоже попадут в репозиторий вместе с директорией ~/.gnupg/.
Шифрование файлов в git при помощи фильтров
Я для шифрования репозитория решил использовать gpg, создав специально под эту задачу новый ключ. Ключ нужно генерировать безпарольный (на локальной машине файлы всё равно хранятся в открытом виде), иначе автоматическая расшифровка при загрузке файлов из сетевой копии (команда git checkout
) будет проблематичной.
# генерация gpg ключа
# все значения приняты по умолчанию,
# срок действия ключа не ограничен,
# пароль пустой, email: dimio@dimio.org
gpg --gen-key
# посмотреть информацию о ключе
gpg --fingerprint dimio@dimio.org
pub 1024R/1C9E9C65 2015-10-12
Отпечаток ключа = DBA7 327B 2049 05D2 928C A1B0 8309 4115 1C9E 9C65
uid Dmitry (GIT encrypt) "dimio @dimio.org"
sub 1024R/475149F7 2015-10-12
Теперь в .gitattributes нужного репозитория следует добавить фильтр для обработки (в данном случае — шифрования) нужных файлов (в случае с vcsh — сначала потребуется создать соответствующие каталог gitattributes.d и файл с атрибутами вручную, внимание — старые версии vcsh не поддерживают работу с отдельными файлами .gitattributes):
mkdir ~/.gitattributes.d
touch ~/.gitattributes.d/dimio_ibm_dotfiles_all
echo '* filter=gpg diff=gpg' > ~/.gitattributes.d/dimio_ibm_dotfiles_all
Здесь *
— шаблон, под который должны подпадать названия файлов, требующих шифровки/расшифровки, т.е. обрабатываться будут все файлы.
Затем нужно прописать использование свежесозданного .gitattributes в нужном репозитории, для этого есть несколько путей:
- Выполнить команду
git config core.attributesfile ~/.gitattributes.d/dimio_ibm_dotfiles_all
, находясь в режиме оболочки vcsh с загруженным репозиторием dimio_ibm_dotfiles_all; - Вручную внести информацию об используемом файле .gitattributes в настройки репозитория, отредактировав файл
~/.config/vcsh/repo.d/dimio_ibm_dotfiles_all.git/config
и добавив в секцию[core]
путь к .gitattributes:
[core]
attributesfile = .gitattributes.d/dimio_ibm_dotfiles_all
- В новых версиях vcsh может сработать команда
vcsh upgrade "repo_name"
, но в моей версии vcsh автоматическая обработка файла атрибутов отключена в коде программы (: ${VCSH_GITATTRIBUTES:=none}
) и этот способ не работает.
Следующий шаг — создание фильтров, отвечающих за шифрование/дешифровку файлов. Они вносятся в файл конфигурации репозитория: ~/.config/vcsh/repo.d/dimio_ibm_dotfiles_all.git/config
[filter "gpg"]
;decrypt
smudge = gpg -d -q --batch --no-tty
;encrypt
clean = gpg -ea --batch --no-tty -r 475149F7
;filter must succeed in order to make
;the stored contents usable
required
[diff "gpg"]
;replacement for standard diff
textconv = git-gpg-decrypt
Где 475149F7
— идентификатор созданного ранее приватного ключа gpg (взамен можно указать e-mail, прописанный в информации о ключе). А git-gpg-decrypt
— небольшой скрипт следующего содержания:
#!/bin/sh
gpg -d -q --batch --no-tty "$1" || cat "$1"
Путь к скрипту нужно внести в ${PATH}
: у меня он лежит в директории ${HOME}/bin/
, которая автоматически добавляется в ${PATH}
путем загрузки bash_path-expand из bashrc. Теперь просмотр изменений (типа git log -p -1
) будет работать корректно.
При желании, для шифрования репозиториев возможно применить специальную утилиту git-crypt, мне же подобное решение на данном этапе показалось избыточным.
А вот теперь можно вернуться к клонированию репозитория на сервер BitBucket (не забывая, что шифрование происходит на стадии подготовки к коммиту — при вызове команды git add
).
После записи изменений (git push
) в репоизторий на BitBucket — остается лишь убедиться, что фильтр сработал и шифрование прошло успешно. Для примера — вот так мой bashrc выглядит в репозитории BitBucket после совершения всего вышеописанного:
В заключение, для лучшего знакомства с git, могу смело порекомендовать отличную книгу ProGit, на материалы которой, среди прочего, я ссылался в этой заметке.
Слишком много телодвижений для решения задачи (особенно для развертывания на новом месте). После неудачного опыта использования, остановился на homesick
Просмотрел бегло на гитхабе:
— руби — мне не нужен и не установлен;
— симлинки в домашнем — от них избавлялся как раз.
Время ушло на составление и проверку правил gitignore, которые позволят полноценно мониторить через git status домашнюю директорию в нужном и достаточном объеме в целом (полагаю, homesick этот шаг никак не упростит). Отдельные частные репозитории, типа хранения настроек окружения или сохраненок от игр, таких затрат времени на разворачивание уже не потребуют.
Что у homesick с шифрованием?
Спасибо за полезную и интересную информацию!