Java操作Git (JGit)
JGit文档地址:https://github.com/centic9/jgit-cookbook
JGit是eclipse基金会下属的一个Java项目,用于在java环境下实现对git仓库的操作,包括的基本的clone pull push remote commit add等操作。底层的实现逻辑还是依赖了操作系统中已安装的Git软件,所以请确保安装了Git。
注意
jdk1.8使用5.13版本(含)
jdk11及以上使用5.13以上版本
POM依赖
xml
<!-- com.jcraft.jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>5.13.2.202306221912-r</version>
</dependency>
为什么要使用 com.jcraft.jsch
包?因为jgit需要这个包,但jgit没有依赖它,需要你自己去导入这个依赖。
克隆仓库
java
try {
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI(uri);
cloneCommand.setBranch(branch);
cloneCommand.setDirectory(new File(repositoryDir));
cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password));
Git git = cloneCommand.call();
} catch (Exception e) {
e.printStackTrace();
}
拉取代码
java
Git git = null;
try {
git = Git.open(new File("仓库目录"));
PullCommand pull = git.pull();
pull.setRemote("origin");
pull.setCredentialsProvider(new UsernamePasswordCredentialsProvider("用户名", "密码"));
pull.setRemoteBranchName("分支名");
pull.call();
} catch (Exception e) {
e.printStackTrace();
//释放资源
if (git != null && git.getRepository() != null) {
git.getRepository().close();
}
}
代码比对信息统计
java
public static void log(Repository repository, String commitId) {
try (RevWalk revWalk = new RevWalk(repository)) {
RevCommit revCommit = revWalk.parseCommit(ObjectId.fromString(commitId));
//只需要 1 个父提交
if (revCommit.getParents().length == 1) {
//当前提交的父提交
RevCommit parentCommit = revCommit.getParent(0);
CommitCodeLinesBO ccl = codeDiff(repository, revCommit, parentCommit);
//当前提交的commitId
System.out.println(revCommit.getName());
//父提交的commitId
System.out.println(parentCommit.getName());
//当前提交人信息
PersonIdent committer = revCommit.getCommitterIdent();
//提交人name
System.out.println(committer.getName());
//提交人邮箱
System.out.println(committer.getEmailAddress());
//提交message
System.out.println(revCommit.getFullMessage());
//提交时间戳
System.out.println(revCommit.getCommitTime() * 1000L);
} else {
System.out.println("jgit操作:根据commitId获取详细信息,包含多个父提交,跳过");
}
} catch (Exception e) {
log.warn("jgit操作:根据commitId获取详细信息失败:", e);
if (repository != null) {
repository.close();
}
}
}
/**
* 代码比较
* @param repository 仓库
* @param currentCommit 当前提交(新)
* @param parentCommit 父提交(旧)
* @return 代码变更行数
*/
public static void codeDiff(Repository repository, RevCommit currentCommit, RevCommit parentCommit) {
CommitCodeLinesBO codeLinesBO = new CommitCodeLinesBO();
try (DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE)) {
//设置仓库
diffFormatter.setRepository(repository);
//忽略所有空白
diffFormatter.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
//启用重命名检测
diffFormatter.setDetectRenames(true);
//比较提交
List<DiffEntry> diffs = diffFormatter.scan(parentCommit, currentCommit);
//增 删 的行数
int addLines = 0, deleteLines = 0;
for (DiffEntry diff : diffs) {
FileHeader fileHeader = diffFormatter.toFileHeader(diff);
List<HunkHeader> hunks = (List<HunkHeader>) fileHeader.getHunks();
for (HunkHeader hunkHeader : hunks) {
EditList editList = hunkHeader.toEditList();
for (Edit edit : editList) {
//新增行数
addLines += edit.getEndB() - edit.getBeginB();
//删除行数
deleteLines += edit.getEndA() - edit.getBeginA();
}
}
}
System.out.pringln("新增代码行数" + addLines);
System.out.pringln("删除代码行数" + deleteLines);
System.out.pringln("改动的文件数" + diffs.size());
} catch (Exception e) {
e.printStackTrace();
}
}
遇到的问题
remote hung up unexpectedly
问题原因:因为使用了ssh操作git。作者说jgit从5.8版本将ssh支持给抽出去了,但即使你在pom里依赖了jssh也不会解决这个问题,因为Jgit仍然无法找到正确的SshSessionFactory。尽管使用旧版本,也会报一个Auth false的错误。解决办法:
- 使用https的方式,需要用户名和密码做身份验证。
CloneCommand cloneCommand = Git.cloneRepository();
cloneCommand.setURI( "https://example.com/repo.git" );
cloneCommand.setCredentialsProvider(new UsernamePasswordCredentialsProvider("user", "password" ));
cloneCommand.setDirectory(file)
cloneCommand.call();
- 在代码中配置ssh。需要使用公钥做身份验证。