jgit是存java实现的git版本控制,学习jgit能够更好的理解学习git,其源代码托管在github上JGit。主要的模块以下:java
使用JGit的软件有:EGit(Eclipse git版本管理插件)、Gitblit等。其maven配置坐标为:git
<dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit</artifactId> <version>4.11.0.201803080745-r</version> </dependency>
官方文档github
RevTree 表明树对象api
Git.init().setGitDir(new File("D:\\source-code\\temp\\.git")).call();--------------不推荐,由于这样新建出来在.git/config文件下面多了一个core.workTree属性,其值为user.dir属性,而不是工做区为temp目录 //推荐以下方式: File dir = new File("D:\\source-code\\temp\\.git"); Git.init().setGitDir(dir).setDirectory(dir.getParentFile()).call();
只须要简单的一行代码就能够建立本地仓库,能够调用setBare方法来设置版本库是否为裸版本库。
注意org.eclipse.jgit.api.Git这个类,其方法返回全部支持的git命令
另外对于全部的命令,使用Builder模式。服务器
Repository build = null; try { build = new RepositoryBuilder().setGitDir(new File("D:\\source-code\\temp\\.git")).setMustExist(true) .build(); build.getConfig().setString(ConfigConstants.CONFIG_USER_SECTION, null, ConfigConstants.CONFIG_KEY_NAME, "xxxx"); build.getConfig().save(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != build) { //为了节省篇幅,后续代码省略调Git对象和Repository对象的close方法 build.close(); } }
设置完之后能够到.git/config目录下面看到配置生效。版本库api并无直接提供修改系统或者用户级别的配置(--system、--global),若是用户须要修改这两个级别的,能够参考FileRepository 的构造函数:eclipse
if (StringUtils.isEmptyOrNull(SystemReader.getInstance().getenv( Constants.GIT_CONFIG_NOSYSTEM_KEY))) systemConfig = SystemReader.getInstance().openSystemConfig(null, getFS()); else systemConfig = new FileBasedConfig(null, FS.DETECTED) { @Override public void load() { // empty, do not load } @Override public boolean isOutdated() { // regular class would bomb here return false; } }; userConfig = SystemReader.getInstance().openUserConfig(systemConfig, getFS()); loadSystemConfig(); //load完之后,能够直接修改config对象了,最后save一下就能够了 loadUserConfig();
AddCommand能够把工做区的内容添加到暂存区。maven
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用于提交操做ide
Git git =Git.open(new File("D:\\source-code\\temp\\user1\\.git")); CommitCommand commitCommand = git.commit().setMessage("master 23 commit").setAllowEmpty(true); commitCommand.call();
StatusCommand命令等同于git 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)); //工做区删除的文件列表
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())); });
CloneCommand等价与git clone命令
Git.cloneRepository().setURI("https://admin@localhost:8443/r/game-of-life.git") .setDirectory(new File("D:\\source-code\\temp-1")).call();
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();
而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();
RevWalk基本是jgit中使用最多的api了,不少jgit的命令就是使用该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对象的内容 } } }