如何使用 Objective-Git (libgit2) "unstage" 文件?

How to "unstage" a file with Objective-Git (libgit2)?

我正在编写一个允许使用 Objective-Git 执行基本 git 操作的应用程序,但我无法弄清楚如何 "unstage" 一个文件。更具体地说,我有一个文件,其中包含以前已添加到当前 GTIndex 的更改,现在我想放弃这些更改(不会丢失文件在磁盘上的当前状态)。

以下是我的程序在切换文件的 "staged" 状态时当前遵循的相关逻辑的粗略概述:

- Fetch current GTIndex using GTRepository.indexWithError:
- Fetch GTIndexEntry for the file using GTIndex.entryWithPath:
- If the file has an index and GTIndexEntry.status == GTIndexEntryStatusUpdated:
    - Here's where I'm stuck

According to this old unanswered question 我需要在当前 HEAD 中查找文件的信息。在那种情况下,这就是我得出的逻辑:

- Fetch head's GTReference using GTRepository.headReferenceWithError:
- If the reference resolves to a GTCommit object:
    - Fetch the GTTree using GTCommit.tree
    - Fetch the file's GTTreeEntry using GTTree.entryWithPath:error:
    - Stuck again! Do I convert GTTreeEntry to GTIndexEntry somehow?

感谢任何指导!如果必须的话,我不害怕直接进入 libgit2(这个项目已经需要它一两次),但是因为我在 Swift 工作,所以我想避免如果可以的话,"unstaging" 一个文件似乎是一个标准程序,我想我一定不理解 Objective-Git 类 是如何联系在一起的。

从 HEAD 提交中获得树条目后,您可以从中提取数据以填充新的索引条目。您无需填写所有字段,但至少设置 pathmodeid。您可以直接从树条目中复制它们。然后使用等同于 git_index_add 的 objective-git 用新条目更新索引。

如果文件在 HEAD 树中不存在(因为之前没有被跟踪),那么您可以简单地使用 git_index_remove_bypath.

从索引中删除它

放置一段时间后,我发现它实际上比我做的要容易得多;无需将 HEAD 树与活动索引进行比较,您可以简单地使用 GTRepository.statusForFile:success:error: 来确定文件是否已暂存、未暂存等,然后为该文件添加、删除或添加 blob基于此。

原始方法

(偶尔它包含对其他人有用的信息。)

事实证明这比一开始看起来要简单,主要是因为不需要在 GTTreeEntry 和 GTIndexEntry 之间进行转换。相反,我只需要获取 GTTreeEntry 的 GTObject(这是文件的 blob),然后将 blob 的数据传递到 GTIndex。

我最终得到的代码流程大致如下:

- Fetch head's GTReference using GTRepository.headReferenceWithError:
- If the reference resolves to a GTCommit =>
    - Fetch the GTIndexEntry using GTIndex.entryWithPath:
    - If we have an index entry =>
        - Fetch the GTTree using GTCommit.tree
        - Fetch the GTTreeEntry using GTTree.entryWithPath:error:
        - If GTTreeEntry.SHA == GTIndexEntry.OID.SHA =>
            - GTIndex.addFile:error:
            (using this approach, it's possible to end up with identical
             tree and index entries, which means the file is unstaged)
        - Else if GTTreeEntry.type == GTObjectTypeBlob =>
            - Fetch GTBlob using GTTreeEntry.GTObject:error:
            - Pass GTBlob.data to GTIndex.addData:withPath:error:
        - Else if no GTTreeEntry => GTIndex.removeFile:error:
    - Else add the file/directory to the GTIndex (since we have no index entry)
    - Write the changes to disk with GTIndex.write:

一些注释希望它们对后代抨击 Objective-Git 的大部分未记录的隐藏的人有所帮助:

  • GTIndexEntry.status 在这种情况下没用;它引用了一些 的标志,但对之后确定文件状态没有帮助(坦率地说,我不确定为什么这些标志会被 Objective-Git 公开)
  • 如果你想 un/stage 工作目录中的所有文件,你可以 Objective-Git 使用 GTDiff 的 +diffIndexFromTree:inRepository:options:error: