Understanding Diff view in Bitbucket Server
Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.
Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
The following information is applicable only to versions of Bitbucket prior to 7.0, as major changes to pull request diffs were included as part of that version.
Please see the full release notes for Bitbucket 7.0 here for further details on these changes.
When creating a Pull Request, the Diff view in Bitbucket Server compares the changes between branches with the ultimate goal of providing an overview of which changes will be merged when a merge is performed.
In other words, the git diff starts at the common ancestor.
This also applies to the following use cases:
Comparing branches
Comparing tags
This is achieved by running the Git merge-base command.
Solution
Let's check the behavior with a step-by-step example.
In this example there are three branches involved:
target_branch
source_branch_A
source_branch_B
Step #1 - Create the branches
These three branches are created in the following order:
target_branch
source_branch_A
source_branch_B
The following commands have been used for the creation of these branches:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Define the source branch for the checkout
git checkout master
# target_branch: a branch with master as source
git checkout -b target_branch
git push origin target_branch
# source_branch_A: a branch with target_branch as source
git checkout -b source_branch_A
git push origin source_branch_A
# source_branch_B: a branch with target_branch as source
git checkout target_branch # To reset the source branch to target_branch
git checkout -b source_branch_B
git push origin source_branch_B
The git log command returns the following
1
2
git log --oneline --abbrev-commit --all --graph --decorate
* bfa489b (HEAD -> source_branch_B, origin/master, origin/HEAD, target_branch, source_branch_A, master) final
The branches will be presented as follows in the Bitbucket Server Commits page:

Step #2 - Change the target_branch
Apply a change to the target branch, commit it and push the change to the remote repository.
1
2
3
4
5
git checkout target_branch
# change the file
git add file1.txt
git commit -m "change on target_branch"
git push origin target_branch
When checking the Diffs tab in a pull request, no changes are shown between the two branches.
The screenshot shows source_branch_B
but source_branch_A
will present the same behaviour.

This is the same, empty, result of the following Git command:
1
git diff $(git merge-base source_branch_B target_branch) source_branch_B
Note that when comparing the two branches with 2 . instead of one, the change applied to the target_branch is shown:
1
2
3
4
5
6
git diff source_branch_B..target_branchdiff --git a/file1.txt b/file1.txt
index 6168ae0..f99b4b2 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,3 +1,6 @@
+A change on the target_branch
Step #3 - Change the source_branch_A
Apply a change to the source_branch_A branch, commit it, and push the change to the remote repository.
1
2
3
4
5
git checkout source_branch_A
# change the file
git add file1.txt
git commit -m "change on source_branch_A"
git push origin source_branch_A
When checking the Diffs tab in a pull request, the changes applied to the source_branch_A
are shown.

This is the same result of the following Git command:
1
2
3
4
5
6
7
8
9
git diff $(git merge-base source_branch_A target_branch) source_branch_A
diff --git a/file1.txt b/file1.txt
index 6168ae0..43bb5b6 100644
--- a/file1.txt
+++ b/file1.txt
@@ -25,3 +25,5 @@ master2
+
+A change on source_branch_A
How does it work real time?
A merge commit hash is generated by Bitbucket by performing a Merge Base when a pull request is created. This hash can be retrieved by checking the content of the $BITBUCKET_HOME/shared/data/repositories/<repository_id>/stash-refs/pull-requests/<pull_request_id>/merge.
When we create a Pull Request for a source branch to the target branch, the diff is as follows:
1
2019-03-18 14:14:03,250 DEBUG [http-nio-25160-exec-2] bitadmin @7FMTJ5x854x1106x0 15ddvyz 0:0:0:0:0:0:0:1 "GET /rest/api/latest/projects/~BITADMIN/repos/mine/pull-requests/1/changes HTTP/1.1" c.a.s.i.s.g.p.DefaultPullRequestRefHelper ~BITADMIN/mine[2]:1@5: Resolving effective diff (7e955114c9c616fc8cb0c9b676fa08052c3b03bb -> d805b33ef5b64a874f082890225d4860e5279a5e)
Here, 7e955114c9c616fc8cb0c9b676fa08052c3b03bb is the new commit ready to be merged and d805b33ef5b64a874f082890225d4860e5279a5e is the latest commit on the target branch.
When the pull request is merged, we can see that content of $BITBUCKET_HOME/shared/data/repositories/<repository_id>/stash-refs/pull-requests/<pull_request_id>/merge was 7d86796957509036b0520a1d1881e4594235ee08
1
2
cat /bitbucket-home/atlassian-bitbucket-5.16.0/shared/data/repositories/2/stash-refs/pull-requests/1/merge
7d86796957509036b0520a1d1881e4594235ee08
So the effective diff that needs to be shown on the UI is calculated as the diff between d805b33ef5b64a874f082890225d4860e5279a5e and 7d86796957509036b0520a1d1881e4594235ee08 since 7d86796957509036b0520a1d1881e4594235ee08 is the automatic merge commit that was done by bitbucket.
This can be checked using git show command:
1
2
3
4
5
6
7
git show 7d86796957509036b0520a1d1881e4594235ee08
commit 7d86796957509036b0520a1d1881e4594235ee08
Merge: d805b33 7e95511
Author: bitadmin <bitadmin@bit.com>
Date: Mon Mar 18 12:33:50 2019 +1100
Automatic merge
Even when the Merge is done on the PR, the value in $BITBUCKET_HOME/shared/data/repositories/<repository_id>/stash-refs/pull-requests/<pull_request_id>/merge still stays the same.
When selecting an individual commit in the diff view, Bitbucket shows the diff between those two commits only.
In both cases, the following two git commands are run:
1
2
/usr/local/bin/git diff-tree -C -r --format=%H <hash_1> <hash_2> --
/usr/local/bin/git diff -C --color=never -U10 --dst-prefix=dst:// --src-prefix=src:// <hash_1> <hash_2> – <files>
When selecting the "All changes in this pull request" option, the <hash_1> used will be the one from the merge commit generated by Bitbucket when the pull request was created.
1
2
/usr/local/bin/git diff-tree -C -r --format=%H <hash_1> <hash_2> --
/usr/local/bin/git diff -C --color=never -U10 --dst-prefix=dst:// --src-prefix=src:// <merge commit hash> <hash_2> – <files>
FAQ
Q: Does this apply only to a branch comparison or a diff in a pull request?
A: No, this also applies to a tag comparison. The following example shows that no Diff are displayed, even if a new change has been pushed to the target branch (as in Step #2 above):

Q: If I change the order of the compare and I see a difference, is it wrong?
A: No, that's expected and it depends on the Git changes applied.

Was this helpful?