如果你想在一个 Java 程序中使用 Git ,有一个功能齐全的 Git 库,那就是 JGit 。 JGit 是一个用 Java 写成的功能相对健全的 Git 的实现,它在 Java 社区中被广泛使用。 JGit 项目由 Eclipse 维护,它的主页

依赖添加

有很多种方式可以将 JGit 依赖加入到你的项目,并依靠它去写代码。 最简单的方式也许就是使用 Maven 。你可以通过在你的 pom.xml 文件里的 标签中增加像下面这样的片段来完成这个整合。

    <dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>5.5.1.201910021850-r</version>
</dependency>

在你读到这段文字时 version 很可能已经更新了,所以请浏览 http://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit 以获取最新的仓库信息。 当这一步完成之后, Maven 就会自动获取并使用你所需要的 JGit 库。

项目实践

在搭建我的博客的过程中,因为该博客是部署在自己的服务器上,需要在ci自动编译完成后,实现自动部署到我的服务器上(该步实现的方式很多,通过开放git接口,有编译部署的时候自动拉取到我的服务器就是其中的一个方法)

以下主要使用了pull拉取方法

package com.easy.jGit.controller;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.*;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Repository;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.io.File; @RestController
@Slf4j
public class JGitController { /**
* git仓路径
*/
final String patch = "/opt/webapps/blog/.git"; /**
* 代码分支
*/
final String branch = "origin/gh-pages"; /**
* 拉取
*
* @return
*/
@RequestMapping("/pull")
public String pull() {
String result;
Repository repo = null;
try {
repo = new FileRepository(new File(patch));
Git git = new Git(repo); log.info("开始重置");
//重置
git.reset()
.setMode(ResetCommand.ResetType.HARD)
.setRef(branch).call(); log.info("开始拉取"); //拉取
git.pull()
.setRemote("origin")
.setRemoteBranchName("gh-pages")
.call();
result = "拉取成功!";
log.info(result);
} catch (Exception e) {
result = e.getMessage();
} finally {
if (repo != null) {
repo.close();
}
}
return result;
} /**
* 重置
*
* @return
*/
@RequestMapping("/reset")
public String reset() {
String result; Repository repo = null;
try {
repo = new FileRepository(new File(patch));
Git git = new Git(repo);
git.reset().setMode(ResetCommand.ResetType.HARD).setRef(branch).call();
result = "重置成功!"; } catch (Exception e) {
result = e.getMessage();
} finally {
if (repo != null) {
repo.close();
}
}
return result;
} /**
* 恢复
*/
@RequestMapping("/revert")
public String revert() {
String result; Repository repo = null;
try {
repo = new FileRepository(new File(patch));
Git git = new Git(repo);
git.revert().call();
result = "恢复成功!"; } catch (Exception e) {
result = e.getMessage();
} finally {
if (repo != null) {
repo.close();
}
}
return result;
} /**
* 克隆
*
* @return
*/
@RequestMapping("/clone")
public String clone() {
String result;
try {
Git.cloneRepository()
.setURI("https://github.com/smltq/blog.git")
.setDirectory(new File("/blog"))
.call();
result = "克隆成功了!";
} catch (GitAPIException e) {
result = e.getMessage();
e.printStackTrace();
}
return result;
} /**
* 状态
*/
@RequestMapping("/status")
public static void status() {
File RepoGitDir = new File("/blog/.git");
Repository repo = null;
try {
repo = new FileRepository(RepoGitDir.getAbsolutePath());
Git git = new Git(repo);
Status status = git.status().call();
log.info("Git Change: " + status.getChanged());
log.info("Git Modified: " + status.getModified());
log.info("Git UncommittedChanges: " + status.getUncommittedChanges());
log.info("Git Untracked: " + status.getUntracked());
} catch (Exception e) {
log.info(e.getMessage());
} finally {
if (repo != null) {
repo.close();
}
}
}
}

.travis.yml 源文件

