JGIT使用的常见问题

具体代码详见:https://gitee.com/RainyGao/DocSys

JGIT是非常好用的Java库,通过JGIT的API可以新建、克隆仓库、CheckOut和Commit文件,但使用JGIT时需要关注一些地方,否则会出现很多异常。

1. 关于仓库的遍历

JGIT通过treeWalk来实现对仓库的遍历,原理上是首先根据revision来获取这个revision对应的revTree,换句话说就是这个版本上的文件节点树(这些文件在该版本一定是存在的),然后获取该revTree相应的入口文件(treeWalk)来实现遍历。

默认情况下获取的treeWalk是递归的(换句话说,就是会自动进入子目录进行遍历),所以如果只是遍历所有文件那么没有问题,但实际上的应用场景而言,通常只需要获取该目录下的文件列表即可(尤其对于需要展示目录结构的场景),如果这个时候需要将treeWalk设置为不可递归。

treeWalk.setRecursive(true)

(1)获取GIT根目录的revTree的入口的方法如下:

treeWalk = new TreeWalk( repository )
treeWalk.reset(revTree)
需要注意的是如果是根目录的treeWalk,那么此时treeWalk指向的是根目录下的第一个文件,而不是根目录,换句话说根目录本身是不会有treeWalk的,所以如果在这个revision上没有文件的话,那么treeWalk将会是Null值。

由于指向的是根目录下的第一个文件,那么设置非递归的话,调用treeWalk.next就可以遍历根目录下的文件列表。

(2)获取指定的文件的treeWalk入口:

treeWalk = TreeWalk.forPath(repository, entryPath, revTree);

网上还有利用更底层的PathFilter接口来实现treeWalk的获取,我也尝试过,但似乎并不能达到我想要的效果,个人建议直接使用forPath接口即可,forPath返回的treeWalk的递归设置默认是不递归。

forPath返回的treeWalk可能是文件也可能是目录,通过treeWalk.isSubTree可以判断是不是目录,该接口是通过FileMode的值来实现的,但某些情况下treeWalk的FileMode是个Null值(例如根目录的treeWalk),所以直接对treeWalk进行判断会导致异常,因此对于treeWalk的判断需要区分是不是根目录的treeWalk。

另外treeWalk指向的是revTree的某个节点,在不递归的情况下,要遍历其子目录需要调用 treeWalk.enterSubtree()来进入子目录(treeWalk将指向该目录下的第一个文件)

2、关于CheckOut

只要treeWalk搞定了,CheckOut是最简单的,找到指定的文件节点的入口(即treeWalk),用如下代码即可将文件下载下来:

                out = new FileOutputStream(localParentPath + targetName);
                ObjectId blobId = treeWalk.getObjectId(0);
                ObjectLoader loader = repository.open(blobId);
                loader.copyTo(out);

3、关于Commit

Commit目前的实现还是依赖于jgit提供的commit接口,原理根本地的git命令没什么区别,但是对本地WorkingCopy是有依赖的(也就是说必须本地CheckOut一个branch才能Commit),这并不是我想要的(我更倾向于直接利用文件数据流直接向Stash中写入想要Commit的文件),但似乎还有点复制,所以会放在后面来实现。

以下是Commit和Push的实现代码。

        RevCommit ret = null;
        try {
            ret = git.commit().setCommitter(commitUser, "").setMessage(commitMsg).call();
            System.out.println("doAutoCommmit() commitId:" + ret.getName());
        } catch (Exception e) {
            System.out.println("doAutoCommmit() commit error");
            e.printStackTrace();
            return null;
        }
        
        if(isRemote)
        {
            try {
                git.push().call();
            } catch (Exception e) {
                System.out.println("doAutoCommmit() Push Error");    
                e.printStackTrace();
                //Do roll back commit
                rollBackCommit(git, null);
                return null;
            }
        }

      rollBackCommit是用来将本地仓库还原掉,因为push失败的原因,通常是远程仓库已经有更新了,那么需要对本地仓库先进行rebase以保证本地仓库与远程仓库的同步。

4. 关于删除

实际上删除也是一个Commit操作,但有有些不同,因为删除实际上并没有内容需要commit到仓库中去,只是删除了节点,那么这时候的操作就需要一点点技巧了。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
好的,JGit使用ssh免密认证需要进行以下几个步骤: 1. 生成ssh公钥和私钥 您可以在本地使用ssh-keygen命令生成ssh公钥和私钥,例如: ``` ssh-keygen -t rsa -C "your_email@example.com" ``` 这里的“your_email@example.com”是您的邮箱地址,执行命令后,系统会提示您输入保存密钥对的文件名及密码等信息。 2. 将公钥添加到git服务器上 将生成的公钥添加到Git服务器上的authorized_keys文件中,这里以GitHub为例,进入GitHub网站,点击右上角头像,选择“Settings”,在左侧菜单栏中选择“SSH and GPG keys”,点击“New SSH key”,将生成的公钥复制到Key文本框中,点击“Add SSH key”按钮即可。 3. 在JGit使用ssh协议克隆代码库 在JGit使用ssh协议克隆代码库时,需要设置ssh协议的URL,例如: ``` git@github.com:your_username/your_repository.git ``` 这里的“your_username”是您的GitHub用户名,“your_repository”是您的代码库名称,您也可以将这个URL放到URI对象中,然后通过CloneCommand对象进行克隆操作。在克隆之前,您需要设置JschConfigSessionFactory对象,该对象是用于创建JschSession对象的工厂,您可以在其中设置ssh私钥和密码等信息。 代码示例: ``` String gitUrl = "git@github.com:your_username/your_repository.git"; String privateKey = "/path/to/your/private_key"; String passphrase = "your_passphrase"; // 设置JschConfigSessionFactory JschConfigSessionFactory sessionFactory = new JschConfigSessionFactory() { @Override protected void configure(Host hc, Session session) { // 设置ssh私钥 JschSession jschSession = (JschSession) session; jschSession.setConfig("StrictHostKeyChecking", "no"); jschSession.setIdentity(privateKey, passphrase); } }; // 克隆代码库 Git.cloneRepository() .setURI(gitUrl) .setTransportConfigCallback(transport -> { SshTransport sshTransport = (SshTransport) transport; sshTransport.setSshSessionFactory(sessionFactory); }) .setDirectory(new File("/path/to/your/local/repository")) .call(); ``` 希望以上信息能够帮助到您。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值