文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何使用java来操作git/gitlab?

2023-09-25 20:23

关注

在我们的学习和开发过程中,git作为一个优秀的分布式版本控制工具是经常会被我们使用到的,那么如何通过java代码来实现Git的更新,提交,推送等操作呢?
1.首先我们会想到的应该是寻找市面上是否已经有了比较成熟的、开源的git客户端。这是我推荐使用一个比较成熟的git客户端——JGit。JGit 是一个轻量级纯 Java 的类库,用来实现 Git 的版本控制系统的访问,以及提供核心的版本控制算法。EGit 这个 Eclipse 上的 Git 插件就是采用 JGit 开发的。
如果你对git和jgit还不熟悉,推荐学习书籍:pro git
下面介绍如何在代码中集成jgit:
(1)在pom.xml中引入如下依赖:

<dependency>            <groupId>org.eclipse.jgitgroupId>            <artifactId>org.eclipse.jgitartifactId>            <version>5.12.0.202106070339-rversion>        dependency>

(2)编写配置类JgitConfig.java

@Configuration@ConfigurationProperties(prefix = "jgit")public class JgitConfig {    private static String username;    private static String password;    public static String getUsername() {        return username;    }    public void setUsername(String username) {        JgitConfig.username = username;    }    public static String getPassword() {        return password;    }    public void setPassword(String password) {        JgitConfig.password = password;    }}

(3)application.yml文件配置

jgit:  username: #git账号名  password: #git密码

(4)编写JgitUtil工具类。(注:由于业务原因,方法中需要的localPath参数我是通过数据库获取的,大家用的时候也可以放入配置文件中配置)

