【问题标题】:Non-destructive Git checkout in dirty work tree ($HOME/.dotfiles)脏工作树 ($HOME/.dotfiles) 中的非破坏性 Git 检出
【发布时间】:2023-03-18 22:32:02
【问题描述】:

这个问题是在设计另一个 Git .dotfiles 管理系统时出现的。我想使用$HOME 作为我的工作树并将存储库存储在其他地方(不在.git 下,因为这会混淆其他存储库)。

在具有先前复制和可能调整的点文件的旧机器上,我现在想克隆我的新点文件存储库并(挥手)进入我可以看到(预)的状态我的$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 将只有我在这台机器上所做的更改并且没有文件被删除?

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

上下文是我的(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

【问题讨论】:

    标签: git git-checkout dotfiles working-copy


    【解决方案1】:

    2012-08-19 更新

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

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

    脏更新

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

    假设我 git 添加我的 ~/.XCompose 并推送它。当我想把它拉到机器上时 已经有一个 .XCompose 文件,我想获取更改,查看我的差异 本地(未添加)复制并从那里合并。 Git 对此进行检查并退出,这通常是合适的。

    我再次使用管道命令来执行大部分更高级别的命令, 但没有一些讨厌的安全检查,以便与 肮脏的工作副本。文档中没有很好地介绍管道命令 但似乎有效(不保证)。

    这些说明假定您没有新的本地更改, IE。它不会做变基。

    (请注意,这最终可能会丢弃文件,包括未跟踪的文件。 我不知道这是否接近安全,我怀疑 如果出现问题,您可能会陷入混乱。)

    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
    

    【讨论】:

      【解决方案2】:

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

      不要这样做。我要做的是

      把你的工作树放在这里

      /opt/dotfiles
      

      把你的仓库放在这里

      /opt/dotfiles/.git
      

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

      . /opt/dotfiles/bootstrap.sh
      

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

      mathiasbynens bootstrap.sh

      svnpenn bootstrap.sh

      【讨论】:

      • 你能澄清一下“不要这样做”吗?我的方法中是否存在需要警惕的风险? rsync-ing repo→$HOME 有什么好处?谢谢
      • $HOME 是一个经常使用的目录,不应该是 git 工作目录的站点;几乎可以肯定的工作目录会被污染
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-06
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      相关资源
      最近更新 更多