Some of our customers have contacted us with questions about why their pull requests are not working as expected, for example, unexpected diffs being shown (or not) when a PR is created. This document aims at helping to understand how these things work in Git.


Behaviour

  1. Start with just the master branch.

  2. Create a staging branch from master

  3. Create a uat branch from master

  4. Create a feature branch from master and add a commit to it. (e.g. I’m changing the version from v51 to v52)

  5. Now make the same change directly on the staging branch as well. This should be the resulting state.

  6. What do you expect to see as file diffs when you open a PR from feature to uat? This, right? This is indeed the case.

  7. Now what do you expect to see as file diffs when you open a PR from feature to staging?

    Recalling that staging and feature branches are currently identical (as the same changes have been committed). Users may imagine that there are no differences to show, but that is NOT what happens.

    GitHub will show the commit. Why?

Explanation

The GitHub documentation states that

“Pull request pages show the diff between the tip of the head ref and the common ancestor of the head and base ref at the time when the pull request was created.”

  • The “tip of the head ref” is the current state in the feature branch with the commit added.

  • The “common ancestor of the head and base ref” is the “common ancestor of the feature branch and the staging branch”. Which in turn is what the master branch is currently showing.

Let’s think of this as a diagram.

It is helpful to think of branches as not existing at all, and only the commits are real (c1, c2 and c3).

feature branch is a pointer to c2, staging is a pointer to c3, uat and master are both pointing to c1 and so on. In this model, only the commits are “comparable” or “diffable”.

In step 6, comparing feature to uat, is comparing c2 to c1 (as c1 is the common ancestor).

In step 7, comparing feature to staging, is therefore also comparing c2 to c1 (as c1 is the common ancestor), and NOT comparing c2 to c3.

Comparing c2 to c3 is not the way git was designed, however much we, as users, may want that to be the case.

See this thread for more people talking about this.

Did this answer your question?