Reputation: 4516
I have created a repository hook on Bitbucket that automatically creates a pull request from one branch to another (and merge it) when some specific conditions are fulfilled. I would like to detect the case where the result of the merge is that no files will be modified (empty merge).
What I tried so far:
To check if there is commits on source branch that are not on target branch :
CommitsBetweenRequest commitsBetweenRequest = new CommitsBetweenRequest
.Builder(repository)
.include(sourceBranch)
.exclude(targetBranch)
.build();
Boolean anyChanges = commitService
.getCommitsBetween(commitsBetweenRequest, new PageRequestImpl(0, 1))
.stream()
.anyMatch();
This works great for simple cases. However, some "empty merges" are still undetected. This occurs when files modified on source branch have also been modified on target branch the same way, but in different commits.
FB1 -- FB2 (source)
/
/
---- A ---- B ---- C (target)
getCommitsBetween()
will return FB1 and FB2.
However, if files modified in FB1 and FB2 have been modified in C as well (the same way) the result of the merge is no changes at all.
Checking the difference between branches in terms of file changes :
//I have tried to invert sourceBranch and targetBranch, without success
ChangesetsRequest changesRequest = new ChangesetsRequest
.Builder(request.getRepository(), sourceBranch)
.sinceId(targetBranch)
.build();
commitService.getChangesets(changesRequest, new PageRequestImpl(0, 1));
It does not give expected results. It give me the list of files modified in both source and target branch (not the files modified as the result of the merge).
Upvotes: 1
Views: 492
Reputation: 29084
This question can be even more general:
How can you determine what changes will occur as a result of a merge?
Perhaps the quickest and easiest method, is to simply perform the merge and see what changed:
git switch target-branch --detach
git merge source-branch --no-ff
git diff @~1 @
Here we are checking out the target branch using --detach
so you move off of the branch and don't actually modify it, and we merge with --no-ff
to make sure the diff command works even in the case where the source branch could be fast-forwarded. Commits are cheap in Git and get cleaned up with garbage collection, so it shouldn't ever be a problem to make a commit just for testing. Behind the scenes this is probably what Git SCM tools are doing to let you view a Pull/Merge Request before it's completed.
Note, in the case of your specific question, if the above diff
command has no output, then you have confirmed your query regarding "no changes".
But do we really have to actually do the merge; is it possible to determine it?
I don't know for sure, but for now I'm going with you probably have to do the merge. Usually you can get pretty darned close by checking the diff of just the source branch from the target branch, for example:
git diff target-branch...source-branch
# note the 3 dots is shorthand for starting from the merge-base, so this is like:
git diff $(git merge-base source-branch target-branch) source-branch
but, as you point out in the question, that's not always perfect if some of the same changes were made on both the source and target branches. You could inspect the changes the other way too and compare them piece by piece, but it's likely that the logic to determine it is complicated enough that your best bet is to just do the merge and look at it. I wouldn't bother trying to re-create the merge logic if you don't have to. Besides, there are different merge strategies that can be used, and even the default merge strategy is subject to change; in fact it did recently.
Upvotes: 1