Navigating & Comparing Commits in Git

19 min read·Jan 1, 2025

In Git, navigating and comparing commits allows developers to understand, debug, and collaborate more effectively by tracking the changes made to a codebase over time.

It helps them identify when and why specific modifications were made, and pinpoint the eventual introduction of bugs.

It also allows them to review each other's changes, which is essential for providing feedback, and ensuring code quality and standards.

Reviewing the commit history

To output the complete list of commits present in the history in chronological order, from the newest to the oldest, you can use the git log command:

$ git log

This will output the commits in the following format:

commit <hash>
Author: <author>
Date:   <date>

    <message>

Where:

  • <hash> is a unique hexadecimal string used to reference a specific commit in the history.
  • <author> is the name and email address of the user who created the commit.
  • <date> is the date and time the commit was added to the history.
  • <message> is a short message describing the commit.

Example

In this example, the git log command outputs all the commits of the repository:

$ git log
commit 52d8599a61f8f23867ddd249a171c10727e34f50 (HEAD -> master)
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:50:23 2024 +0100

    feat: add login route

commit 5a37268ac01f5b2f1d0659642ebbdeea1d446485
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:42:51 2024 +0100

    feat: add health check endpoint

commit ca4a22ab8935f8da66aedcb7d9ecf24cbf4d66a4
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:42:15 2024 +0100

    refactor: pass server port as config object

commit f828067e84c02058731f3ceb99a8f32cdeea2337
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:41:06 2024 +0100

    feat: create http server module

commit e7e9a6db131fba4622aa5f44d050b974e30d3576
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:39:32 2024 +0100

    feat: add app manifest and gitignore

Displaying the change summary

To output all commits and include the list of files that were changed in each commit, you can use the git log command with the --stat option as follows:

$ git log --stat

This will output the commits in the following format:

commit <hash>
Author: <author>
Date:   <date>

    <message>

 <filepath- | <N> +-
 <N> files changed, <N> insertions(+), <N> deletions(-)

Where:

  • <filepath> is the relative path to the file changed in the commit.
  • <N> +- is the total number of lines added (+) and removed (-) in the specified file.
  • <N> files changed is the total number of files changed.
  • <N> insertions(+) is the total number of new lines inserted across all files.
  • <N> deletions(-) is the total number of lines removed across all files.

Example

In this example, the git log command outputs all the commits of the repository, including their change summary:

$ git log --stat
commit 52d8599a61f8f23867ddd249a171c10727e34f50 (HEAD -> master)
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:50:23 2024 +0100

    feat: add login route

 server.js | 13 +++++++++++++
 1 file changed, 13 insertions(+)

commit 5a37268ac01f5b2f1d0659642ebbdeea1d446485
Author: John Doe <johndoe@mail.com>
Date:   Sun Dec 1 16:42:51 2024 +0100

    feat: add health check endpoint

 server.js | 2 ++
 1 file changed, 2 insertions(+)

commit ca4a22ab8935f8da66aedcb7d9ecf24cbf4d66a4
Author: John Doe <johndoe@mail.com>
Date:   Fri Nov 22 16:42:15 2024 +0100

    refactor: pass server port as config object

 index.js  | 2 +-
 server.js | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

commit f828067e84c02058731f3ceb99a8f32cdeea2337
Author: John Doe <johndoe@mail.com>
Date:   Mon Nov 18 16:41:06 2024 +0100

    feat: create http server module

 index.js  | 3 +++
 server.js | 9 +++++++++
 2 files changed, 12 insertions(+)

commit e7e9a6db131fba4622aa5f44d050b974e30d3576
Author: John Doe <johndoe@mail.com>
Date:   Wed Nov 13 16:39:32 2024 +0100

    feat: add app manifest and gitignore

 .gitignore        |   1 +
 package-lock.json | 711 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 package.json      |  14 +++
 3 files changed, 726 insertions(+)

Displaying commits on single lines

To output all commits on single lines in the short format, you can use the git log command with the --oneline option as follows:

$ git log --oneline

This will output the commits in the following format:

<short_hash> <message>

Where:

  • <short_hash> is the shortened version of the commit hash.
  • <message> is the commit message.

Example

In this example, the git log command outputs all the commits in the short format:

$ git log --oneline
52d8599 (HEAD -> master) feat: add login route
5a37268 feat: add health check endpoint
ca4a22a refactor: pass server port as config object
f828067 feat: create http server module
e7e9a6d feat: add app manifest and gitignore

Filtering commits by date

To filter the list of commits by date range, you can use the git log command with the --since and --until flags as follows:

$ git log [--since=<date>] [--until=<date>]

Where date is a date in the YYYY-MM-DD format.

Example

In this example, the git log command outputs all the commits in the short format, from November 30th, 2024 until now:

$ git log --oneline --since=2024-11-30
52d8599 (HEAD -> master) feat: add login route
5a37268 feat: add health check endpoint