language: node_js # 设置语言
node_js: stable # 设置相应版本
cache:
apt: true
directories:
- node_modules # 缓存不经常更改的内容
before_install:
- export TZ='Asia/Shanghai' # 更改时区
- npm install hexo-cli -g
#- chmod +x ./publish-to-gh-pages.sh # 为shell文件添加可执行权限
install:
- npm install # 安装hexo及插件
script:
- hexo clean # 清除
- hexo g # 生成
after_script:
- git clone https://${GH_REF} .deploy_git
- cd .deploy_git
- git checkout master:gh-pages
- cd ../
- mv .deploy_git/.git/ ./public/
- cd ./public
- git config user.name "tqlin"
- git config user.email "smltq@126.com"
# add commit timestamp
- git add .
- git commit -m "Travis CI Auto Builder at `date +"%Y-%m-%d %H:%M"`"
- git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages && curl http://49.235.170.100:8787/pull
- curl http://49.235.170.100:8787/pull #这里调用上面实现的拉取接口
branches:
only:
- master # 只监测master分支
env:
global:
- GH_REF: github.com/smltq/blog.git #设置GH_REF

基本概念

  • Repository 包括所有的对象和引用,用来管理源码

  • AnyObjectId 表示SHA1对象,可以获得SHA1的值,进而可以获得git对象

  • Ref 引用对象,表示.git/refs下面的文件引用 Ref HEAD = repository.getRef("refs/heads/master");

  • RevWalk 可以遍历提交对象,并按照顺序返回提交对象

  • RevCommit 代表一个提交对象

  • RevTag 代表标签对象

  • RevTree 代表树对象

其它常用命令

大多数 JGit 会话会以 Repository 类作为起点,你首先要做的事就是创建一个它的实例。 对于一个基于文件系统的仓库来说(JGit 允许其它的存储模型),用 FileRepositoryBuilder 完成它。

// 创建一个新仓库
Repository newlyCreatedRepo = FileRepositoryBuilder.create(
new File("/tmp/new_repo/.git"));
newlyCreatedRepo.create(); // 打开一个存在的仓库
Repository existingRepo = new FileRepositoryBuilder()
.setGitDir(new File("my_repo/.git"))
.build();

当你拥有一个 Repository 实例后,你就能对它做各种各样的事。比如:

// 获取引用
Ref master = repo.getRef("master"); // 获取该引用所指向的对象
ObjectId masterTip = master.getObjectId(); // Rev-parse
ObjectId obj = repo.resolve("HEAD^{tree}"); // 装载对象原始内容
ObjectLoader loader = repo.open(masterTip);
loader.copyTo(System.out); // 创建分支
RefUpdate createBranch1 = repo.updateRef("refs/heads/branch1");
createBranch1.setNewObjectId(masterTip);
createBranch1.update(); // 删除分支
RefUpdate deleteBranch1 = repo.updateRef("refs/heads/branch1");
deleteBranch1.setForceUpdate(true);
deleteBranch1.delete(); // 配置
Config cfg = repo.getConfig();
String name = cfg.getString("user", null, "name");

提交命令

AddCommand可以把工作区的内容添加到暂存区。

Git git = Git.open(new File("D:\\source-code\\temp\\.git"));
git.add().addFilepattern(".").call(); // 相当与git add -A添加所有的变更文件git.add().addFilepattern("*.java")这种形式是不支持的
git.add().addFilepattern("src/main/java/").call(); // 添加目录,可以把目录下的文件都添加到暂存区
//jgit当前还不支持模式匹配的方式,例如*.java

CommitCommand用于提交操作

Git git =Git.open(new File("D:\\source-code\\temp\\user1\\.git"));
CommitCommand commitCommand = git.commit().setMessage("master 23 commit").setAllowEmpty(true);
commitCommand.call();

status命令

    Git git = Git.open(new File("D:\\source-code\\temp-1\\.git"));
Status status = git.status().call(); //返回的值都是相对工作区的路径,而不是绝对路径
status.getAdded().forEach(it -> System.out.println("Add File :" + it)); //git add命令后会看到变化
status.getRemoved().forEach(it -> System.out.println("Remove File :" + it)); ///git rm命令会看到变化,从暂存区删除的文件列表
status.getModified().forEach(it -> System.out.println("Modified File :" + it)); //修改的文件列表
status.getUntracked().forEach(it -> System.out.println("Untracked File :" + it)); //工作区新增的文件列表
status.getConflicting().forEach(it -> System.out.println("Conflicting File :" + it)); //冲突的文件列表
status.getMissing().forEach(it -> System.out.println("Missing File :" + it)); //工作区删除的文件列表

