Understanding Diff view in Bitbucket Server

Still need help?

The Atlassian Community is here for you.

Ask the community

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.

Purpose

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:

# 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

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.

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:

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:

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.

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:

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:

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


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:


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:

/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.

/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.


Last modified on Oct 2, 2020

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.