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

org.eclipse.jgit

org.eclipse.jgit

5.12.0.202106070339-r

(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参数我是通过数据库获取的,大家用的时候也可以放入配置文件中配置)

@Slf4j

public 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;

}

/**

* 初始化(init)——git init

*/

public static void init(String localPath) throws GitAPIException {

Git.init().setDirectory(new File(localPath)).call();

}

/**

* 添加到暂存区(Add)git add .

* git add Delete.txt

* 删除和移动的文件不能使用git.add(),需要使用git.rm()的方式,就算参数是“.”也需要使用 git.rm()方法

*/

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

}

/**

* 提交(Commit) git commit -m"first commit"

*/

public static void commit(String localPath, String commitInfo) throws Exception {

openRpo(localPath).commit().setMessage(Optional.ofNullable(commitInfo).orElse("default commit info")).call();

}

/**

* 移动(mv)

*/

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

}

}

/**

* 状态(status) git status

*

* @throws Exception

*/

public static Map status(String localPath) throws Exception {

Map 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;

}

/**

* ===============================分支操作=============================

*/

/**

* 创建分支(Create Branch) git branch dev

*

* @throws Exception

*/

public static void branch(String localPath, String branchName) throws Exception {

openRpo(localPath).branchCreate()

.setName(branchName)

.call();

}

/**

* 删除分支(Delete Branch) git branch -d dev

*

* @throws Exception

*/

public static void delBranch(String localPath, String branchName) throws Exception {

openRpo(localPath).branchDelete()

.setBranchNames(branchName)

.call();

}

/**

* 切换分支(Checkout Branch) git checkout dev

*

* @throws Exception

*/

public static void checkoutBranch(String localPath, String branchName) throws Exception {

openRpo(localPath).checkout()

.setName(branchName)

.call();

}

/**

* 所有分支(BranchList) git branch

*

* @throws Exception

*/

public static List listBranch(String localPath) throws Exception {

return openRpo(localPath).branchList().call();

}

/**

* 合并分支(Merge Branch) git merge dev

*

* @throws Exception

*/

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

}

/**

* ========================远端仓库操作(Repository)==============================

*/

/**

* 推送(Push) git push origin master

*

* @throws Exception

*/

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

}

/**

* /拉取(Pull) git pull origin

*

* @throws Exception

*/

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

}

/**

* 克隆(Clone) git clone https://xxx.git

*

* @throws Exception

*/

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客户端。 下面是示例代码:

@Slf4j

public 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("文件移动异常!");

}

}

}

3.如果你的git服务端使用的是gitlab,还可以使用gitlab的api来操作。下面是具体的实现操作: (1)在gitlab中配置访问令牌。

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

org.gitlab4j

gitlab4j-api

4.19.0

(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 getOptionalFile(Integer projectId, String filepath, String branch) throws GitLabApiException {

return gitLabApi.getRepositoryFileApi().getOptionalFile(projectId, filepath, branch);

}

public static List getProjects() throws GitLabApiException {

return gitLabApi.getProjectApi().getProjects();

}

//查询文件树结构

public static List getFileTree(Integer gitProjId, String branch, String filePath) throws GitLabApiException {

return gitLabApi.getRepositoryApi().getTree(gitProjId,filePath,branch,true);//默认递归查询

}

//获取blob文件列表

public static List getFileList(Integer gitProjId, String branch, String filePath) throws GitLabApiException {

List tree = gitLabApi.getRepositoryApi().getTree(gitProjId, filePath, branch, true);//默认递归查询 筛选出文件后返回list

ArrayList treeItems = new ArrayList<>();

for (TreeItem treeItem : tree) {

if ("blob".equals(treeItem.getType().toString()) ) {

treeItems.add(treeItem);

}

}

return treeItems;

}

public static List 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);

}

}

参考链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: