Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why GitHub shows changes when compare two identical branches?

Tags:

git

github

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?

like image 931
dhythhsba Avatar asked Aug 09 '18 22:08

dhythhsba


People also ask

How do I compare the differences between two branches in GitHub?

Comparing branches is as easy as selecting the “compare to branch” option while perusing the feature branch you'd like to compare to another. The compare to branch option in GitHub Desktop is located under the “Branch” in the main menu at the top of the interface.

How does GitHub compare work?

The two-dot comparison shows the difference between the latest state of the base branch (for example, main ) and the most recent version of the topic branch. To see two committish references in a two-dot diff comparison on GitHub, you can edit the URL of your repository's "Comparing changes" page.


2 Answers

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.

like image 69
torek Avatar answered Oct 25 '22 19:10

torek


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.

like image 25
Schwern Avatar answered Oct 25 '22 17:10

Schwern