Статьи

Как получить доступ к Git-репозиторию с помощью JGit

Репозиторий Git представлен в JGit через класс Repository, который можно рассматривать как дескриптор хранилища. С помощью экземпляра репозитория вы можете создавать команды JGit (через класс фабрики Git), получать доступ к настройкам конфигурации, разрешать ссылки и т. Д.

Есть несколько способов получить ссылку на репозиторий, и, поскольку я видел людей, имеющих проблемы тут и там, эта статья суммирует, как получить доступ к репозиторию Git с помощью JGit.

Хранилищ и строителей

Класс Repository является абстрактным, чтобы разрешить реализации с различными бэкэндами хранилища. Например, есть InMemoryRepository для тестов и экспериментов. Но, конечно, чаще всего используется FileRepository, представляющий хранилище в локальной файловой системе. Поскольку фактические реализации считаются внутренними, каждая реализация репозитория имеет соответствующий конструктор репозитория, который следует использовать для создания его экземпляров.

Следовательно, FileRepositoryBuilder является рекомендуемым способом создания FileRepository. По историческим причинам существует также RepositoryBuilder, который делает то же самое, но будет удален при следующем обновлении основной версии.

После того, как вы настроили построитель хранилища в соответствии со своими потребностями, вызовите его метод build (), чтобы создать хранилище.

1
2
3
4
FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();
repositoryBuilder.setMustExist( true );
repositoryBuilder.setGitDir( ... );
Repository repository = repositoryBuilder.build();

По причинам компоновки я поместил вызовы метода в одну строку, но FileRepositoryBuilder также реализует свободный интерфейс, так что вызовы методов могут быть связаны между собой.

Все обсуждаемые здесь методы применимы только к локальным репозиториям. Git — это распределенная система контроля версий, поэтому она не предназначена для непосредственного управления удаленным репозиторием.

Чтобы манипулировать удаленным репозиторием, вы должны сначала его клонировать. Теперь вы можете вносить изменения в локальную копию, например фиксировать новые или измененные файлы, создавать ветки или теги и т. Д. Чтобы синхронизировать ваши изменения с удаленным репозиторием, вам сначала нужно будет интегрировать (или извлекать) изменения (если они есть) с удаленного и, наконец, подтолкнуть ваши локальные изменения.

Предпочитаю setGitDir ()

В JGit файловый репозиторий идентифицируется через каталог. Тем не менее, есть два каталога, которые могут оказаться подходящими для идентификации хранилища: рабочий каталог, в котором находится текущая извлеченная ревизия, и каталог git, который содержит базу данных объектов и метаданные (например, ветви, теги и т. Д.).

Хотя FileRepositoryBuilder имеет setGitDir (), а также метод setWorkTree (), я рекомендую всегда использовать setGitDir (), потому что:

  • По умолчанию каталог git является прямым подкаталогом рабочего каталога, но его можно переопределить с помощью переменной среды или параметра конфигурации.
  • И еще есть голые репозитории, у которых вообще нет рабочего каталога.

Это хранилище?

Метод build () FileRepositoryBuilder возвращает репозиторий, независимо от того, существует репозиторий. Даже если данный каталог не существует, экземпляр возвращается.

Я нашел два способа проверить, действительно ли данный каталог указывает на существующий репозиторий. Вызывая setMustExist (true), FileRepositoryBuilder может быть настроен для создания только существующих репозиториев. Как только флаг обязательный существует, build () выдаст исключение RepositoryNotFoundException, если хранилище не найдено. Как примечание стороны, это поведение недокументировано. Это может быть просто ошибка в JavaDoc, и я сомневаюсь, что это поведение изменится, но все же нет никакой гарантии, как если бы оно было частью API.

В качестве альтернативы вы можете проверить, действительно ли существует объектная база данных возвращаемого репозитория.

1
2
3
4
Repository repository = repositoryBuilder.build();
if( repository.getObjectDatabase().exists() ) {
  ...
}

Как следует из названия, ObjectDatabase.exists () возвращает true, если база данных объектов существует, и false в противном случае.

Небольшой обход: findGitDir ()

Конструктор хранилища также предлагает метод findGitDir (), который можно использовать для поиска хранилища, начиная с заданного каталога и переходя от его родительской иерархии вверх.

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

Поиск заканчивается, если был найден либо каталог репозитория, либо был достигнут корень файловой системы. getGitDir () может быть использован для получения результата поиска и возвращает найденный каталог git или ноль, если ничего не найдено.

Поиск можно ограничить, добавив один или несколько потолочных каталогов. Если один из них достигнут при переходе по иерархии каталогов, поиск заканчивается.

Альтернатива: Git.open ()

Если вы обнаружите, что FileRepositoryBuilder неудобен в использовании, существует также сокращение: Git.open ().

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

Метод ожидает параметр File, который обозначает каталог, в котором находится хранилище. Каталог может указывать либо на рабочий каталог, либо на каталог git. Опять же, я рекомендую использовать каталог git здесь.

Если данный каталог не существует или не содержит хранилище, будет выдано исключение RepositoryNotFoundException. В случае успеха возвращается экземпляр класса Git, который можно использовать для доступа к хранилищу (git.getRepository ()) и создания команд git.

Более одного способа доступа к Git-репозиторию с помощью JGit

Хотя Git.open () хорош и короток, FileRepositoryBuilder дает вам больше контроля и надежный способ определить, существует ли хранилище. Предпочитаете ли вы первое или последнее, вероятно, зависит от вашего варианта использования. Просто помните, что не следует использовать конструктор FileRepository напрямую, поскольку он может исчезнуть или изменить свое поведение без предварительного уведомления.