Why GitHub shows changes when compare two identical branches?
Asked Answered
C

3

12

I have created test repository: https://github.com/Labutin/CompareBranches Let's try to clone and compare two branches branch_01 and branch_02

$ git clone https://github.com/Labutin/CompareBranches.git
Cloning into 'CompareBranches'...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 7 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (7/7), done.

$ git diff remotes/origin/branch_01..remotes/origin/branch_02 --exit-code
$ echo $?
0

So, we have two branches which are identical.

But if I try to use Web UI to compare two branches https://github.com/Labutin/CompareBranches/compare/branch_01...branch_02 it shows 1 file changed. Why? Whats wrong with Web UI? Maybe I have to modify URL?

Connie answered 9/8, 2018 at 22:9 Comment(1)
If you use VS code, the GitLens extension can compare files between branches without caring of the commits ahead/behind or history of them: #42113026Enfeoff
U
10

This question is really about GitHub—but we can use it to construct a question about Git.

After I clone your repository:

$ git clone https://github.com/Labutin/CompareBranches.git
Cloning into 'CompareBranches'...
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 7 (delta 0), reused 0 (delta 0), pack-reused 0

I can view all of the commits in it:

$ cd CompareBranches
$ git log --all --decorate --oneline --graph
* 5707453 (origin/branch_02) Commit to branch_02
| * c0e3722 (origin/branch_01) commit to branch_01
|/  
* 0e9a4e3 (HEAD -> master, origin/master, origin/HEAD) Initial commit

So there are three commits, whose actual (but abbreviated) names are 0e9a4e3, c0e3722, and 5707453. The remote-tracking name origin/master refers to the first commit, and the other two remote-tracking names origin/branch_01 and origin/branch_02 refer to the other two commits.

If we ask Git to compare commits c0e3722 and 5707453, we see no difference:

$ git diff c0e3722 5707453

But if we ask Git to compare, say, commit 0e9a4e3 to commit 5707453, we see that these two commits are different:

$ git diff 0e9a4e3 5707453
diff --git a/README.md b/README.md
index f00f3be..b183451 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
-# CompareBranches
\ No newline at end of file
+# CompareBranches
+commit1

Since commits c0e3722 and 5707453 have the same content, comparing 0e9a4e3 to either one will show this same change.

The git diff command has special syntax

When we want to compare two commits, we can run:

git diff <thing-1> <thing-2>

and Git will compare thing-1 to thing-2. The part inside the angle brackets can be anything that identifies a commit: a raw hash ID like 0e9a4e3, or a branch name, or a remote-tracking name, for instance.

If we run:

git diff <thing-1>..<thing-2>

Git does exactly the same thing: it compares the two things.

But, if we use three dots instead of two:

git diff <thing-1>...<thing-2>

Git does something special. Instead of comparing the two commits we named, Git finds a third commit. In particular, Git looks for a merge base commit, from which both the named commits descend. We see this in the git log --graph output above: the two tip commits both descend from commit 0e9a4e3. So that's the merge base, and therefore, with three dots instead of two, that's the commit Git uses on the left side of the comparison.

The right side is just <thing-2> itself.

As it turns out, GitHub is doing the same thing here, which is why GitHub's link has three dots in it: GitHub is mimicking the syntax of git diff, on purpose.

Usia answered 9/8, 2018 at 22:23 Comment(0)
C
2

Note the triple dot in the Github URL. Github is doing git diff remotes/origin/branch_01...remotes/origin/branch_02. r1..r2 is subtly different from r1...r2.

r1..r2 asks for all commits reachable from r2 except those reachable by r1.

r1...r2 asks for "all the commits that are reachable by either of two references but not by both of them."

Let's look at these in your repo.

A - B [branch_02]
 \
  C [branch_01]

git log branch_01..branch_02 gives us B. branch_02 can reach A and B, but branch_01 can also reach A, so this gives us B.

git log branch_01..branch_02 gives us B and C. branch_01 can reach A and C. branch_02 can reach A and B. Both branches can reach A, so it is excluded. We're left with B and C.

For more, see Revision Selection, Double Dot and Triple Dot in Pro Git.

Coffeecolored answered 9/8, 2018 at 22:17 Comment(3)
GitHub actually doesn't "do" the two dot comparison at all, it seems.Usia
Looks like two dot doesn't work. Try github.com/Labutin/CompareBranches/compare/branch_01..branch_03 Branches are not equal.Connie
@Connie I think you're right. It looks like Github is interpreting branch_01..branch_03 as a reference and defaulting the base to master. Rather than throwing an error because the reference doesn't exist, it's reporting no difference. For example, github.com/Labutin/CompareBranches/compare/aldkflakjfkjdCoffeecolored
B
0

The official GitHub documentation says:

There are two comparison methods for the git diff command:

  • two-dot (git diff main..topic)
  • and three-dot (git diff main...topic).

The two-dot comparison shows the difference between the latest [i.e. most recent] state of the base branch [main in the example above] and the most recent version of the topic branch.

The three-dot comparison shows the difference between the latest common commit of both branches (merge base) and the most recent version of the topic branch.

Pull requests on GitHub show a three-dot diff.

The main reason for this looks like

When you use a two-dot comparison, the diff changes when the base branch is updated, even if you haven't made any changes to the topic branch.

Another argument for it is

Additionally, a two-dot comparison focuses on the base branch. This means that anything you add is displayed as missing from the base branch, as if it was a deletion, and vice versa. As a result, the changes the topic branch introduces become ambiguous.

To see the difference between tips of your branches replace three dots in the comparison URL by two dots (..).

If you are interested in learning more about double dot and triple dot, I would recommend checking out the answers on this question.

Bluefish answered 29/7 at 15:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.