我正在尝试获取与该命令等效的 JGit
git describe --match "[0-9]*.[0-9]*.[0-9]*" --abbrev=0 --tags $(git rev-list --tags --branches=master --max-count=1)
我尝试获取项目中的所有标签,然后通过 BranchListCommand 找到分支中最大的标签,但这很慢。
我陷入困境,无法通过搜索找到任何有帮助的内容。
有人知道如何达到预期的结果吗?
您可以获取所有标签,然后遍历分支上的提交并检查每个提交是否有此引用的标签。
即通过以下方式获取所有标签:
git.tagList().call()
然后通过以下方式获取分支的所有提交:
git.log().add(repository.resolve(BRANCH)).call()
然后对于每个提交检查此引用处是否存在标签。
当在具有超过 60k 提交的分支上的相当大的存储库上运行时,以这种方式遍历所有提交只需 1.2 秒。
Had 60843 commits overall on branch remotes/origin/master, iteration took 1200ms
更大的分支在执行 380k 提交时需要 8 秒。
Had 388613 commits overall on branch remotes/origin/master, iteration took 8261ms
我已在 jgit-cookboot 中添加了一个可立即运行的代码片段,请参阅 ListTagsOnBranch.java
基于之前的答案,我想分享我的解决方案(JGit 6.6.0.202305301015-r)。本质上,简单地映射
tagList()
对我来说不起作用,因为生成的 Refs 是未剥离的。解决方案是在将它们分组到地图中之前将它们剥离。 RefDatabase.peel 的 JavaDoc 指出:
通过遍历带注释的标签来剥离可能未剥离的参考。 如果引用无法剥离(因为它不引用带注释的标签)>剥离的 id 保持为 null,但 Ref.isPeeled() 将为 true。 实施者应该在执行任何额外工作>努力之前检查 Ref.isPeeled()。
try (final var git = Git.open(new File("/path/to/your/repository"))) {
final var repository = git.getRepository();
final var refDatabase = repository.getRefDatabase();
// Create a map of peeled references.
final var tags = refDatabase.getRefsByPrefix(R_TAGS).stream().map(ref -> {
try {
return refDatabase.peel(ref);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}).collect(Collectors.groupingBy(ref -> {
final var peeledObjectId = ref.getPeeledObjectId();
return peeledObjectId == null ? ref.getObjectId() : peeledObjectId;
}, Collectors.mapping(ref -> ref, Collectors.toList())));
// Collect the matching tag(s) into a chronological list
final var result = StreamSupport.stream(git.log()
.add(repository.resolve(branch))
.call().spliterator(), false)
.map(rev -> tags.get(rev.getId()))
.filter(refs -> refs != null)
.toList();
}
由于这个问题是短语
jgit get latest tag
的第一个Google结果,我发布了一个简单的解决方案来获取当前分支的最新标签:
git.describe().setTags(true).setAbbrev(0).call()