JGit常用功能(提交、回滚、日志查询)—优化

之前写的一篇有些bug,而且里面的概念也没搞清楚,查询了《Git权威指南》后又优化了一下,如下:

public class GitUtil {

    private final static String GIT         = ".git";

    private final static String REF_REMOTES = "refs/remotes/origin/";

    /**
     * 将文件列表提交到git仓库中
     * @param gitRoot git仓库目录
     * @param files 需要提交的文件列表
     * @param remark 备注
     * @return 返回本次提交的版本号
     * @throws IOException 
     */
    public static String commitToGitRepository(String gitRoot, List<String> files, String remark)
                                                                                                 throws Exception {
        if (StringUtils.isNotBlank(gitRoot) && files != null && files.size() > 0) {

            File rootDir = new File(gitRoot);

            //初始化git仓库
            if (new File(gitRoot + File.separator + GIT).exists() == false) {
                Git.init().setDirectory(rootDir).call();
            }

            //打开git仓库
            Git git = Git.open(rootDir);
            //判断工作区与暂存区的文件内容是否有变更
            List<DiffEntry> diffEntries = git.diff()
                .setPathFilter(PathFilterGroup.createFromStrings(files))
                .setShowNameAndStatusOnly(true).call();
            if (diffEntries == null || diffEntries.size() == 0) {
                throw new Exception("提交的文件内容都没有被修改,不能提交");
            }
            //被修改过的文件
            List<String> updateFiles = new ArrayList<String>();
            ChangeType changeType;
            for (DiffEntry entry : diffEntries) {
                changeType = entry.getChangeType();
                switch (changeType) {
                    case ADD:
                    case COPY:
                    case RENAME:
                    case MODIFY:
                        updateFiles.add(entry.getNewPath());
                        break;
                    case DELETE:
                        updateFiles.add(entry.getOldPath());
                        break;
                }
            }
            //将文件提交到git仓库中,并返回本次提交的版本号
            //1、将工作区的内容更新到暂存区
            AddCommand addCmd = git.add();
            for (String file : updateFiles) {
                addCmd.addFilepattern(file);
            }
            addCmd.call();
            //2、commit
            CommitCommand commitCmd = git.commit();
            for (String file : updateFiles) {
                commitCmd.setOnly(file);
            }
            RevCommit revCommit = commitCmd.setCommitter("yonge", "[email protected]")
                .setMessage(remark).call();
            return revCommit.getName();
        }
        return null;
    }

    /**
     * 回滚到指定版本的上一个版本
     * @param gitRoot git仓库目录
     * @param diffEntries 需要回滚的文件
     * @param revision 版本号
     * @param remark 备注
     * @return
     * @throws Exception
     */
    public static boolean rollBackPreRevision(String gitRoot, List<DiffEntry> diffEntries,
                                              String revision, String remark) throws Exception {

        if (diffEntries == null || diffEntries.size() == 0) {
            throw new Exception("没有需要回滚的文件");
        }

        Git git = Git.open(new File(gitRoot));

        List<String> files = new ArrayList<String>();

        //注意:下面的reset命令会将暂存区的内容恢复到指定(revesion)的状态,相当于取消add命令的操作
        /*Repository repository = git.getRepository();

        RevWalk walk = new RevWalk(repository);
        ObjectId objId = repository.resolve(revision);
        RevCommit revCommit = walk.parseCommit(objId);
        String preVision = revCommit.getParent(0).getName();
        ResetCommand resetCmd = git.reset();
        for (String file : files) {
            resetCmd.addPath(file);
        }
        resetCmd.setRef(preVision).call();
        repository.close();*/

        //取出需要回滚的文件,新增的文件不回滚
        for (DiffEntry diffEntry : diffEntries) {
            if (diffEntry.getChangeType() == ChangeType.DELETE) {
                continue;
            } else {
                files.add(diffEntry.getNewPath());
            }
        }

        if (files.size() == 0) {
            throw new Exception("没有需要回滚的文件");
        }

        //checkout操作会丢失工作区的数据,暂存区和工作区的数据会恢复到指定(revision)的版本内容
        CheckoutCommand checkoutCmd = git.checkout();
        for (String file : files) {
            checkoutCmd.addPath(file);
        }
        //加了“^”表示指定版本的前一个版本,如果没有上一版本,在命令行中会报错,例如:error: pathspec '4.vm' did not match any file(s) known to git.
        checkoutCmd.setStartPoint(revision + "^");
        checkoutCmd.call();

        //重新提交一次
        CommitCommand commitCmd = git.commit();
        for (String file : files) {
            commitCmd.setOnly(file);
        }
        commitCmd.setCommitter("yonge", "[email protected]").setMessage(remark).call();

        return true;
    }

    /**
     * 获取上一版本的变更记录,如果是新增的文件,不会显示,因为做回滚时不需要回滚新增的文件
     * @param gitRoot git仓库目录
     * @param revision 版本号
     * @return
     * @throws Exception
     */
    public static List<DiffEntry> rollBackFile(String gitRoot, String revision) throws Exception {

        Git git = Git.open(new File(gitRoot));
        Repository repository = git.getRepository();

        ObjectId objId = repository.resolve(revision);
        Iterable<RevCommit> allCommitsLater = git.log().add(objId).call();
        Iterator<RevCommit> iter = allCommitsLater.iterator();
        RevCommit commit = iter.next();
        TreeWalk tw = new TreeWalk(repository);
        tw.addTree(commit.getTree());
        commit = iter.next();
        if (commit != null) {
            tw.addTree(commit.getTree());
        } else {
            throw new Exception("当前库只有一个版本,不能获取变更记录");
        }

        tw.setRecursive(true);
        RenameDetector rd = new RenameDetector(repository);
        rd.addAll(DiffEntry.scan(tw));
        List<DiffEntry> diffEntries = rd.compute();
        if (diffEntries == null || diffEntries.size() == 0) {
            return diffEntries;
        }
        Iterator<DiffEntry> iterator = new ArrayList<DiffEntry>(diffEntries).iterator();
        DiffEntry diffEntry = null;
        while (iterator.hasNext()) {
            diffEntry = iterator.next();
            System.out.println("newPath:" + diffEntry.getNewPath() + "    oldPath:"
                               + diffEntry.getOldPath() + "   changeType:"
                               + diffEntry.getChangeType());
            if (diffEntry.getChangeType() == ChangeType.DELETE) {
                iterator.remove();
            }
        }
        return diffEntries;
    }
}

可能里面还会有一些问题,若发现请留言,谢谢!!

相关推荐