Filtering commits by patterns

To filter the commits by log message, you can use the git log command with the --grep flag as follows:

$ git log --grep=<pattern>

Where pattern is a regular expression.

Example

In this example, the git log command outputs all the commits in the short format, whose message contain the string "feat":

$ git log --oneline --grep="feat"
52d8599 (HEAD -> master) feat: add login route
5a37268 feat: add health check endpoint
f828067 feat: create http server module
e7e9a6d feat: add app manifest and gitignore

Reviewing a single commit

To review the changes introduced by a single commit, you can use the git show command as follows:

$ git show <commit>

Where commit is the hash of the commit.

This will output the commits in the following format:

commit <hash>
Author: <author>
Date:   <date>

    <message>

diff --git a/<filepath> b/<filepath>
index e70febc..f728ce1 100644
--- a/<filepath>
+++ b/<filepath>
@@ -<N,M> +<N,M> @@ <first_line>
   <line>
-  <line>
+  <line>
   <line>

Where:

  • --- a/<filepath> indicates the old path to the file.
  • +++ b/<filepath> indicates the new path to the file.
  • -<N,M> refers to the starting line (N) in the original file and the number of lines (M) that are shown for context.
  • +<N,M> refers to the starting line (N) in the original file and the new number of lines (M).
  • <first_line> refers to the first line of the file.
  • ⠀⠀⠀<line> indicates an unchanged line from the original file, shown to provide context.
  • -⠀⠀<line> indicates a line that was removed from the file.
  • +⠀⠀<line> indicates a line that was inserted into the file.

Example

In this example, the git show command outputs the detailed code changes introduced by the commit ac19863:

$ git show ca4a22ab8935f8da66aedcb7d9ecf24cbf4d66a4
commit ca4a22ab8935f8da66aedcb7d9ecf24cbf4d66a4
Author: John Doe <johndoe@mail.com>
Date:   Fri Nov 22 16:42:15 2024 +0100

    refactor: pass server port as config object

diff --git a/index.js b/index.js
index 770d5d6..e96dbbc 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1,3 @@
 const server = require('./server.js');

-server();
+server({ port: 8080 });
diff --git a/server.js b/server.js
index b058cad..e96da2b 100644
--- a/server.js
+++ b/server.js
@@ -1,9 +1,9 @@
 const express = require('express');

-module.exports = () => {
+module.exports = ({ port }) => {
   const app = express();

-  app.listen(3000);
+  app.listen(port);

   return app;
 };

Comparing commits

Comparing commits allows you to track and compare the differences between the various states of your repository or changes that haven't yet been committed, allowing you to understand how they differ from each other at different points in time.

Comparing unstaged changes

To check the changes made to the files in the working tree that haven't been staged yet, you can use the git diff command:

$ git diff [<commit>]

Where commit is an optional commit hash to compare the changes to. Defaults to the latest commit.

Example

This command compares the changes in the server.js file between the working tree and the latest commit:

$ git diff
diff --git a/server.js b/server.js
index bcfc623..7bff777 100644
--- a/server.js
+++ b/server.js
@@ -3,13 +3,16 @@ const express = require('express');
 module.exports = ({ port }) => {
   const app = express();
   const router = express.Router();
+  const users = {
+    'johndoe@mail.com': 'helloworld'
+  };

   app.get('/', (req, res) => res.sendStatus(200));

   router.post('/login', express.json(), (req, res) => {
     const { email, password } = req.body;

-    if (email === 'johndoe@mail.com' && password === 'helloworld') {
+    if (users[email] === password) {
       res.json({ access_token: 's8df123sa1DSAa' });
     } else {
       res.status(401).json({ error_message: 'invalid_credentials' });

Comparing changes between two commits

To compare the textual changes between two different commits, you can use the git diff command as follows:

$ git diff <commitA> <commitB>

Summary

Here's a summary of what you've learned in this lesson:

  • The git log command is used to output the complete list of commits in the history.
  • The git log --stat command is used to include the list files changed.
  • The git log --oneline command is used to only display the commit hash and message.
  • The git log [--since=<date>] [--until=<date>] command is used to filter commits based on date ranges.
  • The git log --grep=<pattern> command is used to filter commits by commit message.
  • The git show <commit> command is used to review the changes introduced by a specific commit.
  • The git diff command is used to check the changes made to the files of the working directory that haven't been staged yet.
  • The git diff <commit> command is used to compare the changes between the working directory and a specific commit.
  • The git diff <commitA> <commitB> command is used to compare the changes between two specific commits.

Enjoying the courses?

I've made these courses completely free so anyone can learn from them. If they've helped you and you'd like to actively support the work behind BackendBrewery, you can leave a tip:

Support BackendBrewery
Navigating & Comparing Commits in Git | Backend Brewery