zoukankan      html  css  js  c++  java
  • 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对象的内容
             }
         }
     }

    其它更多命令参考官网

    资料

  • 相关阅读:
    cocos2dx 3.0 飞机大战
    cocos2dx 3.0 触摸机制
    cocos2d-x 3.0 rc0 + flappybird 学习心得
    cocos2dx 3.0 +VS2012 环境搭建
    cocos2dx 内存管理(3)---CCPoolManager浅析
    cocos2dx 内存管理机制(2)
    Cocos2dx 入门小游戏实例
    myBaits入门
    Java8:函数式编程、Stream
    Java基础巩固
  • 原文地址:https://www.cnblogs.com/xuwc/p/13613189.html
Copyright © 2011-2022 走看看