JGit學習


參考:

https://blog.csdn.net/Amy126/article/details/85335834

https://blog.csdn.net/yulin_Hu/article/details/81673446

https://blog.csdn.net/gaoyong3013/article/details/84295783?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

 https://github.com/smltq/spring-boot-demo/tree/master/jGit

 

 

 

java 使用jgit 操作 git

如果你想在一個 Java 程序中使用 Git ,有一個功能齊全的 Git 庫,那就是 JGit 。 JGit 是一個用 Java 寫成的功能相對健全的 Git 的實現,它在 Java 社區中被廣泛使用。 JGit 項目由 Eclipse 維護,它的主頁在 http://www.eclipse.org/jgit 。

1、在本地文件夾建立起與遠程倉庫的連接

2、根據主干master新建分支並同步到遠程

3、提交commit文件到遠程

4、從遠程拉去代碼到本地文件夾

 

maven依賴

<dependency>
     <groupId>org.eclipse.jgit</groupId>
     <artifactId>org.eclipse.jgit</artifactId>
     <version>3.7.0.201502260915-r</version>
</dependency>
public class GitUtilClass {
    public static String localRepoPath = "D:/repo";
    public static String localRepoGitConfig = "D:/repo/.git";
    public static String remoteRepoURI = "git@gitlab.com:wilson/test.git";
    public static String localCodeDir = "D:/platplat";
    
