用libgit2卸载文件 [英] Un-stage file with libgit2

查看:151
本文介绍了用libgit2卸载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用objective-git和libgit2可以很容易地准备好提交文件:

  GTIndex * repoIndex = [self.repository indexWithError:& error]; 

[repoIndex removeFile:path error:& error];
$ b $ if(status!= GTFileStatusIgnored&& status!!= GTFileStatusWorkingDeleted){
//现在将文件添加到索引
[repoIndex addFile:path error:&错误];
}

[repoIndex write:& error];

然而,将文件解除分档已经证明有点棘手。简单地从版本库的索引中删除它不起作用,因为git认为文件已被删除,这是合理的。看起来我需要做的就是将索引中的索引条目更改为索引条目之前的索引条目。



我尝试了以下操作,使用diff到获取旧的差异增量并从中构建 git_index_entry 并插入它:

  GTIndex * repoIndex = [self.repository indexWithError:& error]; 
GTBranch * localBranch = [self.repository currentBranchWithError:& error];
GTCommit * localCommit = [localBranch targetCommitAndReturnError:& error];

GTDiff * indexCommitDiff = [GTDiff diffIndexFromTree:localCommit.tree inRepository:self.repository options:nil error:& error];

//通过diff deltas枚举,直到我们到达要取消存储的文件
[indexCommitDiff enumerateDeltasUsingBlock:^(GTDiffDelta * delta,BOOL * stop){

NSString * deltaPath = delta.newFile.path;

//检查它是否与我们想要使用
的路径匹配if([deltaPath isEqualToString:path]){
GTDiffFile * oldFile = delta.oldFile;

NSString * oldFileSHA = oldFile.OID.SHA;
git_oid oldFileOID;
int status = git_oid_fromstr(& oldFileOID,oldFileSHA.fileSystemRepresentation);

git_index_entry条目;
entry.mode = oldFile.mode;
entry.oid = oldFileOID;
entry.path = oldFile.path.fileSystemRepresentation;

[repoIndex removeFile:path error:& error];

status = git_index_add(repoIndex.git_index,& entry);

[repoIndex write:& error];
}
}];

然而,这会使git索引处于损坏状态,导致任何git命令记录致命错误:

 致命:未知索引输入格式bfff0000 
致命:未知索引输入格式bfff0000

使用libgit2取消档案的正确方法是什么?

解决方案

请记住,Git是基于快照的,因此索引中的任何内容都将被提交。



没有任何停顿行动本身,因为它是依赖于上下文的。如果该文件是新的,那么删除它就是你做什么来取消它。否则,暂停和暂存操作是相同的操作,区别在于您在条目中使用的blob是该文件的旧版本。



由于您要移动文件回到他们在HEAD中的状态,应该不需要使用diff,而是拿起HEAD树并在那里查找你想要的条目(尽管从一瞥中我看不到包含 git_tree_entry_bypath()



如果我们写出一个糟糕的索引版本,那肯定是库中的一个bug,你打开一个问题,我们可以尝试重现它?


Using objective-git and libgit2 it has been fairly easy to stage a file ready for commit:

GTIndex *repoIndex = [self.repository indexWithError:&error];

[repoIndex removeFile:path error:&error];

if (status != GTFileStatusIgnored && status != GTFileStatusWorkingDeleted) {
    // Now add the file to the index
    [repoIndex addFile:path error:&error];
}

[repoIndex write:&error];

However un-staging a file is proving to be a tad more tricky. Simply removing it from the repository's index doesn't work as git then thinks the file has been deleted which makes sense. It seems what I need to do is change the index entry in the index to the one it was before it was staged.

I have tried doing the following, using diff to get the old diff delta and constructing a git_index_entry from that and inserting it:

GTIndex *repoIndex = [self.repository indexWithError:&error];
GTBranch *localBranch = [self.repository currentBranchWithError:&error];
GTCommit *localCommit = [localBranch targetCommitAndReturnError:&error];

GTDiff *indexCommitDiff = [GTDiff diffIndexFromTree:localCommit.tree inRepository:self.repository options:nil error:&error];

// Enumerate through the diff deltas until we get to the file we want to unstage
[indexCommitDiff enumerateDeltasUsingBlock:^(GTDiffDelta *delta, BOOL *stop) {

    NSString *deltaPath = delta.newFile.path;

    // Check if it matches the path we want to usntage
    if ([deltaPath isEqualToString:path]) {
        GTDiffFile *oldFile = delta.oldFile;

        NSString *oldFileSHA = oldFile.OID.SHA;
        git_oid oldFileOID;
        int status = git_oid_fromstr(&oldFileOID, oldFileSHA.fileSystemRepresentation);

        git_index_entry entry;
        entry.mode = oldFile.mode;
        entry.oid = oldFileOID;
        entry.path = oldFile.path.fileSystemRepresentation;

        [repoIndex removeFile:path error:&error];

        status = git_index_add(repoIndex.git_index, &entry);

        [repoIndex write:&error];
    }
}];

However this leaves the git index in a corrupt state resulting in any git command logging a fatal error:

fatal: Unknown index entry format bfff0000
fatal: Unknown index entry format bfff0000     

What is the correct way to un-stage a file using libgit2?

解决方案

Remember that Git is snapshot-based, so whatever is in the index at commit time will be what's committed.

There is no unstage action by itself, as it's context-dependent. If the file is new, then removing it is what you do to unstage it. Otherwise, unstaging and staging are the same operation, with the difference that the blob you use in the entry is the old version of the file.

Since you want to move files back to their state in HEAD, there shouldn't be a need to use diff, but take the tree of HEAD and look up the entries you want there (though from a quick glance, I don't see objective-git wrapping git_tree_entry_bypath())

If we write out a bad version of the index, that's definitely a bug in the library, could you open an issue so we can try to reproduce it?

这篇关于用libgit2卸载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