Just a heads up: On March 24, 2025, starting at 4:30pm CDT / 19:30 UTC, the site will be undergoing scheduled maintenance for a few hours. During this time, the site might be unavailable for a short while. Thanks for your patience.
×What follows is three example commits. In all cases 'git show' explains correctly, yet for merge commits the two API's give inconsistent results.
Consider this merge commit #1, 'git show' *correctly shows the changes to the files* (file A was developer resolved, file B was auto-merged, file C was included w/out file-level merge changes (no new revision)):
$ git show c47af8deac6b87a
commit c47af8deac6b87a35c54f750166a13089c35b770 (HEAD -> master, origin/PR2, PR2)
Merge: 4a7b7ed 705cb5f
Author: Joe
Date: Fri Mar 18 14:27:03 2022 -0400
Merge branch 'master' into PR2
diff --cc A
index bb62e45,c875e2d..695279f
--- a/A
+++ b/A
@@@ -1,3 -1,7 +1,8 @@@
adios
more stuff
+take that!
+ hello
+ what are we doing
+ this is it
+ more of the same
+ gimme a break
diff --cc B
index fecdf68,864a49b..aa01e7f
--- a/B
+++ b/B
@@@ -1,6 -1,5 +1,4 @@@
-guten tag
this is getting ridiculous
- what now?
- ho hum
goodbye
more changes
uh-oh
However the Java API shows three changes (when iterating through the changesets for that commit):
2022-03-18 19:46:16,817 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:46:16,817 WARN [c.o.s.r.ScriptBindingsManager]: Path: A
2022-03-18 19:46:16,817 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:46:16,818 WARN [c.o.s.r.ScriptBindingsManager]: Path: B
2022-03-18 19:46:16,818 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:46:16,818 WARN [c.o.s.r.ScriptBindingsManager]: Path: C
While the REST API shows no changes (.../commits/c47af8d/changes):
{"fromHash":null,"toHash":"c47af8d","properties":{},"values":[],"size":0,"isLastPage":true,"start":0,"limit":25,"nextPageStart":null}
Consider this merge commit #2, 'git show' *correctly shows that there are no changes to any files* (files A and C were included, but no new file revisions via file-level merge):
$ git show 8907e98fb71ffca612
commit 8907e98fb71ffca6120f703d0e43be4787dd173e
Merge: edb85da 2d76267
Author: Joe
Date: Thu Mar 17 12:57:40 2022 -0400
Merge branch 'master' into PR2
However the Java API shows two changes:
2022-03-18 19:53:38,354 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:53:38,373 WARN [c.o.s.r.ScriptBindingsManager]: Path: A
2022-03-18 19:53:38,374 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 19:53:38,374 WARN [c.o.s.r.ScriptBindingsManager]: Path: C
While the REST API shows no changes (.../commits/8907e98/changes):
{"fromHash":null,"toHash":"8907e98","properties":{},"values":[],"size":0,"isLastPage":true,"start":0,"limit":25,"nextPageStart":null}
For a simple (non-merge) commit, results are as expected (file A is modified):
$ git show 4a7b7ed55
commit 4a7b7ed55512a5814292ba6b1689a781c4dc225b
Author: Joe
Date: Fri Mar 18 14:24:44 2022 -0400
PR2
diff --git a/A b/A
index 76b9b5a..bb62e45 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
adios
more stuff
+take that!
2022-03-18 20:11:46,977 WARN [c.o.s.r.ScriptBindingsManager]: Type: MODIFY
2022-03-18 20:11:47,012 WARN [c.o.s.r.ScriptBindingsManager]: Path: A
{"fromHash":null,"toHash":"4a7b7ed55","properties":{},"values":[{"contentId":"bb62e451e87164abcba481ef8f73d719230e0b62","fromContentId":"76b9b5ab7d2242c33ab6ee0d9ede24233add0b66","path":{"components":["A"],"parent":"","name":"A","toString":"A"},"executable":false,"percentUnchanged":-1,"type":"MODIFY","nodeType":"FILE","srcExecutable":false,"links":{...},"properties":{"gitChangeType":"MODIFY"}}],"size":1,"isLastPage":true,"start":0,"limit":25,"nextPageStart":null}
Can execute the 'git show' command from bitbucket...
// check if the commit has new file revisions
// use 'git show' and count the number of new file revisionsdef outputHandler = new SingleLineOutputHandler()
gitCommandBuilderFactory.builder(commit.repository)
.command("show")
.argument("--oneline")
.argument("--name-status")
.argument(commit.id)
.build(outputHandler)
.call()
def new_file_revisions = (outputHandler.getOutput().split("\t").size()-1)
From a top-level perspective, we've implemented a pre-receive hook to prevent pushes to master if all the files don't have review credit in Crucible...
...
def REVIEWS_PATH = 'rest-service-fe/search-v1/queryAsRows/'
commitCallback =
new PreRepositoryHookCommitCallback() {
@Override boolean onCommitAdded(@Nonnull CommitAddedDetails commitDetails) {
def commit = commitDetails.commit
// for commits on master, check to see if the commit includes file revisions
// that are part of a CLOSED review
if (commitDetails.ref.id.startsWith("refs/heads/master")) {
// check if the commit has new file revisions
// use 'git show' and count the number of occurrences of diff output
def outputHandler = new SingleLineOutputHandler()
gitCommandBuilderFactory.builder(commit.repository)
.command("show")
.argument("--oneline")
.argument("--name-status")
.argument(commit.id)
.build(outputHandler)
.call()
def int new_file_revisions = (outputHandler.getOutput().split("\t").size()-1)
if (new_file_revisions > 0) {
// check Crucible
def REVIEWS_QUERY = URLEncoder.encode("select revisions where csid = ${commit.id} and reviewed return count(revisions)", "UTF-8")
def getReviews = authenticatedRequestFactory
.createRequest(GET, "${FISHEYE_URL}${REVIEWS_PATH}${commit.repository.name}?query=${REVIEWS_QUERY}")
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
// {headings=[countReviews], row=[{item=[0]}]}
def result = getReviews.execute(handler)["row"]["item"][0] as ArrayList
def reviewedRevisions = result[0] as int
if (new_file_revisions == reviewedRevisions) {
// allow commits w/ reviewed revisions
return true
} else {
// the number or reviewed revisions does not match the number of new file revisions
resultBuilder.veto("*** Unreviewed commit to master!!! ***",
"*** Commit ID: " + commit.id +
" *** New file revisions: " + new_file_revisions +
" *** Reviewed revisions: " + reviewedRevisions + " ***") return false
}
} else {
// allow commit w/ no new file revisions (likely a clean merge-commit)
return true
}
} else {
// allow non-master commits
return true
}
}
@Override RepositoryHookResult getResult() {
resultBuilder.build()
}
}
commitFilters << RepositoryHookCommitFilter.ADDED_TO_ANY_REF
return RepositoryHookResult.accepted()
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.