Неразрушающий контроль Git в грязном рабочем дереве ($HOME/.dotfiles)

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

На старых машинах с ранее скопированными и потенциально подправленными точечными файлами, я теперь хотел бы клонировать мой новый репозиторий точечных файлов и (махать руками) перейти в состояние, в котором я могу видеть (предварительно) существующее состояние моего $HOME/.* Дотфайлы как модификации мастера моего недавно клонированного репозитория. Это в основном фон, в 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

2 ответа

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

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

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

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

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

Допустим, я добавляю свой ~/.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

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

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

положи здесь свое рабочее дерево

/opt/dotfiles

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

/opt/dotfiles/.git

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

. /opt/dotfiles/bootstrap.sh

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

mathiasbynens bootstrap.sh

svnpenn bootstrap.sh

Другие вопросы по тегам