log命令

LogCommand相当于git log命令

//提取某个作者的提交,并打印相关信息
Git git = Git.open(new File("D:\\source-code\\temp-1\\.git"));
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Iterable<RevCommit> results = git.log().setRevFilter(new RevFilter() {
@Override
public boolean include(RevWalk walker, RevCommit cmit)
throws StopWalkException, MissingObjectException, IncorrectObjectTypeException, IOException {
return cmit.getAuthorIdent().getName().equals("xxxxx dsd");
} @Override
public RevFilter clone() {
return this;
}
}).call();
results.forEach(commit -> {
PersonIdent authoIdent = commit.getAuthorIdent();
System.out.println("提交人: " + authoIdent.getName() + " <" + authoIdent.getEmailAddress() + ">");
System.out.println("提交SHA1: " + commit.getId().name());
System.out.println("提交信息: " + commit.getShortMessage());
System.out.println("提交时间: " + format.format(authoIdent.getWhen()));
});

fetch命令

fetch命令

Repository rep = new FileRepository("D:\\source-code\\temp-1\\.git");
Git git = new Git(rep);
git.pull().setRemote("origin").call();
//fetch命令提供了setRefSpecs方法,而pull命令并没有提供,所有pull命令只能fetch所有的分支
git.fetch().setRefSpecs("refs/heads/*:refs/heads/*").call();

push命令

而PushCommand和git push相同,一般都需要我们提供用户名和密码,需要用到CredentialsProvider类

Repository rep = new FileRepository("D:\\source-code\\temp-1\\.git");
Git git = new Git(rep);
git.push().setCredentialsProvider(new UsernamePasswordCredentialsProvider("myname", "password")).call();

clone命令

CloneCommand等价与git clone命令

Git.cloneRepository().setURI("https://admin@localhost:8443/r/game-of-life.git")
.setDirectory(new File("D:\\source-code\\temp-1")).call();

RevWalk API

以下代码实现这样一个功能,查找某个文件的历史记录,并把每个提交的文件内容打印出来。

 DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Repository repository = new RepositoryBuilder().setGitDir(new File("D:\\source-code\\temp-1\\.git")).build();
try (RevWalk walk = new RevWalk(repository)) {
Ref head = repository.findRef("HEAD");
walk.markStart(walk.parseCommit(head.getObjectId())); // 从HEAD开始遍历,
for (RevCommit commit : walk) {
RevTree tree = commit.getTree(); TreeWalk treeWalk = new TreeWalk(repository, repository.newObjectReader());
PathFilter f = PathFilter.create("pom.xml");
treeWalk.setFilter(f);
treeWalk.reset(tree);
treeWalk.setRecursive(false);
while (treeWalk.next()) {
PersonIdent authoIdent = commit.getAuthorIdent();
System.out.println("提交人: " + authoIdent.getName() + " <" + authoIdent.getEmailAddress() + ">");
System.out.println("提交SHA1: " + commit.getId().name());
System.out.println("提交信息: " + commit.getShortMessage());
System.out.println("提交时间: " + format.format(authoIdent.getWhen())); ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repository.open(objectId);
loader.copyTo(System.out); //提取blob对象的内容
}
}
}

其它更多命令参考官网

资料

Spring Boot、Cloud 学习项目