@Slf4jpublic class JgitUtil {        private static CredentialsProvider provider = new UsernamePasswordCredentialsProvider(JgitConfig.getUsername(), JgitConfig.getPassword());    public static Git openRpo(String localPath) {        Git git = null;        try {            Repository repository = new FileRepositoryBuilder()                    .setGitDir(Paths.get(localPath, ".git").toFile())                    .build();            git = new Git(repository);        } catch (IOException e) {            e.printStackTrace();        }        return git;    }        public static void init(String localPath) throws GitAPIException {        Git.init().setDirectory(new File(localPath)).call();    }        public static void add(String localPath, String fileName) throws Exception {        openRpo(localPath).add().addFilepattern(Optional.ofNullable(fileName).orElse(".")).call();    }    public static void rm(String localPath, String fileName) throws Exception {        openRpo(localPath).rm().addFilepattern(fileName).call();    }        public static void commit(String localPath, String commitInfo) throws Exception {        openRpo(localPath).commit().setMessage(Optional.ofNullable(commitInfo).orElse("default commit info")).call();    }        public static void mv(String localPath, String sourcePath, String targetPath, File file) {        System.out.println(sourcePath);        try {            File newDir = new File(targetPath);            if (!newDir.exists()) {                newDir.mkdirs();            }            File newFile = new File(newDir, file.getName());            boolean success = file.renameTo(newFile);            if (success) {                add(localPath, ".");                rm(localPath, sourcePath);                commit(localPath, "File moved to new directory");                push(localPath);            } else {                // handle error                log.error("文件移动异常!");            }        } catch (Exception e) {            e.printStackTrace();        }    }        public static Map<String, String> status(String localPath) throws Exception {        Map<String, String> map = new HashMap<>();        Status status = openRpo(localPath).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());        return map;    }            public static void branch(String localPath, String branchName) throws Exception {        openRpo(localPath).branchCreate()                .setName(branchName)                .call();    }        public static void delBranch(String localPath, String branchName) throws Exception {        openRpo(localPath).branchDelete()                .setBranchNames(branchName)                .call();    }        public static void checkoutBranch(String localPath, String branchName) throws Exception {        openRpo(localPath).checkout()                .setName(branchName)                .call();    }        public static List<Ref> listBranch(String localPath) throws Exception {        return openRpo(localPath).branchList().call();    }        public static void mergeBranch(String localPath, String branchName, String commitMsg) throws Exception {        //切换分支获取分支信息存入Ref对象里        Ref refdev = openRpo(localPath).checkout().setName(branchName).call();        //切换回main分支        openRpo(localPath).checkout().setName("main").call();        // 合并目标分支        MergeResult mergeResult = openRpo(localPath).merge().include(refdev)                //同时提交                .setCommit(true)                // 分支合并策略NO_FF代表普通合并, FF代表快速合并                .setFastForward(MergeCommand.FastForwardMode.NO_FF)                .setMessage(Optional.ofNullable(commitMsg).orElse("master Merge"))                .call();    }            public static void push(String localPath) throws Exception {        openRpo(localPath).push()                //设置推送的URL名称如"origin"                .setRemote("origin")                //设置需要推送的分支,如果远端没有则创建                .setRefSpecs(new RefSpec("main"))                //身份验证                .setCredentialsProvider(provider)                .call();    }    public static void push(String localPath, String branch) throws Exception {        openRpo(localPath).push()                //设置推送的URL名称如"origin"                .setRemote("origin")                //设置需要推送的分支,如果远端没有则创建                .setRefSpecs(new RefSpec(branch))                //身份验证                .setCredentialsProvider(provider)                .call();    }        public static void pull(String localPath, String remotePath) throws Exception {        //判断localPath是否存在,不存在调用clone方法        File directory = new File(localPath);        if (!directory.exists()) {            gitClone(localPath, remotePath, "main");        }        openRpo(localPath).pull()                .setRemoteBranchName("main")                .setCredentialsProvider(provider)                .call();    }    public static void pull(String localPath, String remotePath, String branch) throws Exception {        //判断localPath是否存在,不存在调用clone方法        File directory = new File(localPath);        if (!directory.exists()) {            gitClone(localPath, remotePath, branch);        }        openRpo(localPath).pull()                .setRemoteBranchName(branch)                .setCredentialsProvider(provider)                .call();    }        public static void gitClone(String localPath, String remotePath, String branch) throws Exception {        //克隆        Git git = Git.cloneRepository()                .setURI(remotePath)                .setDirectory(new File(localPath))                .setCredentialsProvider(provider)                //设置是否克隆子仓库                .setCloneSubmodules(true)                //设置克隆分支                .setBranch(branch)                .call();        //关闭源,以释放本地仓库锁        git.getRepository().close();        git.close();    }}

(5)直接在对应的业务代码中调用上述工具类中的方法即可。
如果有些朋友还需要集成其他命令,可以了解下这个开源项目:https://github.com/centic9/jgit-cookbook,git的几乎所有操作都在这里面集成了。
2.另外一种方式大家想必也猜到了。既然可以在命令行中执行git命令来操作git,那么能不能通过使用java控制终端来执行git命令呢?答案是肯定的,但前提是需要在你电脑或服务器上先安装好git客户端。
下面是示例代码:

@Slf4jpublic class GitUtils {    public static String executeCommand(String command) {        StringBuilder output = new StringBuilder();        Process process;        try {            process = Runtime.getRuntime().exec(command);            process.waitFor();            BufferedReader reader = new BufferedReader(                    new InputStreamReader(process.getInputStream()));            String line;            while ((line = reader.readLine()) != null) {                output.append(line).append("\n");            }        } catch (IOException | InterruptedException e) {            e.printStackTrace();        }        return output.toString();    }    public static void cloneRepository(String remotePath, String localPath) {        String command = "git clone " + remotePath + " " + localPath;        String output = executeCommand(command);        System.out.println(output);    }    public static void pull(String localPath,String branch) {        String command = "git -C " + localPath + " pull origin "+branch;        String output = executeCommand(command);        System.out.println(output);    }    public static void checkoutBranch(String localPath, String branchName) {        String command = "git -C " + localPath + " checkout " + branchName;        String output = executeCommand(command);        System.out.println(output);    }    public static void commit(String localPath, String message) {        String command = "git -C " + localPath + " commit -a -m \"" + message + "\"";        String output = executeCommand(command);        System.out.println(output);    }    public static void add(String localPath) {        String command = "git -C " + localPath + " add .";        String output = executeCommand(command);        System.out.println(output);    }    public static void push(String localPath) {        String command = "git -C " + localPath + " push";        String output = executeCommand(command);        System.out.println(output);    }    public static void mv(File file,String localPath){        File newDir = new File(localPath);        if (!newDir.exists()) {            newDir.mkdirs();        }        File newFile = new File(newDir, file.getName());        boolean success = file.renameTo(newFile);        if (success) {            add(localPath);            commit(localPath,"File moved to new directory");            push(localPath);        } else {            // handle error            log.error("文件移动异常!");        }    }}

如果你的git服务端使用的是gitlab,还可以使用gitlab的api来操作。下面是具体的实现操作:
(1)在gitlab中配置访问令牌。
在这里插入图片描述

(2)pom.xml文件中引入依赖。

