I already use the GitHub API to make automated commits.
For this I'm using a Java Library from Kohsuke
It works with this API command:
Create a file
This method creates a new file in a repository
PUT /repos/:owner/:repo/contents/:path
But is it possible to include multiple files in 1 Commit per GitHub API?
The following code snippit will allow you to prepare a commit with multiple files, then associate a new branch to it, using the Java library from Kohsuke
// start with a Repository ref
GHRepository repo = ...
// get a sha to represent the root branch to start your commit from.
// this can come from any number of classes:
// GHBranch, GHCommit, GHTree, etc...
// for this example, we'll start from the master branch
GHBranch masterBranch = repo.getBranch("master");
// get a tree builder object to build up into the commit.
// the base of the tree will be the master branch
GHTreeBuilder treeBuilder = repo.createTree().baseTree(masterBranch.getSHA1());
// add entries to the tree in various ways.
// the nice thing about GHTreeBuilder.textEntry() is that it is an "upsert" (create new or update existing)
treeBuilder = treeBuilder.textEntry(pathToFile, contentOfFile, executable);
// repeat calls of treeBuider.textEntry() or .shaEntry() or .entry() ....
// perform the commit
GHCommit commit = repo.createCommit()
// base the commit on the tree we built
.tree(treeBuilder.create().getSha())
// set the parent of the commit as the master branch
.parent(masterBranch.getSHA1()).message("multi-file commit").create();
// create a new branch from that commit
String newBranchName = "myNewBranchName";
GHRef newRef = repo.createRef("/refs/heads/" + newBranchName, commit.getSHA1();
GHBranch newBranch = repo.getBranch(newBranchName);
Extending on Dan Dowma's answer, it is possible to push these changes to an existing branch
final String branchName = "main";
// start with a Repository ref
GHRepository repo = ...
// get a sha to represent the root branch to start your commit from.
// this can come from any number of classes:
// GHBranch, GHCommit, GHTree, etc...
// for this example, we'll start from the selected branch
GHBranch selectedBranch = repo.getBranch(branchName);
// get a tree builder object to build up into the commit.
// the base of the tree will be the master branch
GHTreeBuilder treeBuilder = repo.createTree().baseTree(selectedBranch.getSHA1());
// add entries to the tree.
treeBuilder = treeBuilder.add(pathToFile, contentOfFile, executable);
// perform the commit
GHCommit commit = repo.createCommit()
// base the commit on the tree we built
.tree(treeBuilder.create().getSha())
// set the parent of the commit as the master branch
.parent(selectedBranch.getSHA1()).message("multi-file commit").create();
// Update an existing branch from that commit
GHRef existingBranchRef = repo.getRef("/refs/heads/" + branchName);
existingBranchRef.updateTo(commit.getSHA1());
Not sure if this is what you want, maybe a little bit more description would help, but take a look at this:
https://developer.github.com/v3/git/
Related
using JGit framework, I would like to collect a list of commits with some specific commit message e.g. commits starting with pattern "[EA-" from a range of date e.g. since 24.01.2018 to current date as in git, git log --since=2018-01-24 --until=2020-03.30 --grep=[EA-. I have tried something as below:
String path = "C:/path_to_repo";
FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();
Repository repo = repositoryBuilder.setGitDir(new File(path, ".git")).findGitDir().build();
Git git = new Git(repo);
ObjectId start;
ObjectId end;
Iterable<RevCommit> call = git.log().addRange(start, end).call();
Is this corrrect to do it this way ? Secondly, how can i pass right params to addRange() method ?
JGit's log command does not support filtering for date ranges and message patterns.
You will need to use a RevWalk to manually traverse the history. Filters can be added to limit the resulting commits. Use CommitTimeRevFilter.between(since, until) to restrict commits to the desired date range.
To further filter on certain messages, or select matching messages while iterating over the commits of the RevWalk.
Here is an example to get you started:
try (RevWalk walk = new RevWalk(repo)) {
walk.markStart(walk.parseCommit(repo.resolve(Constants.HEAD)));
walk.sort(RevSort.REVERSE);
walk.setRevFilter(CommitTimeRevFilter.between(since, until));
for(RevCommit commit : walk) {
if (commit.getFullMessage().contains(...)) {
// include commit in result
}
}
}
Alternatively, you can extend RevFilter to write a custom message filter and use AndRevFilter to combine this filter with the date range filter.
See also this questions about using commit filters in JGit:
How do I use filters in jGit?
How to define a "In between" JGit RevFilter?
TreeWalk allows to get all changes in single commit or in whole repository and checking changed files for each commit (by RevWalk) works really slow, about 2 minutes. Is there any method to walk through changed files and check in which commit they has been changed last time? Or other faster solution?
Here is my code for getting changed files from commit:
TreeWalk treeWalk = prepareTreeWalk(commit, git.getRepository());
List<String> files = new ArrayList<>();
while (treeWalk.next()) {
if (!hasSimilar(treeWalk)) {
files.add(treeWalk.getPathString());
}
}
and for selecting commits (since some special):
return Lists.reverse(StreamSupport.stream(
git.log()
.add(git.getRepository().resolve(branch.getName()))
.call()
.spliterator(), false)
.filter(since(sinceCommit::equals))
.collect(Collectors.toList()));
I know command line below, it will print the output within ms
git format-patch initial-commit --stdout > output.patch
I have a branch structure like this.
How can I get an svn log between two revisions in different branches using SvnKit (for example, a revision from branch 5A.1 and a revision from branch 2B.3), excluding already merged revisions?
I know, how to do it inside single branch using SvnLog operation:
// factory - SvnOperationFactory instance
SvnLog svnLog = factory.createLog();
// target - SvnTarget instance, created from branch URL
// using SvnTarget.fromURL(SVNURL.parseURIEncoded(branchPath))
// my problem is there: how to tell svnLog that I need a diffrence
// between two different branches?
// Adding a second target won't solve my problem, I suppose
svnLog.addTarget(target);
// if you need to go deeper in history, set to "false"
// if you looking for revisions only inside this branch, set to "true"
svnLog.setStopOnCopy(stopOnCopy);
// if you need to include merged revisions too
svnLog.setUseMergeHistory(useMergeHistory);
SVNRevision startRev = SVNRevision.create(startRevNumber);
SVNRevision endRev = SVNRevision.create(startRevNumber);
svnLog.addRange(SvnRevisionRange.create(startRev, endRev));
// the limit of SvnLogEntry items
svnLog.setLimit(limit);
return svnLog.run(null);
There is some kind of misunderstanding that I can't handle with.
SvnKit version is 1.8.7
Most likely you should use SvnLogMergeInfo. Check out this solution:
How to use SVNKit to get the list of all revisions merged from one branch to another?
Assume I create a Branch1 on existing branch Branches\ the following way using SVNKit:
SVNCopyClient copyClient = new SVNCopyClient(authManager, options);
SVNCopySource copySource = new SVNCopySource(SVNRevision.UNDEFINED, SVNRevision.HEAD, sourceUrl);
copySource.setCopyContents(false);
copyClient.doCopy(new SVNCopySource[] { copySource }, toUrl,
false, // isMove
true, // make parents
true, // failWhenDstExists
commitMessage, // commit message
null); // SVNProperties
All works nice, branch created. Then I want to create Branch2 on the same source branch using previous code. Branch2 created, but included existing source branch conent, i.e. Branch1. So the branches structure is:
Branches\
Branches\Branch1
Branches\Branch2\Branch1
Seems SVNKit uses the source branch including its content as a source for Branch2. According to documentation setCopyContents(false) should exclude this content but it does not. What am I doing wrong?
Fugured out. I used copy operation so all worked as disigned. Need to use mkDir operation instead in such cases.
How do I merge in JGit?
Let's say I want to merge master with foo branch, how do I do this?
To merge, you can use the MergeCommand (in package org.eclipse.jgit.api), after a CheckoutCommand. To provide you with an example, because indeed Jgit lacks examples:
Git git = ... // you get it through a CloneCommand, InitCommand
// or through the file system
CheckoutCommand coCmd = git.checkout();
// Commands are part of the api module, which include git-like calls
coCmd.setName("master");
coCmd.setCreateBranch(false); // probably not needed, just to make sure
coCmd.call(); // switch to "master" branch
MergeCommand mgCmd = git.merge();
mgCmd.include("foo"); // "foo" is considered as a Ref to a branch
MergeResult res = mgCmd.call(); // actually do the merge
if (res.getMergeStatus().equals(MergeResult.MergeStatus.CONFLICTING)){
System.out.println(res.getConflicts().toString());
// inform the user he has to handle the conflicts
}
I did not try the code so it might not be perfect, but it's just to provide a start. And I didn't include the imports. Developing with JGit implies a lot of tries based on the javadoc
You will find in the JGit repository various test classes for Merge, including for instance the SimpleMergeTest
Merger ourMerger = MergeStrategy.OURS.newMerger(db);
boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") });
assertTrue(merge);
Passing an ObjectId is convenient for me, e.g.
void merge(String uri,File file){
try(Git git = Git.cloneRepository()
.setURI(uri)
.setBranch("master")
.setDirectory(file)
.call()){
ObjectId objectId = git.getRepository().resolve("origin/develop");
MergeResult mergeResult = git.merge().include(objectId).call();
log.debug(mergeResult.getMergeStatus());
} catch (GitAPIException | IOException e) {
log.error("error",e);
}
}
furthermore, you can find more examples here: https://github.com/centic9/jgit-cookbook
JGit has a full blown Java implementation of the git resolve merge strategy since 2010. If you need examples look at the corresponding JGit test cases and have a look how EGit is using the MergeCommand, look at class org.eclipse.egit.core.op.MergeOperation.