JGit----将 Git 嵌入你的应用的更多相关文章

  1. JAVA 使用jgit管理git仓库

    最近设计基于gitops新的CICD方案,需要通过java读写git仓库,这里简单记录下. JGit是一款pure java的软件包,可以读写git仓库,下面介绍基本使用. 引入jgit maven引 ...

  2. Git中文版教程

    1. 起步 1.1 关于版本控制 1.2 Git 简史 1.3 Git 基础 1.4 命令行 1.5 安装 Git 1.6 初次运行 Git 前的配置 1.7 获取帮助 1.8 总结 2. Git 基 ...

  3. Git Pro Book

    目录 2nd Edition (2014) Switch to 1st Edition Download Ebook The entire Pro Git book, written by Scott ...

  4. java操作git简单实现

    记录瞬间 import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.ecli ...

  5. 如何在Ubuntu 16.04安装的Git【转】

    转自:https://www.howtoing.com/how-to-install-git-on-ubuntu-16-04/ 介绍 现代软件开发中不可或缺的工具是某种版本控制系统. 版本控制系统允许 ...

  6. 通过jgit一次性升级fastjson版本

    背景:笔者所在公司经历了三次fastjson的升级,由于集群,工程数量众多,每次升级都很麻烦.因此开发了一个java的升级工具. 功能介绍: 功能介绍:一个jar文件,通过java -jar命令,输入 ...

  7. JGit、SvnKit - 版本提交日志(1)提取

    1.相关开源jar包  1>使用JGIT访问git项目  2>使用SVNkit访问svn Git官方JGit使用教程指导 2.Git历史提交日志导出到文件 在项目根目录执行如下命令,将日志 ...

  8. 探讨 Git 代码托管平台的若干问题

    关于 Git 版本控制软件种类繁多,维基百科收录的最早的版本控制系统是 1972 年贝尔实验室开发的 Source Code Control System.1986 年 Concurrent Vers ...

  9. 探讨 Git 代码托管平台的若干问题 - 2019 版

    关于 Git 版本控制软件种类繁多,维基百科收录的最早的版本控制系统是 1972 年贝尔实验室开发的 Source Code Control System.1986 年 Concurrent Vers ...

随机推荐

  1. python学习之【第八篇】:Python中的函数基础

    1.前言 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段.函数能提高应用的模块性,和代码的重复利用率. 2.函数的定义 定义函数时需要遵守以下规则: 函数代码块以 def 关键词开头 ...

  2. 使用Samba或实现文件共享

    安装Samba服务软件包: 命令:yum install samba 使用Samba服务口令验证方式可以让共享文件更加的安全,做到仅让信任的用户访问,而且验证过程也很简单 第1步:检查当前是否为use ...

  3. PHP Laravel 队列技巧:Fail、Retry 或者 Delay

    当创建队列jobs.监听器或订阅服务器以推送到队列中时,您可能会开始认为,一旦分派,队列工作器决定如何处理您的逻辑就完全由您自己决定了. 嗯……并不是说你不能从作业内部与队列工作器交互,但是通常情况下 ...

  4. [LC] 108题 将有序数组转换为二叉搜索树 (建树)

    ①题目 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定有序数组: [-10,- ...

  5. Vue img的src使用数据绑定不显示

    不少人在vue的开发中遇到这样一个问题: img的src属性绑定url变量,然而图片加载失败. <img src="{{ imgUrl }}"/> 原因:写法错误 解决 ...

  6. mpvue开发微信小程序,分享按钮报错:`Cannot read property 'apply' of null`

    用mpvue开发微信小程序,分享按钮报错:Cannot read property 'apply' of null onShareAppMessage 是于微信小程序Pages的生命周期钩子,顾这个方 ...

  7. 如何在当前文件夹打开cmd(基于win10)

    如何在当前文件夹打开cmd(基于win10) 方法一: 1.先打开你要进入的文件夹 2.在标记的位置输入cmd,就可以进入当前文件的cmd 方法二: 1.打开你要进入的文件夹 2.通过shift + ...

  8. python-语言元素

    变量命令 对于每个变量我们需要给它取一个名字.在python中,变量命名需要遵循一下这些必须遵守硬性规则和强烈建议遵守的非硬性规则. 硬性规则 变量名由字母(广义的Unicode字符,不包括特殊字符) ...

  9. LVM扩容案例

    LVM基础命令: pvdisplay 查看检查pv pvremove /dev/sdb #清除一个pv fdisk -l 检查磁盘 df -h 检查全部磁盘大小 df -Th 检查磁盘大小和分区格式类 ...

  10. 堆 堆排序 优先队列 图文详解(Golang实现)

    引入 在实际应用中,我们经常需要从一组对象中查找最大值或最小值.当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低.哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是堆( ...