jGit常用使用介绍
JGit - Pro Git v2 中文版 - UDN开源文档 (yonyoucloud.com)
地址: http://doc.yonyoucloud.com/doc/wiki/project/pro-git-two/jgit.htmlJgit基础教程(Java调用git)前言
最近公司需要做一个java调用git的工具,这里简单的介绍了一下基本操作方法以及一些衍生的信息获取,或有不对的地方请大家批评指正。转载请注明出处。 一、Jgit依赖导入 org.eclipse.jgit org.eclipse.jgit 4.4.1.201607150455-r org.eclipse.jgit org.eclipse.jgit.archive 5.8.1.202007141445-r 二、Jgit获取Git操作对象
获取Git对象是一切git操作的基础,笔者写了一个方法封装了一下。 import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Repository; public class JGitUtils { public static Git openRpo(String dir){ Git git = null; try { Repository repository = new FileRepositoryBuilder() .setGitDir(Paths.get(dir, ".git").toFile()) .build(); git = new Git(repository); } catch (IOException e) { e.printStackTrace(); } return git; } } 三、基础操作(Base)1.打开仓库(open)git命令:
git Bash Here Jgit代码: Git git = jGitUtils.openRpo(localPath); //获取git对象 System.out.println(git); 参数: String localPath = "C:Usersyang.yangDesktoptest"; //本地仓库位置 结果:
2.初始化(init)git命令:
git init Jgit代码:Git git = Git.init().setDirectory(new File(localPath)).call(); System.out.println(git); 参数:String localPath = "C:Usersyang.yangDesktoptest1"; //本地仓库位置 结果:
3.添加到暂存区(Add)git命令:
git add .
git add Delete.txt
git add Modify.txt
git add Folder/InFolder.txt Jgit代码:git.add().addFilepattern(".").call(); //添加全部文件 git.add().addFilepattern("New.txt").call(); git.add().addFilepattern("Delete.txt").call(); git.add().addFilepattern("Modify.txt").call(); git.add().addFilepattern("Folder/InFolder.txt").call(); git.rm().addFilepattern("Delete.txt").call(); 备注:
删除和移动的文件不能使用git.add(),需要使用git.rm()的方式,就算参数是"."也需要使用 git.rm()方法 结果:
4.提交(Commit)git命令:
git commit -m"first commit" Jgit代码:git.commit().setMessage("first commit").call(); 结果:
5.状态(status)git命令:
git status Jgit代码:Map map = new HashMap(); Git git = jGitUtils.openRpo(localPath); Status status = git.status().call(); map.put("Added",status.getAdded().toString()); map.put("Changed",status.getChanged().toString()); map.put("Conflicting",status.getConflicting().toString()); map.put("ConflictingStageState",status.getConflictingStageState().toString()); map.put("IgnoredNotInIndex",status.getIgnoredNotInIndex().toString()); map.put("Missing",status.getMissing().toString()); map.put("Modified",status.getModified().toString()); map.put("Removed",status.getRemoved().toString()); map.put("UntrackedFiles",status.getUntracked().toString()); map.put("UntrackedFolders",status.getUntrackedFolders().toString()); System.out.println(map); 备注:
里面记录的我目前已经知道的属性,得到的结果是文件名,还有其他的属性可以自行研究。 结果:
四、分支操作(Branch)1.创建分支(Create Branch)git命令:
git branch dev Jgit代码:git.branchCreate() .setName("dev") //创建的分支名字 .call(); 结果:
2.删除分支(Delete Branch)git命令:
git branch -d dev Jgit代码:git.branchDelete() .setBranchNames("dev") //设置删除分支的名字 .call(); 结果:
3.切换分支(Checkout Branch)git命令:
git checkout dev Jgit代码:git.checkout() .setName("dev") //设置分支名 .call(); 结果:
4.所有分支(BranchList)git命令:
git branch Jgit代码:List[ call = git.branchList().call(); //得到所有分支信息 for(Ref ref : call) System.out.println(ref); 备注:
得到的信息是所有内容,可以用函数处理,例如ref.getName()可得到名字相关内容 结果:
5.合并分支(Merge Branch)git命令:
在master分支上使用 git merge dev Jgit代码:Ref refdev = git.checkout().setName("dev").call(); //切换分支获取分支信息存入Ref对象里 git.checkout().setName("master").call(); //切换回master分支 MergeResult mergeResult = git.merge().include(refdev) // 合并目标分支 .setCommit(true) //同时提交 .setFastForward(MergeCommand.FastForwardMode.NO_FF)// 分支合并策略NO_FF代表普通合并 .setMessage("master Merge dev") //设置提交信息 // FF代表快速合并 .call(); 备注:
合并操作是一项危险的操作,我只是做了一个简单尝试,更多的功能还需要自行研究。 结果:
五、远端仓库操作(Repository)1.推送(Push)git命令:
git push origin master Jgit代码:CredentialsProvider provider = new UsernamePasswordCredentialsProvider(userName, password); //生成身份信息 git.push() .setRemote("origin") //设置推送的URL名称 .setRefSpecs(new RefSpec(branch)) //设置需要推送的分支,如果远端没有则创建 .setCredentialsProvider(provider) //身份验证 .call(); 备注:
这种推送需要在已经设置remote的情况下进行。 结果
之前提交的log
push执行后
2.拉取(Pull)git命令:
git pull origin Jgit代码:CredentialsProvider provider = new UsernamePasswordCredentialsProvider(userName, password); //生成身份信息 git.pull() .setRemoteBranchName("master") //设置需要pull的远端分支 .setCredentialsProvider(provider) //身份验证 .call(); 结果:
3.克隆(Clone)git命令:
git clone http://admin@10.179.2.14:10101/r/Test/test01.git Jgit代码://克隆 CredentialsProvider provider = new UsernamePasswordCredentialsProvider(userName, password); //生成身份信息 File localpath = new File(localPath); Git git = Git.cloneRepository() .setURI(remotePath) //设置git远端URL .setDirectory(localpath) //设置本地仓库位置 .setCredentialsProvider(provider) //设置身份验证 .setCloneSubmodules(true) //设置是否克隆子仓库 .setBranch(branch) //设置克隆分支 .call(); //启动命令 git.getRepository().close(); git.close(); //关闭源,以释放本地仓库锁 参数:String localPath = "C:Usersyang.yangDesktoptest"; //本地仓库位置 String remotePath = "http://admin@10.179.2.14:10101/r/Test/test01.git"; //远端仓库URL String branch = "master"; //克隆目标分支 String userName = "admin"; //远端仓库用户名 String password = "admin"; //远端仓库密码密码 结果:
4.设置远程连接(Set Remote)git命令:
git remote master http://admin@10.179.2.14:10101/r/Test/test01.git Jgit代码:git.remoteAdd() .setName("master") //设置remote名字 .setUri(new URIish("http://admin@10.179.2.14:10101/r/Test/test01.git")) //设置url .call(); 结果:
5.删除远程连接(Remove remote)git命令:
git remote rm master Jgit代码:git.remoteRemove() .setRemoteName("master") .call(); 结果:
6.获取所有远程连接(All Remote)git命令:
git remote -v Jgit代码:Map urlMap = new HashMap<>(); List remoteConfigList = git .remoteList() //获取list .call(); for (RemoteConfig x : remoteConfigList) { urlMap.put(x.getName(), x.getURIs().toString()); //获取名字,获取URL } System.out.println(urlMap); 结果:
六、标签(Tag)1.创建标签(Create Tag)git命令:
git -a V1.0 -m "test tag" 9167dadd48bca196208a4687b5d4706e355c42b6 Jgit代码: ObjectId id = git.getRepository().resolve("9167dadd48bca196208a4687b5d4706e355c42b6"); //获取提交的ObjectID RevWalk walk = new RevWalk(git.getRepository()); //获取RevWalk对象 RevCommit commit = walk.parseCommit(id); //获取该commitID的RevCommit对象 git.tag().setObjectId(commit) //设置commit .setName("V1.0") //设置tag名字 .setMessage("test tag") //设置tag注释 // .setAnnotated() //是否为annotate .call(); 结果:
2.所有标签(All Tag)git命令:
git tag Jgit代码: List][ refList = git.tagList().call(); //获取所有tag RevWalk walk = new RevWalk(git.getRepository()); for (Ref ref : refList) { System.out.println("commitID:"+walk.parseCommit(ref.getObjectId()).getName()); // 通过ref获取objectID System.out.println("tagName:" + ref.getName()); // 然后通过walk获取commit对象再获 // 取commitId } 结果:
3.删除标签(Delete Tag)git命令:
git tag -d V1.0 Jgit代码:git.tagDelete() .setTags("V1.0") //设置tag名 .call(); 结果:
4.将标签推送至远程(Push Tag)git命令:Jgit代码:CredentialsProvider provider = new UsernamePasswordCredentialsProvider(userName, password); //生成身份信息 git.push().setRemote("origin") //设置remote .setPushTags() //pushtag .setCredentialsProvider(provider) .call(); 备注:
默认是推送当前仓库内所有tag,单个推送目前没找到方法,得自行研究。 结果:
七、差异对比(Diff)1.两个版本之间的对比(Between two Commit)git命令:
git diff HEAD HEAD^ Jgit代码:ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); AbstractTreeIterator newTreeIter = prepareTreeParser(git.getRepository(), git.getRepository().resolve("HEAD").getName()); AbstractTreeIterator oldTreeIter = prepareTreeParser(git.getRepository(), git.getRepository().resolve("HEAD^").getName()); git.diff() .setNewTree(newTreeIter) //设置源,不设置则默认工作区和历史最新commit版本比较 .setOldTree(oldTreeIter) // .setPathFilter(PathFilter.create(".txt")) //设置过滤 .setOutputStream(outputStream) //输出流 用outputStream,后面转成字符串 .call(); System.out.println(outputStream.toString()); public static AbstractTreeIterator prepareTreeParser(Repository repository, String objectId) throws IOException { try (RevWalk walk = new RevWalk(repository)) { RevCommit commit = walk.parseCommit(ObjectId.fromString(objectId)); RevTree tree = walk.parseTree(commit.getTree().getId()); CanonicalTreeParser treeParser = new CanonicalTreeParser(); try (ObjectReader reader = repository.newObjectReader()) { treeParser.reset(reader, tree.getId()); } walk.dispose(); return treeParser; } } 备注:
prepareTreeParser是一个把RevCommit对象转换成AbstractTreeIterator方法,Jgit中的Tree和Ref是存储git对象的类,具体作用请阅读文尾的官方文档。
当diff()方法中不指定NewTree和OldTree时,默认比较工作区和当前分支最后一次commit的区别。 结果:
2.当前暂存区与最后一次提交之间的对比(Current staging area and last commit)git命令:
git diff Jgit代码:git.diff() .setOutputStream(outputStream) //输出流 用outputStream,后面转成字符串 .call(); System.out.println(outputStream.toString()); 结果:
八、回溯(Reset&Revert)1.Resetgit命令:
git reset Jgit代码:RevWalk walk = new RevWalk(git.getRepository()); //获取walk对象 ObjectId objectId = git.getRepository().resolve("9167dadd48bca196208a4687b5d4706e355c42b6"); //ObjectId对象 RevCommit revCommit = walk.parseCommit(objectId); //获取Revcommit对象 String perVision = revCommit.getParent(0).getName(); //获取commit的身份名 git.reset().setMode(ResetCommand.ResetType.HARD).setRef(perVision).call(); //设置参数 结果:
2.Revertgit命令:
git revert Jgit代码:RevWalk walk = new RevWalk(git.getRepository()); RevCommit revCommit = walk.parseCommit(ObjectId.fromString(commitid)); git.revert().include(revCommit).call(); 结果:
备注:
Reset和Revert结果比较复杂,演示的只是一个可行的方法,具体应用请查看文尾的官方文档。 九、参考链接
参考文档:https://github.com/centic9/jgit-cookbook
官方文档:http://archive.eclipse.org/jgit/site/5.3.0.201903130848-r/apidocs/index.html]