RefChange.getFromHash() returns all zeros on fresh branch

bitbucket-server
plugin-development

#1

I have a plugin that checks for tags on commits based on the commit message. This plugin is a pre-receive hook plugin. This plugin gets all the commits in a ref change using the commit service and the from and to hashes from the refChange. We updated our server at some point from 4.x to 5.9 and now the method refChange.getFromHash() returns a string of all zeroes as the hash when running on the first refChange for a new branch. Our work around is to assume there’s only one commit on a new branch and use git rev-parse <to_hash>~1 to get the previous commit hash. This is usually the case, but there could be cases where that’s not the case. Is this a bug? or is this intentional? I couldn’t find any documentation about this behavior.


#2

Hi Charlie,

Thanks for reaching out. Let me try and unpack your message a little bit so I can give you as much information as possible.

We updated our server at some point from 4.x to 5.9 and now the method refChange.getFromHash() returns a string of all zeroes as the hash when running on the first refChange for a new branch.

This is not a Bitbucket Server thing. This is a git thing. You’ll find it in multiple places in your repository and as the output of multiple git commands. See the following example where I create a branch and add a commit. You can see that the reflog in git/logs uses this “NULL” hash to mark the creation of the branch. You’ll also see in the diff-tree output that it’s used to indicate that a file has been created.

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
$ git checkout -b new-branch
Switched to a new branch 'new-branch'
$ cat .git/logs/refs/heads/new-branch 
0000000000000000000000000000000000000000 2473108ebd78edd2063d4d86a125d2de221e821f username <username@domain.com> 1542321095 +1100	branch: Created from HEAD
$ echo test > new-file && git add new-file && git commit -m "Adding a file to my branch"
[new-branch c7a9897] Adding a file to my branch
 1 file changed, 1 insertion(+)
 create mode 100644 new-file
$ cat .git/logs/refs/heads/new-branch 
0000000000000000000000000000000000000000 2473108ebd78edd2063d4d86a125d2de221e821f username <username@domain.com> 1542321095 +1100	branch: Created from HEAD
2473108ebd78edd2063d4d86a125d2de221e821f c7a9897b317ad814c74b6b3de8c6fe0073231ff3 username <username@domain.com> 1542321141 +1100	commit: Adding a file to my branch
$ git diff-tree HEAD^..HEAD
:000000 100644 0000000000000000000000000000000000000000 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 A	new-file

NOTE: This “NULL” hash can also be used at the end of a history (e.g.: when a branch or file is deleted). As a result it can also be returned by the RefChange.getToHash().

This plugin is a pre-receive hook plugin. This plugin gets all the commits in a ref change using the commit service and the from and to hashes from the refChange.

Starting with Bitbucket Server 5.0.0 we introduced a new hooks API which is the recommended way of achieving this goal. I strongly advice you to migrate your code. The new API allows you to provide a callback for the system to stream the commits to. This means that instead of having all plugins write this code and fork multiple identical git processes on every push, the system does it once in a performant and well tested way. You can find examples on how this API works in our Repository Hooks and Merge Checks Guide. The WorkInProgressHook example shows how to implement and register a callback.

I hope this information was useful.

Regards
Juan Palacios
Atlassian - Bitbucket Server