初始化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
Iterator
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(); } }
maven依赖
org.eclipse.jgit org.eclipse.jgit4.5.0.201609210915-r
