【问题标题】:How to replicate git-checkout using only plumbing commands?如何仅使用管道命令复制 git-checkout?
【发布时间】:2023-03-05 00:58:01
【问题描述】:

我想避免从我的脚本中调用瓷器命令,但是有没有办法只使用像checkout-index 这样的管道命令来获得git checkout <commit> 的某些行为?我对对工作副本的影响特别感兴趣:假设一切都很干净,checkout 删除在旧 HEAD 中跟踪而在新 HEAD 中不存在的文件。 checkout-index 似乎没有删除文件的概念。我能想到的最接近的事情就是打电话

git diff-tree -p <old> <new> | git apply

但计算整个差异似乎不必要地昂贵。有没有更好的办法?

【问题讨论】:

  • 你有什么理由不直接打电话给git checkout ...
  • 是的,不要让你的生活变得不必要的艰难。
  • 最终,我希望能够更好地控制结帐的发生方式。例如,checkout 可以吹走被忽略的文件,我想避免这样做(提高安全性)。但我确实想要覆盖已删除的文件(降低安全性),而不使用--force 来覆盖所有内容。这是在后台使用 git 存储文件树的脚本的一部分,checkout 非常接近我希望我的脚本的行为方式,但不完全是。我想如果我可以通过管道命令获得checkout,我可以从那里对其进行调整,但请告诉我是否有其他方法可以获得此控制。
  • 您是否实际测试过diff-tree 很慢? checkout 基本上区分所有内容以首先弄清楚要做什么。 (当然,checkout 不会创建补丁然后应用它们,您可能也不应该这样做。)
  • @EdwardThomson diff-tree 可能是我想要的,但我不确定将其输出输入什么。除了上面的git apply hack 之外,还有没有办法将此差异应用于工作副本?编写一个 Python 脚本来获取删除列表并实际执行它们很容易,但我担心这会很慢。

标签: git git-checkout git-plumbing


【解决方案1】:

您正在寻找the two-tree git read-tree -um。它使用一个基础树(通常您将其提供给HEAD)、一个目标树以及(隐式)索引和工作树。描述其行为的表格对我来说很难理解,所以我有自己的备忘单,无论如何,重新格式化对我来说更有意义。无论如何,它实现了git checkout

git read-tree -um H M  # `I` is the (implicit) index, GIT_INDEX_FILE

                    Legend

        H       Original tree (usually HEAD:)
        I       Indexed tree
        M       Merge target tree

        H->I     \
        H->M      } status in second relative to first
        I->M     /

        "-"     file exists in neither
       new      exists only in second
       deleted  exists only in first
       same     exists in both, unchanged
       changed  exists in both, different
      (blank)   irrelevant or all cases not otherwise given

        keep    keep current version
        fail    whole command fails, no changes
       delete   delete worktree file


      H->I      H->M      I->M

                          same     keep

     deleted   changed             fail
     deleted   deleted             delete
     deleted    same               delete unless Index empty, else use M
                same               keep

      same     changed             worktree clean: use M; dirty: fail
      same     deleted             worktree clean: deleted; dirty: fail

      new        -                 keep
      new       new      changed   fail
     changed   changed   changed   fail
     changed   deleted             fail


note: "index empty" identifies an initial checkout, where HEAD has been
set but never loaded.  git can't currently distinguish between a
delete-everything index and an initial-checkout index.

【讨论】:

  • +1。我喜欢备忘单。我已经通过使用git read-tree -um 的示例完成了自己的答案。
  • 谢谢!我永远不会猜到。
  • 不客气。我也不会猜到,要知道你可以让 git 做什么并不总是那么容易。我知道我并没有真正得到这个命令,直到我对文档中的表格生气并花时间制作自己的命令。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
相关资源
最近更新 更多