Неразрушающая проверка Git в дереве грязной работы ($HOME/.dotfiles)

Эта проблема возникла при планировании другой системы управления Git .dotfiles. Я хочу использовать $HOME в качестве рабочего дерева и хранить репозиторий в другом месте (не под .git, так как это сбивает с толку другие репозитории).

На старых машинах с ранее скопированными и потенциально измененными dotfiles теперь я хотел бы клонировать мой новый репозиторий dotfiles и (махать руками) до состояния, в котором я могу видеть (ранее) существующее состояние мои $HOME/.* dotfiles как модификации мастера моего недавно клонированного репозитория. В основном это фон, в Git я просто хочу осторожно проверить в грязном каталоге без перезаписи.

(В обычном случае я мог бы просто начать с нового каталога, а затем скопировать свои изменения, но это кажется трудным, когда рабочее дерево — это мой $HOME.)

Я нашел одну пару команд, которая, похоже, привела меня в нужное место, но я не уверен, есть ли в этом подходе подводные камни или более простые способы сделать то же самое:

git read-tree -v HEAD # load HEAD into the index
git checkout-index -a # cautiously check out all files without overwriting

Приходят ли эти две команды к тому же состоянию, что и копирование моего дома, выполнение обычной проверки, а затем копирование обратно моих файлов, так что git diff будет иметь только те изменения, которые я сделал на этой машине, и никакие файлы не будут удалены?

Есть ли другие варианты, которые следует применить?

Контекст - это мой (альфа) загрузочный скрипт:

git clone --bare -n git://github.com/$(git config github.user)/.dotfiles.git ~/.dotfiles/repo.git
git config -f .dotfiles/repo.git/config core.bare false
git config -f .dotfiles/repo.git/config core.logallrefupdates true
git config -f .dotfiles/repo.git/config core.worktree $HOME
export GIT_DIR=~/.dotfiles/repo.git ;  export GIT_WORK_TREE=~
git read-tree -v HEAD 
git checkout-index -a # all files without overwriting
ln -sf $HOME/.dotfiles/gitignore-dots $HOME/.dotfiles/repo.git/info/exclude

person bsb    schedule 21.04.2012    source источник


Ответы (2)


Я хочу использовать $HOME в качестве рабочего дерева и хранить репозиторий в другом месте (не в .git, поскольку это сбивает с толку другие репозитории).

Не делай этого. Что я делаю

поместите свое рабочее дерево здесь

/opt/dotfiles

поместите свой репозиторий сюда

/opt/dotfiles/.git

Затем вы можете загрузить рабочее дерево в $HOME, запустив

. /opt/dotfiles/bootstrap.sh

Известный пример, и мой пример здесь

mathiasbynens bootstrap.sh

svnpenn bootstrap.sh

person Steven Penny    schedule 30.07.2012
comment
Не могли бы вы уточнить Не делайте этого? Есть ли риск, присущий моему подходу, которого нужно опасаться? Каковы преимущества rsync-ing repo→$HOME? Спасибо - person bsb; 31.07.2012
comment
$HOME — это часто используемый каталог, и он не должен быть сайтом рабочего каталога git; почти наверняка рабочий каталог будет заражен - person Steven Penny; 31.07.2012

Обновление 2012-08-19

Я уже некоторое время использую эту схему для настройки своих точечных файлов в новых и существующих учетных записях, и приведенные выше команды на сегодняшний день ничего не уничтожили. С другой стороны, ни один из экспертов по git не выразил одобрения этой договоренности, а некоторые выразили неодобрение в расплывчатом вопросе «вы с ума сошли?» вид пути.

Теперь у меня есть псевдонимы doton/dotoff и исходные файлы, которые настраивают GIT_DIR и GIT_WORK_TREE, поэтому я делаю настройку на работе, пробую, отправляю на github, а затем обновляю другие свои машины дома. В большинстве случаев это простая перемотка вперед или перебазирование, но иногда требуется грязное обновление.

Грязное обновление

Я добавляю это здесь, так как это другая половина подхода, описанного в вопросе.

Скажем, я git добавляю свой ~/.XCompose и нажимаю его. Когда я хочу перенести это на машину, на которой уже есть файл .XCompose, я хочу получить изменение, увидеть разницу с моей локальной (недобавленной) копией и объединить ее оттуда. Git проверяет это и выручает, что обычно уместно.

Опять же, я использую команды сантехники для выполнения большей части команд более высокого уровня, но без некоторых надоедливых проверок безопасности для работы с грязной рабочей копией. Сантехнические команды не так хорошо описаны в документах, но, похоже, работают (без гарантии).

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

(Обратите внимание, что это может привести к удалению файлов, в том числе неотслеживаемых. Я не знаю, безопасно ли это, и я подозреваю, что если что-то пойдет не так, вы можете остаться в полном беспорядке. )

git fetch # download FETCH_HEAD

# Check HEAD is an ancestor of FETCH_HEAD
cmp <( git rev-parse HEAD ) <( git merge-base HEAD FETCH_HEAD ) \
    || echo "merge-base is not HEAD, not fast forward"

# merge FETCH_HEAD into HEAD in index (2 tree merge is ff, no local changes)
# (no -u means the work tree is not updated)
git read-tree -v -m  HEAD FETCH_HEAD # --trivial ?
# index now merged with FETCH_HEAD

# set HEAD to be FETCH_HEAD with dereferencing
git update-ref HEAD FETCH_HEAD

# update work tree without overwriting existing files (not forced)
# (existing un-added isn't overwritten)
git checkout-index -a

# can now check diffs for conflicts add either commit/edit/checkout
git diff --stat

git pull -vn # should be a no-op

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

git rev-parse HEAD FETCH_HEAD   # what do they point to
git diff --stat HEAD FETCH_HEAD # differences
git merge-base HEAD FETCH_HEAD  # common ancestor
for r in HEAD FETCH_HEAD; do echo $r ; git log --oneline $r | head -1; done
git name-rev $( git merge-base HEAD FETCH_HEAD )

# peek at index
git ls-files --directory --exclude-standard --stage

git diff-index --cached FETCH_HEAD # see "local changes" carried forward
person bsb    schedule 19.08.2012