通过 JGit 访问 Git 仓库

jopen 10年前

一个Git库仓在 JGit里面表现为Repository类,该类可以看作是这个库的句柄。通过Repository类实例,你可以创建JGit命令以及可以控制配置、参数等。

获取Git库仓的引用有很多种方法,看到很多人在这方面有困难,本文总结了如何通过JGit来访问Git库仓来帮助大家。

存储库和建造者

Repository类是抽象的,允许实现不同的存储后端。 举例来说,有一个InMemoryRepository类作为测试和实验。当然,最常用的是FileRepository,它表示的是一个本地文件系统。因为实际的实现被考虑为内置的,每一个Repository的实现都有一个相应的存储库建造者,他们应该被用于在内部创建实例。

因此FileRepositoryBuilder是一种被推荐的方式,用这种方式创建了一个FileRepository。由于历史原因,另外还有一个RepositoryBuilder,它是完全一样的,但是在下一个大版本升级之后将会被移除。

为了你的需要,一旦你已经配置了一个存储库构建器,调用它的build()方法来创建一个存储库。

FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();  repositoryBuilder.setMustExist( true );  repositoryBuilder.setGitDir( ... );  Repository repository = repositoryBuilder.build();

布局的原因,我在每行放置了一个方法调用,但是FileRepositoryBuilder还是一个流接口的实现,所以这个方法调用能够被链接。

这里讨论的所有方法只能应用于本地存储库。Git是一个分布式的版本控制系统,因此不是为了直接操作远程库设计。

为了操作远程库,首先你不得不克隆它。现在你可以在本地副本做些修改,例如提交新的或修改的文件,创建分支或标签等等。为了向远程库同步你的变更,你首先不得不从远程库集成(即获取)变更(如果有的话),然后最终推送你本地的变更。

推荐 setGitDir()

在JGit中,一个基于文件的存储库是通过一个目录被识别的。然而,识别一个存储库的两个目录在合适条件下可能出现:当前检出的版本属于工作目录并且git目录保存着对象数据库和元数据(如分支,标签等等)。

尽管FileRepositoryBuilder有setGitDir()方法和setWorkTree()方法,我推荐始终使用setGitDir()方法,因为:

  • 默认情况下,git目录是工作目录的一个直接子目录,但是这个可以通过一个环境变量或一个配置设置被覆盖。

  • 并且裸存储库根本就没有工作目录。

这是一个存储库吗?

FileRepositoryBuilder的build()方法不论一个存储库是否存在都会返回一个Repository。即使所给的目录不存在,一个实例也被返回了。

我发现有两种方式测试是否所给的目录真实的指向一个存在的存储库。通过调研setMustExist(true)方法,FileRepositoryBuilder 能被配置,只用来构建存在的存储库。一旦must-exist标记被打开,如果没有找到存储库,build()方法将抛出一个RepositoryNotFoundException 异常。值得一提的是,这种行为没有正式文档说明。这可能是JavaDoc中的一个失误,我怀疑这种行为会改变,但仍不能保证是否是API的一部分。

或者,你可以测试返回的存储库的对象数据库是否真实的存在。

Repository repository = repositoryBuilder.build();  if( repository.getObjectDatabase().exists() ) {    ...  }

顾名思义, 如果有一个对象数据库,ObjectDatabase.exists()返回true,否则返回false。

小技巧:findGitDir()

仓库生成器提供了一个findGitDir()方法用于从指定的路径开始搜索仓库并且回退到上级目录。

FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();  repositoryBuilder.addCeilingDirectory( new F‌ile( "/home/user" ) );  repositoryBuilder.findGitDir( new F‌ile( "/home/user/git/foo/bar" ) );

如果仓库路径被找到或者已到达根目录则搜索结束。getGitDir()可以用于获取搜索结果和返回找到的git路径,如果没找到则返回null。

通过添加一个或多个目录可以限制搜索。只要目录的其中一个被搜索到,则搜索结束。

另一种选择:Git.open()

如果你觉得FileRepositoryBuilder不方便使用,可以用等效的简写形式:Git.open()。

Git git = Git.open( new F‌ile( "/path/to/repo/.git" ) );

这个方法要求一个位于仓库中的表示路径的文件作为参数。路径可以是工作路径或者git路径。我建议在这里使用git路径。

如果给定的路径不存在或者不包含git仓库,将会抛出RepositoryNotFoundException异常。成功会返回Git类的实例,然后可以用它访问仓库(git.getRepository())和创建git命令。

JGit访问Git仓库的多种方式

Git.open()函数很简短,而FileRepositoryBuilder给了你更多的控制和可靠的方式来判断仓库是否存在。你喜欢前者还是后者完全取决于你的使用情况。记住,不要直接使用FileRepositoryBuilder构造函数或者在没有提前通知的情况下改变其行为。

我希望这篇文章有助于澄清怎样使用JGit访问仓库。如果你有进一步的问题,请在评论中回复。