git diff and Commit Ranges

There are two additional forms of git diff that bear some explanation, especially in contrast to git log.

The git diff command supports a double-dot syntax to represent the difference between two commits. Thus, the following two commands are equivalent:

git diff master bug/pr-1
git diff master..bug/pr-1

Unfortunately, the double-dot syntax in git diff means something quite different from the same syntax in git log, which you learned about in Chapter 6. It’s worth comparing git diff and git log because doing so highlights the relationships of these two commands to changes made in repositories. Some points to keep in mind for the following example:

  • git diff doesn’t care about the history of the files it compares or anything about branches.

  • git log is extremely conscious of how one file changed to become another—say, when two branches diverged and what happened on each branch.

The log and diff commands perform two fundamentally different operations. Whereas log operates on a set of commits, diff operates on two different endpoints.

Imagine the following sequence of events:

  1. Someone creates a new branch off the master branch to fix bug pr-1, calling the new branch bug/pr-1.

  2. The same developer adds the line Fix Problem report 1 to a file in the bug/pr-1 branch.

  3. Meanwhile, another developer fixes bug pr-3 in the master branch, adding the line Fix Problem report 3 to the same file in the master branch.

In short, one line was added to a file in each branch. If you look at the changes to branches at a high level, you can see when the bug/pr-1 branch was launched and when each change was made:

$ git show-branch master bug/pr-1
* [master] Added a bug fix for pr-3.
 ! [bug/pr-1] Fix Problem Report 1
--
*  [master] Added a bug fix for pr-3.
 + [bug/pr-1] Fix Problem Report 1
*+ [master^] Added Bob's fixes.

If you type git log -p master..bug/pr-1, you will see one commit, because the syntax master..bug/pr-1 represents all those commits in bug/pr-1 that are not also in master. The command traces back to the point where bug/pr-1 diverged from master, but it does not look at anything that happened to master since that point:

$ git log -p master..bug/pr-1
commit 8f4cf5757a3a83b0b3dbecd26244593c5fc820ea
Author: Jon Loeliger <[email protected]>
Date:   Wed May 14 17:53:54 2008 -0500

    Fix Problem Report 1

diff --git a/ready b/ready
index f3b6f0e..abbf9c5 100644
--- a/ready
+++ b/ready
@@ -1,3 +1,4 @@
 stupid
 znill
 frot-less
+Fix Problem report 1

In contrast, git diff master..bug/pr-1 shows the total set of differences between the two trees represented by the heads of the master and bug/pr-1 branches. History doesn’t matter; only the current state of the files does:

$ git diff master..bug/pr-1
diff --git a/NewStuff b/NewStuff
index b4d8596..0f2416e 100644
--- a/NewStuff
+++ b/NewStuff
@@ -1,2 +1 @@
 Something
-Fix Problem report 3
diff --git a/ready b/ready
index f3b6f0e..abbf9c5 100644
--- a/ready
+++ b/ready
@@ -1,3 +1,4 @@
 stupid
 znill
 frot-less
+Fix Problem report 1

To paraphrase the git diff output, you can change the file in the master branch to the version in the bug/pr-1 branch by removing the line Fix Problem report 3 from and then adding the line Fix Problem report 1 to the file.

As you can see, this diff includes commits from both branches. This may not seem crucial with this small example, but consider the example in Figure 8-2 with more expansive lines of development on two branches.

git diff larger history

Figure 8-2. git diff larger history

In this case, git log master..maint represents the five individual commits V, W,..., Z. On the other hand, git diff master..maint represents the differences in the trees at H and Z, an accumulated eleven commits: C, D,..., H and V,..., Z.

Similarly, both git log and git diff accept the form commit1...commit2 to produce a symmetrical difference. As before, however, git log commit1...commit2 and git diff commit1...commit2 yield different results.

As discussed in Commit Ranges, the command git log commit1...commit2 displays the commits reachable from either commit but not both. Thus, git log master...maint in the previous example would yield C, D,..., H and V,..., Z.

Note

The order of these commits is important. git diff A B is not the same as git diff B A.

The symmetric difference in git diff shows the differences between commit2 and a commit that is a common ancestor (or merge base) of commit1 and commit2. Given the same genealogy in Figure 8-2, git diff master...maint combines the changes in the commits V, W, ... , Z.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.112.7