天天看點

jGit常用使用介紹

作者:效能IT哥

JGit - Pro Git v2 中文版 - UDN開源文檔 (yonyoucloud.com)

位址: http://doc.yonyoucloud.com/doc/wiki/project/pro-git-two/jgit.html

Jgit基礎教程(Java調用git)

前言

最近公司需要做一個java調用git的工具,這裡簡單的介紹了一下基本操作方法以及一些衍生的資訊擷取,或有不對的地方請大家批評指正。轉載請注明出處。

一、Jgit依賴導入

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

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

二、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:\\Users\\yang.yang\\Desktop\\test";    //本地倉庫位置
           

結果:

jGit常用使用介紹

2.初始化(init)

git指令:

git init

Jgit代碼:

Git git = Git.init().setDirectory(new File(localPath)).call();
System.out.println(git);
           

參數:

String localPath = "C:\\Users\\yang.yang\\Desktop\\test1";    //本地倉庫位置
           

結果:

jGit常用使用介紹

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()方法

結果:

jGit常用使用介紹

4.送出(Commit)

git指令:

git commit -m"first commit"

Jgit代碼:

git.commit().setMessage("first commit").call();
           

結果:

jGit常用使用介紹

5.狀态(status)

git指令:

git status

Jgit代碼:

Map<String,String> map = new HashMap<String,String>();
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);
           

備注:

裡面記錄的我目前已經知道的屬性,得到的結果是檔案名,還有其他的屬性可以自行研究。

結果:

jGit常用使用介紹

四、分支操作(Branch)

1.建立分支(Create Branch)

git指令:

git branch dev

Jgit代碼:

git.branchCreate()
        .setName("dev") //建立的分支名字
        .call();  
           

結果:

jGit常用使用介紹

2.删除分支(Delete Branch)

git指令:

git branch -d dev

Jgit代碼:

git.branchDelete()
        .setBranchNames("dev")   //設定删除分支的名字
        .call();
           

結果:

jGit常用使用介紹

3.切換分支(Checkout Branch)

git指令:

git checkout dev

Jgit代碼:

git.checkout()
        .setName("dev") //設定分支名
        .call();
           

結果:

jGit常用使用介紹

4.所有分支(BranchList)

git指令:

git branch

Jgit代碼:

List<Ref> call = git.branchList().call();     //得到所有分支資訊
for(Ref ref : call)
    System.out.println(ref);
           

備注:

得到的資訊是所有内容,可以用函數處理,例如ref.getName()可得到名字相關内容

結果:

jGit常用使用介紹

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();
           

備注:

合并操作是一項危險的操作,我隻是做了一個簡單嘗試,更多的功能還需要自行研究。

結果:

jGit常用使用介紹

五、遠端倉庫操作(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

jGit常用使用介紹

push執行後

jGit常用使用介紹

2.拉取(Pull)

git指令:

git pull origin

Jgit代碼:

CredentialsProvider provider = new UsernamePasswordCredentialsProvider(userName, password);  //生成身份資訊
git.pull()
        .setRemoteBranchName("master")  //設定需要pull的遠端分支
        .setCredentialsProvider(provider)  //身份驗證
        .call();
           

結果:

jGit常用使用介紹

3.克隆(Clone)

git指令:

git clone http://[email protected]: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:\\Users\\yang.yang\\Desktop\\test";    //本地倉庫位置
String remotePath = "http://[email protected]:10101/r/Test/test01.git";  //遠端倉庫URL
String branch = "master";   //克隆目标分支
String userName = "admin";  //遠端倉庫使用者名
String password = "admin";  //遠端倉庫密碼密碼
           

結果:

jGit常用使用介紹

4.設定遠端連接配接(Set Remote)

git指令:

git remote master http://[email protected]:10101/r/Test/test01.git

Jgit代碼:

git.remoteAdd()
        .setName("master")   //設定remote名字
        .setUri(new URIish("http://[email protected]:10101/r/Test/test01.git"))  //設定url
        .call();
           

結果:

jGit常用使用介紹

5.删除遠端連接配接(Remove remote)

git指令:

git remote rm master

Jgit代碼:

git.remoteRemove()
        .setRemoteName("master")
        .call();
           

結果:

jGit常用使用介紹

6.擷取所有遠端連接配接(All Remote)

git指令:

git remote -v

Jgit代碼:

Map<String, String> urlMap = new HashMap<>();
    List<RemoteConfig> remoteConfigList = git
            .remoteList()   //擷取list
            .call();
    for (RemoteConfig x : remoteConfigList) {
        urlMap.put(x.getName(), x.getURIs().toString());   //擷取名字,擷取URL
    }
   System.out.println(urlMap);
           

結果:

jGit常用使用介紹

六、标簽(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();
           

結果:

jGit常用使用介紹

2.所有标簽(All Tag)

git指令:

git tag

Jgit代碼:

List<Ref> 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
            }
           

結果:

jGit常用使用介紹

3.删除标簽(Delete Tag)

git指令:

git tag -d V1.0

Jgit代碼:

git.tagDelete()
        .setTags("V1.0")   //設定tag名
        .call();
           

結果:

jGit常用使用介紹

4.将标簽推送至遠端(Push Tag)

git指令:

Jgit代碼:

CredentialsProvider provider = new UsernamePasswordCredentialsProvider(userName, password);  //生成身份資訊
git.push().setRemote("origin")  //設定remote
        .setPushTags()   //pushtag
        .setCredentialsProvider(provider)
        .call();
           

備注:

預設是推送目前倉庫内所有tag,單個推送目前沒找到方法,得自行研究。

結果:

jGit常用使用介紹

七、差異對比(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的差別。

結果:

jGit常用使用介紹

2.目前暫存區與最後一次送出之間的對比(Current staging area and last commit)

git指令:

git diff

Jgit代碼:

git.diff()           
       .setOutputStream(outputStream) //輸出流  用outputStream,後面轉成字元串
       .call();
System.out.println(outputStream.toString());
           

結果:

jGit常用使用介紹

八、回溯(Reset&Revert)

1.Reset

git指令:

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();  //設定參數
           

結果:

jGit常用使用介紹

2.Revert

git指令:

git revert

Jgit代碼:

RevWalk walk = new RevWalk(git.getRepository());
RevCommit revCommit = walk.parseCommit(ObjectId.fromString(commitid));
git.revert().include(revCommit).call();
           

結果:

jGit常用使用介紹

備注:

Reset和Revert結果比較複雜,示範的隻是一個可行的方法,具體應用請檢視文尾的官方文檔。

九、參考連結

參考文檔:https://github.com/centic9/jgit-cookbook

官方文檔:http://archive.eclipse.org/jgit/site/5.3.0.201903130848-r/apidocs/index.html

繼續閱讀