 <dependency>            <groupId>org.gitlab4jgroupId>            <artifactId>gitlab4j-apiartifactId>            <version>4.19.0version>        dependency>

(3)编写配置类,并在yml文件中配置。

@Configuration@ConfigurationProperties(prefix = "git")public class GitConfig {    public static String hostUrl;    public static String personalAccessToken;    public static String getHostUrl() {        return hostUrl;    }    public static void setHostUrl(String hostUrl) {        GitConfig.hostUrl = hostUrl;    }    public static String getPersonalAccessToken() {        return personalAccessToken;    }    public static void setPersonalAccessToken(String personalAccessToken) {        GitConfig.personalAccessToken = personalAccessToken;    }}
git:  hostUrl: #gitlab访问的ip+端口,如:http://127.0.0.1:8080  personalAccessToken: #刚刚配置的访问令牌

(4)编写工具类。(注:gitProjId,branch,filePath都可写入配置文件中,gitProjId为gitlab中对应的项目id,filePath为git本地文件路径)

public class GitLabApiUtils {    private static GitLabApi gitLabApi = new GitLabApi(GitConfig.hostUrl, GitConfig.personalAccessToken, null,null);    public static InputStream getRawFileStreamByProjId(Integer gitProjId, String branch, String filePath) throws GitLabApiException {        return   gitLabApi.getRepositoryFileApi().getRawFile(gitProjId,branch,filePath);    }    public static InputStream getRawFileStreamByGitPath(String gitPath,String branch,String filePath) throws GitLabApiException {        return   gitLabApi.getRepositoryFileApi().getRawFile(gitPath,branch,filePath);    }    public static RepositoryFile getFile(Integer projectId, String filepath, String branch) throws GitLabApiException {        return gitLabApi.getRepositoryFileApi().getFile(projectId, filepath, branch);    }    public static Optional<RepositoryFile> getOptionalFile(Integer projectId, String filepath, String branch) throws GitLabApiException {        return gitLabApi.getRepositoryFileApi().getOptionalFile(projectId, filepath, branch);    }    public static List<Project> getProjects() throws GitLabApiException {        return gitLabApi.getProjectApi().getProjects();    }    //查询文件树结构    public static List<TreeItem> getFileTree(Integer gitProjId, String branch, String filePath) throws GitLabApiException {        return gitLabApi.getRepositoryApi().getTree(gitProjId,filePath,branch,true);//默认递归查询    }    //获取blob文件列表    public static List<TreeItem> getFileList(Integer gitProjId, String branch, String filePath) throws GitLabApiException {        List<TreeItem> tree = gitLabApi.getRepositoryApi().getTree(gitProjId, filePath, branch, true);//默认递归查询  筛选出文件后返回list        ArrayList<TreeItem> treeItems = new ArrayList<>();        for (TreeItem treeItem : tree) {            if ("blob".equals(treeItem.getType().toString()) ) {                treeItems.add(treeItem);            }        }        return  treeItems;    }    public static List<TreeItem> getFileList(String projectPath, String branch, String filePath) throws GitLabApiException {        return gitLabApi.getRepositoryApi().getTree(projectPath,filePath,branch,true);//默认递归查询  筛选出文件后返回list    }    public static synchronized RepositoryFile createFile(Integer gitProjId , RepositoryFile file, String branch, String commit) throws GitLabApiException {        return  gitLabApi.getRepositoryFileApi().createFile(gitProjId,file,branch,commit);    }    public static synchronized RepositoryFile updateFile(Integer gitProjId , RepositoryFile file, String branch, String commit) throws GitLabApiException {        return  gitLabApi.getRepositoryFileApi().updateFile(gitProjId,file,branch,commit);    }    public static RepositoryFile getFileByProjId(Integer gitProjId,String branch,String filePath) throws GitLabApiException {        return   gitLabApi.getRepositoryFileApi().getFile(gitProjId,filePath,branch);    }}

来源地址:https://blog.csdn.net/ZhengXinMing1998/article/details/131759179

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