初始化jgit的Git实例 @Value("${git.repository.dir}") private String gitDir; private void ensureGitWorkDir(String gitPath, File dir) throws Exception { if (dir.exists() dir.isDirectory()) { if (ArrayUtils.isEmpty(dir.list(new FilenameFi
@Value("${git.repository.dir}") private String gitDir; private void ensureGitWorkDir(String gitPath, File dir) throws Exception { if (dir.exists() && dir.isDirectory()) { if (ArrayUtils.isEmpty(dir.list(new FilenameFilter() { @Override public boolean accept(File parentDir, String name) { return name.endsWith(".git"); } }))) { gitClone(gitPath, dir); } if (gitRepositoryMap.get(dir.getAbsolutePath()) == null) { gitRepositoryMap.putIfAbsent(dir.getAbsolutePath(), Git.open(dir)); } return; } ReentrantLock lock = getLock(dir.getAbsolutePath()); try { lock.lock(); if (!dir.exists()) { dir.mkdirs(); } if (!dir.isDirectory()) { String path = dir.getAbsolutePath(); dir.renameTo(new File(dir.getAbsoluteFile().getParentFile(), dir.getName() + "_" + System.currentTimeMillis())); dir = new File(path); dir.mkdirs(); } if (ArrayUtils.isEmpty(dir.list())) { gitClone(gitPath, dir); } } finally { lock.unlock(); } }执行git的clone
private void gitClone(String gitPath, File dir) throws Exception { ReentrantLock lock = getLock(dir.getAbsolutePath()); try { lock.lock(); long time = System.currentTimeMillis(); Git git = Git.cloneRepository().setDirectory(dir).setURI(gitPath).call(); gitRepositoryMap.putIfAbsent(dir.getAbsolutePath(), git); logger.info("================gitClone time {} ms: {}, {}", (System.currentTimeMillis() - time), gitPath, dir.getAbsolutePath()); } finally { lock.unlock(); } }打tag
/** * 按commit hash来打tag */ public void tagByCommitHash(String gitPath, String branchName, String commitHash, String tagNameNew) throws Exception { tagByRef(gitPath, branchName, commitHash, tagNameNew); } /** * 按branch上的HEAD来打tag */ public void tagByBranchName(String gitPath, String branchName, String tagNameNew) throws Exception { tagByRef(gitPath, branchName, "refs/remotes/origin/" + branchName, tagNameNew); } /** * 按tag来打tag */ public void tagByTagName(String gitPath, String branchName, String tagNameOld, String tagNameNew) throws Exception { tagByRef(gitPath, branchName, "refs/tags/" + tagNameOld, tagNameNew); } private void tagByRef(String gitPath, String branchName, String tagRef, String tagNameNew) throws Exception { File dir = new File(gitDir, DigestUtils.md5DigestAsHex(gitPath.getBytes(StandardCharsets.UTF_8))); ReentrantLock lock = getLock(dir.getAbsolutePath()); try { lock.lock(); ensureGitWorkDir(gitPath, dir); long time = System.currentTimeMillis(); Git git = gitRepositoryMap.get(dir.getAbsolutePath()); git.fetch().setTagOpt(TagOpt.FETCH_TAGS) .setRefSpecs(new RefSpec("refs/heads/*:refs/remotes/origin/*")) .call(); // 判断tag是否已存在 List tagList = git.tagList().call(); if (tagList != null) { for (Ref ref : tagList) { if (ref.getName().endsWith(tagNameNew)) { throw new RuntimeException( String.format("tag %s already exists: %s, %s", tagNameNew, gitPath, dir.getAbsolutePath())); } } } // 打tag: 先判断旧tag、branch或commit是否存在,然后打tag并push ObjectId objectId = null; if (tagRef.contains("/")) { Ref ref = git.getRepository().findRef(tagRef); if (null != ref) objectId = ref.getObjectId(); } else { objectId = git.getRepository().resolve(tagRef + "^{commit}"); } if (objectId == null) { throw new RuntimeException( String.format("tag by %s can't be applied because it not exist: %s, %s", tagRef, gitPath, dir.getAbsolutePath())); } RevWalk walk = new RevWalk(git.getRepository()); RevCommit commit = walk.parseCommit(objectId); Ref tagNew = git.tag().setName(tagNameNew).setObjectId(commit).call(); PushResult pushResult = git.push().add(tagNew).call().iterator().next(); logger.info("================tagByRef time {} ms, {}, {}, {}", (System.currentTimeMillis() - time), gitPath, dir.getAbsolutePath(), pushResult.getRemoteUpdate(tagNew.getName()).getStatus()); } finally { lock.unlock(); } }合并tag到分支
/** * 合并tag到分支 */ public void mergeTagToBranch(String gitPath, String branchName, String tagName) throws Exception { File dir = new File(gitDir, DigestUtils.md5DigestAsHex(gitPath.getBytes(StandardCharsets.UTF_8))); ensureGitWorkDir(gitPath, dir); ReentrantLock lock = getLock(dir.getAbsolutePath()); try { lock.lock(); long time = System.currentTimeMillis(); Git git = gitRepositoryMap.get(dir.getAbsolutePath()); git.fetch().setTagOpt(TagOpt.FETCH_TAGS) .setRefSpecs(new RefSpec("refs/heads/*:refs/remotes/origin/*")) .call(); git.checkout().setName(branchName).setStartPoint("refs/remotes/origin/" + branchName).setForce(true).call(); Ref ref = git.getRepository().findRef(tagName); if (null == ref) throw new RuntimeException( String.format("pull failed, tag '%s' not exists: %s, %s", tagName, gitPath, dir.getAbsolutePath())); MergeResult mergeResult = git.merge().include(ref) .setFastForward(MergeCommand.FastForwardMode.FF_ONLY) .setMessage(String.format("merge tag '%s' into %s", tagName, branchName)).call(); if (!mergeResult.getMergeStatus().isSuccessful()) { // merge失败时reset git.reset().setMode(ResetCommand.ResetType.HARD).setRef("remotes/origin/" + branchName).call(); throw new RuntimeException(String.format("mergeTagToBranch merge failed: %s, %s, %s, %s", tagName, branchName, gitPath, dir.getAbsolutePath())); } PushResult pushResult = git.push().call().iterator().next(); RemoteRefUpdate.Status pushStatus = pushResult.getRemoteUpdates().iterator().next().getStatus(); if (!pushStatus.equals(RemoteRefUpdate.Status.OK) && !pushStatus.equals(RemoteRefUpdate.Status.UP_TO_DATE)) { git.reset().setMode(ResetCommand.ResetType.HARD).setRef("remotes/origin/" + branchName).call(); throw new RuntimeException(String.format("mergeTagToBranch merge success but push failed: %s, %s, %s, %s", tagName, branchName, gitPath, dir.getAbsolutePath())); } logger.info("================mergeTagToBranch time {} ms, {}, {}, {}, {}, {}", (System.currentTimeMillis() - time), pushStatus, tagName, branchName, gitPath, dir.getAbsolutePath()); } finally { lock.unlock(); } }判断master分支上是否有commit没有合并到特定分支
/** * 查询git仓库中,master分支上未合并到本分支的代码;如果有这种代码,返回commit的log信息 */ public String notMergedCommitsInMaster(String gitPath, String branchName) throws Exception { File dir = new File(gitDir, DigestUtils.md5DigestAsHex(gitPath.getBytes(StandardCharsets.UTF_8))); ensureGitWorkDir(gitPath, dir); ReentrantLock lock = getLock(dir.getAbsolutePath()); try { lock.lock(); long time = System.currentTimeMillis(); // fetch最新代码 Git git = gitRepositoryMap.get(dir.getAbsolutePath()); git.fetch().setTagOpt(TagOpt.FETCH_TAGS) .setRefSpecs(new RefSpec("refs/heads/*:refs/remotes/origin/*")) .call(); // 判断是否有master分支 Ref master = git.getRepository().findRef("refs/remotes/origin/master"); if (master == null) { throw new RuntimeException(String.format("getNotMergedCommitsInMaster failed, can't find master branch in %s, %s", gitPath, dir.getAbsolutePath())); } // 获取master最新的3条commit log Iteratormaven依赖commitIterator = git.log().setMaxCount(1).add(master.getObjectId()).call().iterator(); List masterCommitList = new LinkedList (); while (commitIterator.hasNext()) { RevCommit commit = commitIterator.next(); masterCommitList.add(commit); } // 判断master分支最新的commit是否在当前分支中 StringBuilder builder = new StringBuilder(); if (masterCommitList.size() > 0) { List refList = git.branchList().setContains(masterCommitList.get(0).getName()) .setListMode(ListBranchCommand.ListMode.REMOTE).call(); boolean found = false; String refBranchName = "refs/remotes/origin/" + branchName; for (Ref ref : refList) { if (ref.getName().equals(refBranchName)) { found = true; break; } } if (!found) { for (RevCommit revCommit : masterCommitList) { builder.append("commit ").append(revCommit.getName()).append(": ") .append(revCommit.getShortMessage()).append("\n"); } } } logger.info("================getNotMergedCommitsInMaster time {} ms, {}, {}, {}, {}", (System.currentTimeMillis() - time), branchName, gitPath, dir.getAbsolutePath()); return builder.toString(); } finally { lock.unlock(); } }
org.eclipse.jgit org.eclipse.jgit4.5.0.201609210915-r