    /**
     * 新建一個分支並同步到遠程倉庫
     * @param branchName
     * @throws IOException
     * @throws GitAPIException
     */
    public static String newBranch(String branchName){
        String newBranchIndex = "refs/heads/"+branchName;
        String gitPathURI = "";
        Git git;
        try {
            
            //檢查新建的分支是否已經存在,如果存在則將已存在的分支強制刪除並新建一個分支
            List<Ref> refs = git.branchList().call();
            for (Ref ref : refs) {
                if (ref.getName().equals(newBranchIndex)) {
                    System.out.println("Removing branch before");
                    git.branchDelete().setBranchNames(branchName).setForce(true)
                            .call();
                    break;
                }
            }            
            //新建分支
            Ref ref = git.branchCreate().setName(branchName).call();
            //推送到遠程
            git.push().add(ref).call();
            gitPathURI = remoteRepoURI + " " + "feature/" + branchName;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (GitAPIException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return gitPathURI;                
    }
    
    public static void commitFiles() throws IOException, GitAPIException{
        String filePath = "";
        Git git = Git.open( new File(localRepoGitConfig) );
        //創建用戶文件的過程
        File myfile = new File(filePath);
        myfile.createNewFile();
        git.add().addFilepattern("pets").call();   
        //提交
        git.commit().setMessage("Added pets").call();   
        //推送到遠程
        git.push().call();
    }
    
    public static boolean pullBranchToLocal(String cloneURL){
        boolean resultFlag = false;
        String[] splitURL = cloneURL.split(" ");
        String branchName = splitURL[1];
        String fileDir = localCodeDir+"/"+branchName;
        //檢查目標文件夾是否存在
        File file = new File(fileDir);
        if(file.exists()){
            deleteFolder(file);
        }
        Git git;
        try {
            git = Git.open( new File(localRepoGitConfig) );
            git.cloneRepository().setURI(cloneURL).setDirectory(file).call();
            resultFlag = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (GitAPIException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return resultFlag;    
    }
    
    public static void deleteFolder(File file){
        if(file.isFile() || file.list().length==0){
            file.delete();
        }else{
            File[] files = file.listFiles();
            for(int i=0;i<files.length;i++){
                deleteFolder(files[i]);
                files[i].delete();
            }
        }
    }
    
    public static void setupRepo() throws GitAPIException{
        //建立與遠程倉庫的聯系,僅需要執行一次
        Git git = Git.cloneRepository().setURI(remoteRepoURI).setDirectory(new File(localRepoPath)).call();
    }
    

 

 

 

 

JGit 使用說明

初步

  1. jdk 1.8
  2. 第一次我們需要clone這個git,這個git就是我們的schema集。
  Git git=Git.cloneRepository() .setURI("git號") .setDirectory(new File("gitProject")) .call();

 

這樣的話,這個git工程就被clone到了我們指定的目錄。
3. 當然第二次我們不能再clone了,我們只需要打開上次的git工程就可以進行操作。

Git git=Git.open(new File("gitProject"));
  1. 當我們新增或是修改一個文件的時候:
 DirCache index=git.add().addFilepattern("schemas/test.md").call(); RevCommit commit=git.commit().setMessage("addFile").call(); git.push().call();

這個新增的文件需要位於我們拉下來的那個git工程里面。

  1. 查看一個文件所有的版本(也就是提交記錄):在git的命令行中,我們是通過git log 或是git log –filename來實現。這個通過API的實現方式如下:
git.log().addPath(dir/filename.txt).setMaxCount(num).call();

setMaxCount可以指定返回最近num個版本,addPath則是指定查看文件.返回的是Iterable,我們可以通過其迭代器對其進行遍歷。我們需要的是得到每一次變更的時間,message,提交的內部識別碼,提交人

            Iterable<RevCommit> iterable=git.log().call(); Iterator<RevCommit> iter=iterable.iterator(); while (iter.hasNext()){ RevCommit commit=iter.next(); String email=commit.getAuthorIdent().getEmailAddress(); String name=commit.getAuthorIdent().getName(); //作者 String commitEmail=commit.getCommitterIdent().getEmailAddress();//提交者 String commitName=commit.getCommitterIdent().getName(); int time=commit.getCommitTime(); String fullMessage=commit.getFullMessage(); String shortMessage=commit.getShortMessage(); //返回message的firstLine String commitID=commit.getName(); //這個應該就是提交的版本號 System.out.println("authorEmail:"+email); System.out.println("authorName:"+name); System.out.println("commitEmail:"+commitEmail); System.out.println("commitName:"+commitName); System.out.println("time:"+time); System.out.println("fullMessage:"+fullMessage); System.out.println("shortMessage:"+shortMessage); System.out.println("commitID:"+commitID); } 

 

結果:這個log我們並沒有指定哪一個文件,也沒有指定返回多少個,我們可以如前面提到那樣指定文件,指定返回個數,但是從結果中我們確實得到我們想要的東西

authorEmail:yulin@DESKTOP-ALAIMHD authorName:yulin commitEmail:yulin@DESKTOP-ALAIMHD commitName:yulin time:1515468403 fullMessage:addFile shortMessage:addFile commitID:d22491b948e8013df552549a753dcafd4d9b3c4b authorEmail:*** authorName:*** commitEmail:*** commitName:*** time:1515463064 fullMessage:[添加]gitignore文件 shortMessage:[添加]gitignore文件 commitID:be1be26068cd4fb5653c6efd3299f465d5863234

 

注意這里有這樣一個問題,如果你使用了.addPath(dir/filename.txt),也就是你只想得到某個文件的提交。這種方式的確可以實現,如果某一次的提交,包含了多個文件,其中包含了這個文件,該次提交也會被包含到結果其中。(其實這個還是可以理解的。)

  1. 我們得到指定文件的所有版本后,需要去取得每一個版本的變化,這樣我們才能顯示出每一個版本不同的內容。git命令可以用diff實現,那么在JGit中的調用呢.
    如我們比較一個特定文件最近兩次的提交內容的不同。那么我們首先需要得到最近兩次的commit。然后根據commit得到變化內容。如下:
   Git git=Git.open(new File("gitProject")); Repository repository=git.getRepository(); List<RevCommit> list=new ArrayList<RevCommit>(); Iterable<RevCommit> iterable=git.log().addPath("schemas/test1.md").setMaxCount(2).call(); for(RevCommit revCommit:iterable){ list.add(revCommit); } if(list.size()==2){ AbstractTreeIterator newCommit=getAbstractTreeIterator(list.get(0),repository); AbstractTreeIterator oldCommit=getAbstractTreeIterator(list.get(1),repository); List<DiffEntry> diff=git.diff().setOldTree(oldCommit).setNewTree(newCommit).call(); ByteArrayOutputStream outputStream=new ByteArrayOutputStream(); DiffFormatter diffFormatter=new DiffFormatter(outputStream); //設置比較器為忽略空白字符對比(Ignores all whitespace) diffFormatter.setDiffComparator(RawTextComparator.WS_IGNORE_ALL); diffFormatter.setRepository(repository); // 這里為什么還要設置它 for(DiffEntry diffEntry:diff){ diffFormatter.format(diffEntry); System.out.println(outputStream.toString("UTF-8")); outputStream.reset(); } } git.close(); 

 

另外需要通過下面這個方法根據commit得到AbstractTreeIterator,如下:

    public static AbstractTreeIterator getAbstractTreeIterator(RevCommit commit, Repository repository ){ RevWalk revWalk=new RevWalk(repository); CanonicalTreeParser treeParser=null; try { RevTree revTree=revWalk.parseTree(commit.getTree().getId()); treeParser=new CanonicalTreeParser(); treeParser.reset(repository.newObjectReader(),revTree.getId()); revWalk.dispose(); } catch (IOException e) { e.printStackTrace(); } return treeParser; }

 

通過以上代碼,我們可以得到schemas/test1.md文件兩次commit內容的不同,結果如下:

diff --git a/schemas/test.md b/schemas/test.md
index e8fce5c..c226794 100644
--- a/schemas/test.md +++ b/schemas/test.md @@ -1,4 +1,4 @@ -# JSON測試效率總結 +# JSON測試效率總結 test4

 

 

我們可以看到得到的結果的變化內容已經用 - +進行了標注,這與我們平常看到的diff命令結果是相符合的

但是這里就有這樣的一個問題,我們雖然通過addPath來得到了某個文件的commit,但是我們得到diff內容是通過commit來的,如果一次commit包含多個文件,那么我們的diff內容自然也會所有更改文件的內容,那么這與我們說的得到某個文件的變化內容就有一定的出入了,但是這是因為我們的一次commit包含多個文件修改導致的。

那么我們能否對DiffEntry的內容進行篩選呢?通過前面的代碼我們看到事實上我們的變化內容是通過DiffEntry來得到的,如果一次提交內容包含了多個文件的改變,那么我們也會得到對應數目的DiffEntry,我們需要對DiffEntry進行篩選,從而挑選出對應特定文件的DiffEntry,從而得到特定文件的變化內容,接下來試一試。

  1. 篩選DiffEntry

    發現DiffEntry中有oldPath,newPath這樣的屬性。

    /** File name of the old (pre-image). */ protected String oldPath; /** File name of the new (post-image). */ protected String newPath;

那么如果我們得到了文件名,那就就可以根據文件名進行篩選了,如下:

           for(DiffEntry diffEntry:diff){
                diffFormatter.format(diffEntry); System.out.println("new Path:____"+diffEntry.getNewPath()); System.out.println("old path:____"+diffEntry.getOldPath()); System.out.println(outputStream.toString("UTF-8")); outputStream.reset(); }

結果:確實我們得到了文件名

new Path:____schemas/test.md
old path:____schemas/test.md
diff --git a/schemas/test.md b/schemas/test.md
index e8fce5c..c226794 100644
--- a/schemas/test.md +++ b/schemas/test.md @@ -1,4 +1,4 @@ -# JSON測試效率總結 +# JSON測試效率總結 test4 

 

  1. 通過前面我們基本可以得到制指定文件版本之間的差異內容,接下來我們去獲取指定文件指定版本的文件內容,以下為示例代碼:
 public static ByteArrayOutputStream read(String revision, Git git) { ByteArrayOutputStream out = new ByteArrayOutputStream(); Repository repository = null; try { //gitDir表示git庫目錄 // Git git = Git.open(new File("gitProject")); repository = git.getRepository(); RevWalk walk = new RevWalk(repository); ObjectId objId = repository.resolve(revision); RevCommit revCommit = walk.parseCommit(objId); RevTree revTree = revCommit.getTree(); //child表示相對git庫的文件路徑 TreeWalk treeWalk = TreeWalk.forPath(repository, "schemas/test.md", revTree); ObjectId blobId = treeWalk.getObjectId(0); ObjectLoader loader = repository.open(blobId); loader.copyTo(out); } catch (IOException e) { e.printStackTrace(); } catch (JGitInternalException e) { e.printStackTrace(); } finally { if (repository != null) repository.close(); } return out; } //調用 ByteArrayOutputStream outputStream=read("f532e63bac93f05345da1ff665687e69df9732dc",git); System.out.println(outputStream.toString("UTF-8"));

我們仍然是通過commitID去獲取,不過這里是直接給出了CommitID,我們同樣可以像前面的代碼那樣先獲取commit,結果我們確實拿到了這個版本文件的全部內容。(結果太多就不進行展示了)

 

 

 

 

JGit常用功能(提交、回滾、日志查詢)

public class GitUtil {
 
    private final static String GIT         = ".git";
 
    private final static String REF_REMOTES = "refs/remotes/origin/";
 
    /**
     * 將文件列表提交到git倉庫中
     * @param gitRoot git倉庫目錄
     * @param files 需要提交的文件列表
     * @param remark 備注
     * @return 返回本次提交的版本號
     * @throws IOException 
     */
    public static String commitToGitRepository(String gitRoot, List<String> files, String remark)
                                                                                                 throws Exception {
        if (StringUtils.isNotBlank(gitRoot) && files != null && files.size() > 0) {
 
            File rootDir = new File(gitRoot);
 
            //初始化git倉庫
            if (new File(gitRoot + File.separator + GIT).exists() == false) {
                Git.init().setDirectory(rootDir).call();
            }
 
            //打開git倉庫
            Git git = Git.open(rootDir);
            //判斷工作區與暫存區的文件內容是否有變更
            List<DiffEntry> diffEntries = git.diff()
                .setPathFilter(PathFilterGroup.createFromStrings(files))
                .setShowNameAndStatusOnly(true).call();
            if (diffEntries == null || diffEntries.size() == 0) {
                throw new Exception("提交的文件內容都沒有被修改,不能提交");
            }
            //被修改過的文件
            List<String> updateFiles = new ArrayList<String>();
            ChangeType changeType;
            for (DiffEntry entry : diffEntries) {
                changeType = entry.getChangeType();
                switch (changeType) {
                    case ADD:
                    case COPY:
                    case RENAME:
                    case MODIFY:
                        updateFiles.add(entry.getNewPath());
                        break;
                    case DELETE:
                        updateFiles.add(entry.getOldPath());
                        break;
                }
            }
            //將文件提交到git倉庫中,並返回本次提交的版本號
            //1、將工作區的內容更新到暫存區
            AddCommand addCmd = git.add();
            for (String file : updateFiles) {
                addCmd.addFilepattern(file);
            }
            addCmd.call();
            //2、commit
            CommitCommand commitCmd = git.commit();
            for (String file : updateFiles) {
                commitCmd.setOnly(file);
            }
            RevCommit revCommit = commitCmd.setCommitter("yonge", "654166020@qq.com")
                .setMessage(remark).call();
            return revCommit.getName();
        }
        return null;
    }
 
    /**
     * 回滾到指定版本的上一個版本
     * @param gitRoot git倉庫目錄
     * @param diffEntries 需要回滾的文件
     * @param revision 版本號
     * @param remark 備注
     * @return
     * @throws Exception
     */
    public static boolean rollBackPreRevision(String gitRoot, List<DiffEntry> diffEntries,
                                              String revision, String remark) throws Exception {
 
        if (diffEntries == null || diffEntries.size() == 0) {
            throw new Exception("沒有需要回滾的文件");
        }
 
        Git git = Git.open(new File(gitRoot));
 
        List<String> files = new ArrayList<String>();
 
        //注意:下面的reset命令會將暫存區的內容恢復到指定(revesion)的狀態,相當於取消add命令的操作
        /*Repository repository = git.getRepository();
        RevWalk walk = new RevWalk(repository);
        ObjectId objId = repository.resolve(revision);
        RevCommit revCommit = walk.parseCommit(objId);
        String preVision = revCommit.getParent(0).getName();
        ResetCommand resetCmd = git.reset();
        for (String file : files) {
            resetCmd.addPath(file);
        }
        resetCmd.setRef(preVision).call();
        repository.close();*/
 
        //取出需要回滾的文件,新增的文件不回滾
        for (DiffEntry diffEntry : diffEntries) {
            if (diffEntry.getChangeType() == ChangeType.DELETE) {
                continue;
            } else {
                files.add(diffEntry.getNewPath());
            }
        }
 
        if (files.size() == 0) {
            throw new Exception("沒有需要回滾的文件");
        }
 
        //checkout操作會丟失工作區的數據,暫存區和工作區的數據會恢復到指定(revision)的版本內容
        CheckoutCommand checkoutCmd = git.checkout();
        for (String file : files) {
            checkoutCmd.addPath(file);
        }
        //加了“^”表示指定版本的前一個版本,如果沒有上一版本,在命令行中會報錯,例如:error: pathspec '4.vm' did not match any file(s) known to git.
        checkoutCmd.setStartPoint(revision + "^");
        checkoutCmd.call();
 
        //重新提交一次
        CommitCommand commitCmd = git.commit();
        for (String file : files) {
            commitCmd.setOnly(file);
        }
        commitCmd.setCommitter("yonge", "654166020@qq.com").setMessage(remark).call();
 
        return true;
    }
 
    /**
     * 獲取上一版本的變更記錄,如果是新增的文件,不會顯示,因為做回滾時不需要回滾新增的文件
     * @param gitRoot git倉庫目錄
     * @param revision 版本號
     * @return
     * @throws Exception
     */
    public static List<DiffEntry> rollBackFile(String gitRoot, String revision) throws Exception {
 
        Git git = Git.open(new File(gitRoot));
        Repository repository = git.getRepository();
 
        ObjectId objId = repository.resolve(revision);
        Iterable<RevCommit> allCommitsLater = git.log().add(objId).call();
        Iterator<RevCommit> iter = allCommitsLater.iterator();
        RevCommit commit = iter.next();
        TreeWalk tw = new TreeWalk(repository);
        tw.addTree(commit.getTree());
        commit = iter.next();
        if (commit != null) {
            tw.addTree(commit.getTree());
        } else {
            throw new Exception("當前庫只有一個版本,不能獲取變更記錄");
        }
 
        tw.setRecursive(true);
        RenameDetector rd = new RenameDetector(repository);
        rd.addAll(DiffEntry.scan(tw));
        List<DiffEntry> diffEntries = rd.compute();
        if (diffEntries == null || diffEntries.size() == 0) {
            return diffEntries;
        }
        Iterator<DiffEntry> iterator = new ArrayList<DiffEntry>(diffEntries).iterator();
        DiffEntry diffEntry = null;
        while (iterator.hasNext()) {
            diffEntry = iterator.next();
            System.out.println("newPath:" + diffEntry.getNewPath() + "    oldPath:"
                               + diffEntry.getOldPath() + "   changeType:"
                               + diffEntry.getChangeType());
            if (diffEntry.getChangeType() == ChangeType.DELETE) {
                iterator.remove();
            }
        }
        return diffEntries;
    }

 

 

 

 

 

JGit----將 Git 嵌入你的應用

如果你想在一個 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對象的內容 } } }

其它更多命令參考官網

資料

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM