Неразрушающий контроль 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
Известный пример, и мой пример здесь