-
A1. 附录 A:其他环境中的 Git
- A1.1 图形界面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 总结
-
A2. 附录 B:在应用程序中嵌入 Git
-
A3. 附录 C:Git 命令
A2.3 附录 B:在应用程序中嵌入 Git - JGit
JGit
如果您想在 Java 程序中使用 Git,有一个名为 JGit 的全功能 Git 库。JGit 是用 Java 原生编写的功能相对齐全的 Git 实现,在 Java 社区中广泛使用。JGit 项目属于 Eclipse,其主页位于 https://www.eclipse.org/jgit/。
设置
有多种方法可以将您的项目与 JGit 连接并开始针对它编写代码。最简单的方法可能是使用 Maven - 集成是通过在 pom.xml
文件的 <dependencies>
标记中添加以下代码段来完成的
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>3.5.0.201409260305-r</version>
</dependency>
当您阅读本文时,版本
很可能已经更新;请查看 https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit 以获取更新的存储库信息。完成此步骤后,Maven 将自动获取并使用您需要的 JGit 库。
如果您希望自己管理二进制依赖项,则可从 https://www.eclipse.org/jgit/download 获取预构建的 JGit 二进制文件。您可以通过运行如下命令将它们构建到您的项目中
javac -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App.java
java -cp .:org.eclipse.jgit-3.5.0.201409260305-r.jar App
管道
JGit 具有两个基本的 API 级别:管道和瓷器。这些术语源自 Git 本身,而 JGit 大致分为相同类型的区域:瓷器 API 是常见用户级操作(普通用户将使用 Git 命令行工具执行的操作类型)的友好前端,而管道 API 则用于直接与低级存储库对象进行交互。
大多数 JGit 会话的起点是 Repository
类,您要做的第一件事是创建它的一个实例。对于基于文件系统的存储库(是的,JGit 允许使用其他存储模型),可以使用 FileRepositoryBuilder
来完成此操作
// Create a new repository
Repository newlyCreatedRepo = FileRepositoryBuilder.create(
new File("/tmp/new_repo/.git"));
newlyCreatedRepo.create();
// Open an existing repository
Repository existingRepo = new FileRepositoryBuilder()
.setGitDir(new File("my_repo/.git"))
.build();
该构建器具有流畅的 API,可提供查找 Git 存储库所需的所有内容,无论您的程序是否确切知道其位置。它可以使用环境变量 (.readEnvironment()
),从工作目录中的某个位置开始并进行搜索 (.setWorkTree(…).findGitDir()
),或像上面一样打开已知的 .git
目录。
获得 Repository
实例后,您可以使用它执行各种操作。以下是一些快速采样
// Get a reference
Ref master = repo.getRef("master");
// Get the object the reference points to
ObjectId masterTip = master.getObjectId();
// Rev-parse
ObjectId obj = repo.resolve("HEAD^{tree}");
// Load raw object contents
ObjectLoader loader = repo.open(masterTip);
loader.copyTo(System.out);
// Create a branch
RefUpdate createBranch1 = repo.updateRef("refs/heads/branch1");
createBranch1.setNewObjectId(masterTip);
createBranch1.update();
// Delete a branch
RefUpdate deleteBranch1 = repo.updateRef("refs/heads/branch1");
deleteBranch1.setForceUpdate(true);
deleteBranch1.delete();
// Config
Config cfg = repo.getConfig();
String name = cfg.getString("user", null, "name");
这里有很多内容,所以让我们逐一浏览。
第一行获取指向 master
引用。JGit 会自动获取驻留在 refs/heads/master
中的实际 master
引用,并返回一个允许您获取有关引用的信息的对象。您可以获取名称 (.getName()
) 以及直接引用的目标对象 (.getObjectId()
) 或符号引用指向的引用 (.getTarget()
)。引用对象还用于表示标记引用和对象,因此您可以询问标记是否“已剥离”,这意味着它指向(可能很长的)标记对象字符串的最终目标。
第二行获取 master
引用的目标,它作为 ObjectId 实例返回。ObjectId 表示对象的 SHA-1 哈希,该对象可能存在或不存在于 Git 的对象数据库中。第三行类似,但展示了 JGit 如何处理 rev-parse 语法(有关此内容的更多信息,请参阅 分支引用);您可以传递 Git 理解的任何对象说明符,JGit 将返回该对象的有效 ObjectId 或 null
。
接下来的两行展示了如何加载对象的原始内容。在此示例中,我们调用 ObjectLoader.copyTo()
将对象的直接内容流式传输到 stdout,但 ObjectLoader 还具有读取对象类型和大小以及将其作为字节数组返回的方法。对于大型对象(其中 .isLarge()
返回 true
),您可以调用 .openStream()
以获取类似 InputStream 的对象,该对象可以在不一次将其全部拉入内存的情况下读取原始对象数据。
接下来的几行显示了创建新分支所需的操作。我们创建了一个 RefUpdate 实例,配置了一些参数,并调用 .update()
来触发更改。紧随其后的是删除该分支的代码。请注意,此操作需要 .setForceUpdate(true)
;否则,.delete()
调用将返回 REJECTED
,并且不会发生任何事情。
最后一个示例展示了如何从 Git 配置文件中获取 user.name
值。此 Config 实例使用我们之前为本地配置打开的存储库,但会自动检测全局和系统配置文件并从中读取值。
这只是完整管道 API 的一个小示例;还有更多方法和类可用。这里也没有展示 JGit 如何处理错误,即通过使用异常。JGit API 有时会抛出标准 Java 异常(例如 IOException
),但还提供了一些 JGit 特定的异常类型(例如 NoRemoteRepositoryException
、CorruptObjectException
和 NoMergeBaseException
)。
Porcelain
管道 API 非常完整,但将它们串在一起以实现常见目标(例如将文件添加到索引或进行新提交)可能会很麻烦。JGit 提供了一组更高级别的 API 来提供帮助,而这些 API 的入口点是 Git
类
Repository repo;
// construct repo...
Git git = new Git(repo);
Git 类有一组不错的、高级的生成器风格的方法,可用于构建一些非常复杂的行为。我们来看一个示例——执行类似于 git ls-remote
的操作
CredentialsProvider cp = new UsernamePasswordCredentialsProvider("username", "p4ssw0rd");
Collection<Ref> remoteRefs = git.lsRemote()
.setCredentialsProvider(cp)
.setRemote("origin")
.setTags(true)
.setHeads(false)
.call();
for (Ref ref : remoteRefs) {
System.out.println(ref.getName() + " -> " + ref.getObjectId().name());
}
这是 Git 类的常见模式;这些方法返回一个命令对象,该对象允许你链接方法调用以设置参数,这些参数在你调用 .call()
时执行。在这种情况下,我们要求 origin
远程获取标签,但不要获取 HEAD。还要注意使用 CredentialsProvider
对象进行身份验证。
可以通过 Git 类使用许多其他命令,包括但不限于 add
、blame
、commit
、clean
、push
、rebase
、revert
和 reset
。
延伸阅读
这只是 JGit 全部功能的一个小示例。如果你有兴趣并想了解更多信息,请参阅以下内容以获取信息和灵感
-
官方 JGit API 文档可在 https://www.eclipse.org/jgit/documentation 找到。这些是标准 Javadoc,因此您最喜欢的 JVM IDE 也能够在本地安装它们。
-
位于 https://github.com/centic9/jgit-cookbook 的 JGit Cookbook 提供了许多有关如何使用 JGit 执行特定任务的示例。