3

这个问题是在设计另一个 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只会有我在这台机器上所做的更改并且没有文件被删除?

还有其他应该应用的选项吗?

上下文是我的(alpha)引导脚本:

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
4

2 回答 2

0

我想使用 $HOME 作为我的工作树并将存储库存储在其他地方(而不是在 .git 下,因为这会混淆其他存储库)。

不要这样做。我所做的是

把你的工作树放在这里

/opt/dotfiles

把你的回购放在这里

/opt/dotfiles/.git

然后你可以$HOME通过运行引导工作树

. /opt/dotfiles/bootstrap.sh

著名的例子,我的例子在这里

mathiasbynens bootstrap.sh

svnpenn bootstrap.sh

于 2012-07-30T22:14:44.940 回答
0

2012-08-19 更新

一段时间以来,我一直在使用此方案在新帐户和现有帐户上设置我的点文件,并且到目前为止,上述命令还没有破坏任何东西。另一方面,没有 git 专家表示赞同这种安排,有些人含糊地表示反对,“你疯了吗?” 一种方式。

我现在有别名 doton/dotoff 和调整 GIT_DIR 和 GIT_WORK_TREE 的源文件,所以我在工作中进行了调整,尝试一下,推送到 github,然后在家里更新我的其他机器。大多数时候它是一个简单的快进或变基,但偶尔需要一个脏更新。

脏更新

我在这里添加它,因为它是问题中概述的方法的另一半。

假设我 git add 我的 ~/.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
于 2012-08-19T02:41:16.033 回答