Git: How to compare changes across commits

Updated: January 27, 2024 By: Guest Contributor Post a comment

Introduction

Git is an essential tool for version control, allowing developers to keep track of changes and collaborate on software projects. One of its core features is the ability to compare changes across different commits. This feature provides invaluable insight into the evolution of your codebase. In this tutorial, we will explore various ways to compare changes across commits in Git, using code examples ranging from basic to advanced.

Prerequisites

  • A basic understanding of Git and its command-line interface.
  • Git installed on your machine.
  • Access to a repository with a commit history.

Comparing Changes Between Two Commits

Let’s start with the basics of comparing two distinct commits. Use the following command:

git diff <commit-hash-1> <commit-hash-2>

The above command will produce a diff output showing the differences between the two commits. Here is an example:

- This line was removed
+ This line was added

The minus (-) sign indicates a line that was present in <commit-hash-1> but not in <commit-hash-2>, while the plus (+) sign indicates the opposite.

Viewing Changes Made Since a Particular Commit

If you’re interested in viewing the changes made since a specific commit, use:

git diff <commit-hash> HEAD

This will show you what has changed in your working directory since the specified commit.

Comparing Changes in a Specific File

To focus on changes in a particular file across commits, the syntax becomes:

git diff <commit-hash-1> <commit-hash-2> -- <file-path>

For example:

git diff abc123 def456 -- main.py

This command will show the differences in the file main.py between the two specified commits.

Diffing Unstaged Changes Against the Last Commit

Without any arguments, git diff will show changes that are unstaged (i.e., not yet added for the next commit):

git diff

This is very useful for a quick look at what you have changed but not yet prepared to commit.

Using Git Log with Diff

To see the log of commits with the differences introduced by each commit, you can use:

git log -p

This command outputs the commit log with patch text. It’s helpful when you need a historical perspective of changes.

Comparing Branches

When working with branches, you might want to compare changes between two branches:

git diff <branch-name-1>...<branch-name-2>

Using three dots (…) tells Git to show only the changes that occurred on the two branches since they diverged from a common ancestor.

Advanced: Comparing Staged vs. Unstaged Changes

You can compare staged changes against the HEAD (the last commit) with:

git diff --staged

If you want to compare unstaged against staged changes, omit the `–staged` flag.

Using Git Diff with Commit Ranges

Advanced usage involves commit ranges. For example, the following command compares changes between a range of commits:

git diff <commit-hash-1>..<commit-hash-2>

Git interprets this as a request to compare the state of the code at <commit-hash-1> with the state at <commit-hash-2>.

Diff Output Options

Git provides options to customize the diff output for better readability or data that is more manageable, such as:

git diff --shortstat <commit-hash-1> <commit-hash-2>

It shows a brief summary of changes (file count, insertion count, and deletion count).

A Word on GUI Tools

CLI commands are not the only way to compare changes across commits; various GUI tools offer visual diff capabilities. Tools such as SourceTree, GitKraken, or the gitk command:

gitk <commit-hash-1>..<commit-hash-2>

can make comparing changes even more insightful, especially for those who prefer a graphical representation of diffs.

Conclusion

In summary, Git’s diff functionality is integral for developers to understand the history and progression of their codebase. From comparing two commits to inspecting ranges or individual files, Git offers the versatility needed to deal with complex code reviews. As you grow more comfortable with these commands, you’ll find that managing and understanding your code changes becomes a more intuitive part of your development process.