git checkout到临时工作树而不更改索引

时间:2018-07-18 17:08:31

标签: git

我正在创建一个git post-checkout钩子,以确保在分支之间移动时我的数据库状态是一致的,但是我遇到了一个特殊的问题。

要使此工作有效,我必须同时访问“ from”分支和“ to”分支的迁移。 post-checkout挂钩在使用“ to”分支使索引和工作树更新之后运行。它是做什么的:

  1. 运行GIT_WORK_TREE=/tmp/from-branch git checkout $from_branch -- db,将“ from”分支的db文件放入/tmp/from-branch/db
  2. 运行GIT_WORK_TREE=/tmp/to-branch git checkout $to_branch -- db,将“ to”分支的db文件放入/tmp/to-branch
  3. 在迁移中找到共同的祖先。
  4. /tmp/from-branch运行必要的向下迁移。
  5. 从存储库中的当前工作树运行任何新的向上迁移。

这一切都很出色,除了运行后,git显示以下内容:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   db/migrations/non-prod/20180718_102122-new-one-test-data.sql
        new file:   db/migrations/schema/20180718_102108-new-one.sql

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    db/migrations/non-prod/20180718_102122-new-one-test-data.sql
        deleted:    db/migrations/schema/20180718_102108-new-one.sql

这两个文件是从$from_branch检出到tmp工作树中的文件。 Git似乎假设我正在将它们检入到存储库中(尽管将GIT_WORK_TREE变量设置为另一个路径)并自动将它们作为“暂存”添加到索引中。我对git-checkout手册页进行了梳理,以查找可以防止这种情况并且没有找到任何选项的选项。

我目前最好的解决方案是在结帐后运行git reset,但这听起来像是黑客。只是想知道是否还有其他人可以想到更好的解决方案。

1 个答案:

答案 0 :(得分:3)

您的术语有点过头,但这在本质上是正确的:git checkout首先将文件复制到索引中,然后再将其复制到工作树中。索引就是以此方式索引或缓存工作树,因此命名为索引缓存。 (Git还使用索引的缓存信息来最大程度地减少实际工作量,因此,如果文件已经以正确的形式存在于工作树中,则Git不必在此处进行触摸。)

正如您所注意到的,您正在使用不同临时覆盖的工作树。因此,您需要的是一个不同的,暂时被覆盖的索引。实际上,Git仅支持:

TF=$(mktemp)
trap "rm -f $TF" 0 1 2 3 15   # clean up on exit

rm -f $TF # Git prefers a non-existent file to an empty one
GIT_INDEX_FILE=$TF GIT_WORK_TREE=/tmp/from-branch git checkout $from_branch -- db
rm -f $TF
GIT_INDEX_FILE=$TF GIT_WORK_TREE=/tmp/to-branch git checkout $to_branch -- db
... proceed as before

请注意,如果您选择将/tmp/from-branch/tmp/to-branch工作树保留为永久工作树,则不必每次都删除临时索引,使用两个 permanent 索引来为这两个工作树建立索引。