代码之家  ›  专栏  ›  技术社区  ›  Dave Abrahams

有没有办法隐藏当前的git索引'git add-u',然后将索引恢复到隐藏状态?

git
  •  0
  • Dave Abrahams  · 技术社区  · 5 年前

    这里的想法是,我想(暂时)暂存所有挂起的更改,然后稍后撤消它,而不必更改工作树中的文件。它似乎应该属于 git stash ,但我不知道如何使用该命令实现它。谢谢!

    0 回复  |  直到 5 年前
        1
  •  -1
  •   torek    5 年前

    编辑:关于 your comment :

    @当然,这就是我如何获取工作拷贝+索引状态的初始快照的方法。但挑战是如何在结束后恢复到那种状态 git add -u 不更改工作副本中的任何文件 .

    作为参考 @phd 下面是一个涉及 git stash store 一场比赛的结果 git stash create . 这个 git存储创建 操作首先创建两棵树:一棵是 git write-tree (如下所述),另一个是 有效 将索引复制到临时索引的结果,运行 git添加-u git写入树 同样,所有这些都使用临时索引。这两棵树,如果它们是写的; git存储创建 当索引和工作树都是“干净的”时,什么也不做,然后被包装到 I 和 W 中描述的提交 the git stash documentation ,和 git存储创建 打印文件的哈希ID W型 提交(适用于 吉特储藏室 ).

    请注意,您的工作树是 不受干扰 通过这部分操作。没有什么可恢复的。干扰你工作树的是 git reset 第步 git stash push . 但是 不运行此步骤!它只是使 我 W型 git存储创建 会得到你想要的。

    我的项目有一个pre-commit钩子,它只会lint暂存文件状态。。。

    在这种情况下,为什么不:

    • W型 提交(使用) git存储创建 如果你愿意的话)
    • (可选)为其指定一个临时分支名称,然后
    • 使用 git worktree add 检查分支,或者作为分离头提交,然后
    • 在添加的工作树上运行pre-commit钩子。

    如果linter的行为真的很好,那么您也许可以完全跳过添加的worktree,而只进行设置 GIT_INDEX_FILE 到一个临时文件,从中读取树 W型 提交,并用它运行过梁 GIT\u索引\u文件 设置到位。

    真正地 表现得很好他们中很少有人表现得这么好你应该可以 GIT\u索引\u文件 要创建临时文件,请运行 git添加-u ,运行linter,然后删除临时文件。当然,在工作树上运行linter比在索引上运行更容易。这就需要一个灵活的pre-commit linter:它可以使用一个工作树(完全忽略Git的存在)作为更老、更蠢、不支持Git的linter; 或 使用Git索引。总的来说,这会更快更容易。

    [行下原始答案]


    XY problem 在这里,只是回答问题:

    • 可以临时使用临时索引;和
    • 你真的可以这么做,这是毫无意义的。

    Git使用索引的方式很复杂,因此这里有许多粗糙的边。你可以在任何一个上面割伤自己。例如,索引可以假定在特定条目上设置了未更改和/或跳过的工作树位,或者可以处于Git在冲突合并(包括cherry pick、revert和rebase操作)过程中使用的扩展状态。但一般来说,索引可以转换为Git的内部 树对象 几乎在任何时候使用 git写入树 :

    hash=$(git write-tree) || echo "unable to turn index into a tree"
    

    hash 现在包含树对象的哈希ID。默认情况下,此树对象将在存储库中至少存在14天,因此您最多有14天的时间来创建使用它的提交,或者使用标记或其他引用链接到它,这样可以使它更持久地存在。

    有 写出 索引 作为 一棵树,现在可以对索引执行任何操作,包括运行 git添加-u . 稍后,您可以使用将索引恢复到已保存树中的状态 git read-tree :

    git read-tree $hash || echo "unable to restore index"
    

    读取树操作在各种情况下都可能失败;咨询 the documentation . 某些标志使某些操作成功或失败,否则它们可能会分别失败或成功,例如,您也可以先完全清空索引,然后读入索引。

    使用 暂时的 索引,设置环境变量 GIT\u索引\u文件 mktemp 例如)不适合。但是,您可以使用:

    TF=$(mktemp) || exit
    rm -f $TF                     # remove it now
    trap "rm -f $TF" 0 1 2 3 15   # arrange to remove it on exit or signal
    export GIT_INDEX_FILE=$TF     # point Git at this name from here on
    

    GIT\u索引\u文件 unset以使用实数索引,并且 GIT_INDEX_FILE=$TF 要使用临时索引,请执行以下操作:

    git read-tree --empty        # create empty $TF index file
    echo "temp index contents:"
    git ls-files --stage
    
    echo "real index contents:"
    (unset GIT_INDEX_FILE; git ls-files --stage)
    
    # back to using the temporary index in $TF
    

    例如,将演示效果。最后一行使用子shell,以便在最后一行的持续时间内取消设置环境变量 git ls-files ,但是在主线执行中保留环境变量,不管最后注释后面的命令是什么。

    像往常一样,无论出于什么目的创建的临时对象(包括您可能放入临时索引中的任何blob)都有14天的宽限期,可以转化为真正的提交。之后, git gc