Chapter 4: Understanding Commits and History

Chapter Objectives

By the end of this chapter, you will be able to:

  • Define a Git commit as a snapshot of your project at a specific point in time.
  • Describe the key components of a commit object, including its SHA-1 hash, parent(s), tree object, author/committer information, and message.
  • Understand how commits link together to form the project history.
  • Use git log with various options to view and navigate the commit history effectively.
  • Inspect the details and changes introduced by a specific commit using git show.
  • Compare the differences between any two commits in the project’s history using git diff.

Introduction

In Chapter 3, you learned how to initialize a repository, stage changes, and make your first commits. You saw that a commit records a snapshot of your project. But what exactly is in that snapshot? How does Git store these commits, and how do they relate to one another to form a coherent history of your project?

This chapter dives deeper into the nature of Git commits. We’ll dissect the anatomy of a commit object to understand its core components. You’ll learn that Git’s history is not just a linear sequence but can be a more complex structure. Most importantly, we’ll explore powerful commands like git log, git show, and git diff that allow you to navigate, inspect, and understand your project’s evolution over time. Mastering these tools is essential for reviewing past work, understanding changes, and collaborating effectively.

Theory

What is a Git Commit? Snapshots, Not Differences

One of the most fundamental concepts to grasp about Git is how it stores your data. Many older Version Control Systems (like Subversion or CVS) think of information as a set of files and the changes (deltas or diffs) made to each file over time.

Git, however, thinks of its data more like a stream of snapshots. When you make a commit, Git essentially takes a picture of what all your tracked files look like at that moment and stores a reference to that snapshot. To be efficient, if files have not changed from one commit to the next, Git doesn’t store the file again; it just links to the previous, identical file it has already stored.

This snapshot-based approach makes many Git operations, like branching and merging (which we’ll cover later), much simpler and faster than in systems that rely on deltas.

Anatomy of a Commit Object

Every time you run git commit, Git creates a commit object. This object contains several key pieces of information and is uniquely identified by a SHA-1 hash. A SHA-1 hash is a 40-character hexadecimal string (e.g., 2f49c1f2c10362873dd40877894908104f004781). This hash is generated based on the content of the commit and its metadata, meaning that if any part of the commit changes, the SHA-1 hash will also change. This makes Git’s history very secure and verifiable.

A commit object contains the following:

  1. SHA-1 Hash: The unique identifier for the commit.
  2. A pointer to a Tree Object: This tree object, in turn, represents a snapshot of the project’s directory structure and file contents at the time of the commit. It contains pointers to other tree objects (for subdirectories) and “blob” objects (which store the actual file content).
  3. Pointer(s) to Parent Commit(s):
    • Most commits have exactly one parent commit – the commit that came immediately before it in the history. This is what links commits together in a chronological chain.
    • The very first commit in a repository (the “root commit”) has no parents.
    • A merge commit (created when you merge branches) can have two or more parents.
  4. Author Information: The name and email address of the person who originally wrote the changes, along with a timestamp of when they authored the work. This is taken from your user.name and user.email configuration at the time you wrote the changes.
  5. Committer Information: The name and email address of the person who actually made the commit, along with a timestamp of when the commit was made. For local commits, the author and committer are usually the same. However, if someone sends you a patch and you apply it, you might be the committer, while the original writer is the author.
  6. Commit Message: The descriptive message you wrote when you made the commit, explaining the changes.
%%{
  init: {
    "theme": "base",
    "themeVariables": {
      "primaryColor": "#EDE9FE",
      "primaryTextColor": "#5B21B6",
      "primaryBorderColor": "#5B21B6",
      "lineColor": "#A78BFA",
      "textColor": "#1F2937",
      "fontSize": "13px",
      "fontFamily": "Open Sans",

      "componentFill": "#DBEAFE",
      "componentStroke": "#2563EB",
      "componentColor": "#1E40AF",

      "dataFill": "#FEF3C7",
      "dataStroke": "#D97706",
      "dataColor": "#92400E",
      
      "pointerFill": "#D1FAE5",
      "pointerStroke": "#059669",
      "pointerColor": "#065F46"
    },
    "flowchart": {
      "htmlLabels": true,
      "nodeSpacing": 20,
      "rankSpacing": 30
    }
  }
}%%
flowchart TD
    subgraph CommitObject["Commit Object <code style='font-size:0.9em; color:#5B21B6;'>SHA-1: 2f49c1...4781</code>"]
        direction TB
        
        TreePtr["<div style='text-align:left; padding:5px;'><b>Tree SHA-1:</b><br><code style='color:#065F46;'>e.g., 1a2b3c...</code><br><span style='font-size:0.9em;'><i>(Snapshot of project files/dirs)</i></span></div>"]
        
        ParentPtrs["<div style='text-align:left; padding:5px;'><b>Parent(s) SHA-1:</b><br><code style='color:#065F46;'>e.g., 9d8c7b... (single parent)</code><br><code style='color:#065F46;'>e.g., f0e1d2..., a3b4c5... (merge)</code><br><span style='font-size:0.9em;'><i>(Links to previous commit(s))</i></span></div>"]
        
        AuthorInfo["<div style='text-align:left; padding:5px;'><b>Author:</b><br>Name: Alice Wonderland<br>Email: alice@example.com<br>Date: 2025-05-15 10:00:00 +0000<br><span style='font-size:0.9em;'><i>(Original writer)</i></span></div>"]
        
        CommitterInfo["<div style='text-align:left; padding:5px;'><b>Committer:</b><br>Name: Alice Wonderland<br>Email: alice@example.com<br>Date: 2025-05-15 10:05:00 +0000<br><span style='font-size:0.9em;'><i>(Who made the commit)</i></span></div>"]
        
        CommitMsg["<div style='text-align:left; padding:5px;'><b>Commit Message:</b><br>\<i>Fix typo in README.md\</i><br><br>\<i>Further explanation about the fix...\</i><br><span style='font-size:0.9em;'><i>(Why the change was made)</i></span></div>"]
    end

    style CommitObject fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6
    style TreePtr fill:#D1FAE5,stroke:#059669,stroke-width:1.5px,color:#065F46
    style ParentPtrs fill:#D1FAE5,stroke:#059669,stroke-width:1.5px,color:#065F46
    style AuthorInfo fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#1E40AF
    style CommitterInfo fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#1E40AF
    style CommitMsg fill:#FEF3C7,stroke:#D97706,stroke-width:1.5px,color:#92400E

    classDef default fill:transparent,stroke:#1F2937,stroke-width:1px,color:#1F2937,font-family:'Open Sans'

How Commits Form History

The parent pointers are what create the history of your project. Each commit points back to its predecessor(s), forming a Directed Acyclic Graph (DAG). For simple, linear histories, this looks like a straight line of commits. When branching and merging occur (covered in later chapters), this graph becomes more complex but always flows in one direction (from newer commits to older ones) and never contains cycles.

%%{
  init: {
    "theme": "base",
    "themeVariables": {
      "primaryColor": "#EDE9FE",      /* Commit nodes - Light Purple */
      "primaryTextColor": "#5B21B6",
      "primaryBorderColor": "#5B21B6",
      "lineColor": "#5B21B6",         /* Arrow color - Purple */
      "textColor": "#1F2937",
      "fontSize": "14px",
      "fontFamily": "Open Sans"
    },
    "flowchart": {
      "htmlLabels": true,
      "nodeSpacing": 40,
      "rankSpacing": 70,
      "curve": "basis"
    }
  }
}%%
flowchart LR
    subgraph CommitHistory ["Project History (DAG)"]
        direction LR
        C1["<div style='padding:8px; text-align:center;'><b>Commit C1</b><br>(Root Commit)<br><code style='font-size:0.85em;'>SHA: a1b2c3d</code><br><i>(No Parent)</i></div>"]
        C2["<div style='padding:8px; text-align:center;'><b>Commit C2</b><br><code style='font-size:0.85em;'>SHA: e4f5g6h</code><br>Parent: C1</div>"]
        C3["<div style='padding:8px; text-align:center;'><b>Commit C3</b><br><code style='font-size:0.85em;'>SHA: i7j8k9l</code><br>Parent: C2</div>"]
        
        T1["<div style='padding:5px; font-size:0.9em; text-align:center;'>🌳 Tree T1<br>(Snapshot for C1)</div>"]
        T2["<div style='padding:5px; font-size:0.9em; text-align:center;'>🌳 Tree T2<br>(Snapshot for C2)</div>"]
        T3["<div style='padding:5px; font-size:0.9em; text-align:center;'>🌳 Tree T3<br>(Snapshot for C3)</div>"]
    end

    subgraph Pointers
        direction TB
        HEAD_ptr["<div style='padding:5px; text-align:center;'><b>HEAD</b><br>(Current Commit)</div>"]
        Branch_ptr["<div style='padding:5px; text-align:center;'><b>main</b><br>(Branch Tip)</div>"]
    end

    C3 -- "<i>Parent Pointer</i>" --> C2
    C2 -- "<i>Parent Pointer</i>" --> C1

    C1 -.-> T1
    C2 -.-> T2
    C3 -.-> T3
    
    HEAD_ptr -.-> C3
    Branch_ptr -.-> C3

    style C1 fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6
    style C2 fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6
    style C3 fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6
    
    style T1 fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#1E40AF
    style T2 fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#1E40AF
    style T3 fill:#DBEAFE,stroke:#2563EB,stroke-width:1.5px,color:#1E40AF

    style HEAD_ptr fill:#D1FAE5,stroke:#059669,stroke-width:1.5px,color:#065F46
    style Branch_ptr fill:#D1FAE5,stroke:#059669,stroke-width:1.5px,color:#065F46
    
    linkStyle 0,1 stroke:#5B21B6,stroke-width:2px
    linkStyle 2,3,4 stroke:#A78BFA,stroke-width:1.5px,stroke-dasharray:5 2
    linkStyle 5,6 stroke:#059669,stroke-width:1.5px,stroke-dasharray:3 3

    classDef default fill:transparent,stroke:#1F2937,stroke-width:1px,color:#1F2937,font-family:'Open Sans'

HEAD: The Current Commit Pointer

Git uses a special pointer called HEAD (always in uppercase) to refer to the commit representing the current state of your working directory. Most of the time, HEAD points to the latest commit on your current branch. When you make a new commit, HEAD (along with the current branch pointer) moves forward to the new commit. Understanding HEAD is crucial when we discuss detaching HEAD or moving around in history.

Practical Examples

Let’s explore the commit history of the my-git-cookbook repository we started in Chapter 3. If you don’t have it, quickly recreate it with a few files and commits:

Setup (if needed):

Bash
# If you don't have my-git-cookbook, create and set it up:
mkdir my-git-cookbook-ch4
cd my-git-cookbook-ch4
git init

# First commit
echo "# My Git Cookbook" > README.md
echo "A collection of delicious Git recipes." >> README.md
git add README.md
git commit -m "Initial commit: Add README file"

# Second commit
echo "Chapter 3: Our First Repository" >> README.md
git add README.md
git commit -m "Add chapter 3 info to README"

# Third commit
echo "Flour" > ingredients.txt
echo "Sugar" >> ingredients.txt
git add ingredients.txt
echo "More details coming soon." >> README.md
git add README.md
git commit -m "Add ingredients and update README"

# Fourth commit (for more history)
echo "Eggs" >> ingredients.txt
git add ingredients.txt
git commit -m "Add eggs to ingredients"

Make sure your user.name and user.email are configured as per Chapter 2.

1. Viewing Commit History: git log

The git log command is your primary tool for viewing the commit history.

git log Option Description Example Usage
(no option) Default view: Full SHA-1, author, date, message for each commit, newest first. Uses a pager for long output. git log
–oneline Concise view: Short SHA-1 and commit message title. git log –oneline
–decorate Shows branch names, tags, and other refs pointing to commits. git log –decorate
–graph Draws a text-based graph of the commit history. Often used with –oneline and –decorate. git log –graph –oneline –decorate
-p or –patch Shows the patch (diff) introduced by each commit. git log -p or git log -p -2 (for last 2)
–stat Displays abbreviated statistics of changes for each commit (files changed, lines added/removed). git log –stat
-<n> Limits the number of commits shown to <n>. git log -3 (shows the last 3 commits)
–since / –after Shows commits more recent than a specific date or time. git log –since=”2 weeks ago”
git log –after=”2025-05-01″
–until / –before Shows commits older than a specific date or time. git log –until=”yesterday”
–author=”pattern” Shows commits whose author name matches the given pattern (case-sensitive string). git log –author=”Alice”
–committer=”pattern” Shows commits whose committer name matches the given pattern. git log –committer=”Bob”
–grep=”pattern” Shows commits whose commit message contains the given pattern (case-sensitive by default). Use -i for case-insensitivity. git log –grep=”fix”
git log –grep=”BUG” -i
[–] <file>… Shows commits that introduced changes to the specified file(s). The is used to disambiguate file names from branch names if needed. git log README.md
git log — src/app.js
–all Shows commits from all branches, not just the current one. git log –all –oneline –graph
–reverse Outputs the commits in reverse order (oldest first). git log –oneline –reverse

a. Default git log

Run git log in your my-git-cookbook-ch4 repository:

Bash
git log

Expected Output (will show newest commits first, details will vary):

Bash
commit <SHA-1_hash_commit_4> (HEAD -> main) # Or your default branch name
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:30:00 2025 +0300

    Add eggs to ingredients

commit <SHA-1_hash_commit_3>
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:25:00 2025 +0300

    Add ingredients and update README

commit <SHA-1_hash_commit_2>
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:20:00 2025 +0300

    Add chapter 3 info to README

commit <SHA-1_hash_commit_1>
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:15:00 2025 +0300

    Initial commit: Add README file

(Timestamps and hashes will be specific to your commits.)

Explanation of Output:

  • Each commit entry shows its full SHA-1 hash, author, date, and commit message.
  • (HEAD -> main) indicates that HEAD (your current position) is pointing to the main branch, which is at this commit.
  • Commits are listed in reverse chronological order (newest first).
  • If the history is long, git log uses a pager (like less) to display the output. Press q to quit the pager, spacebar to scroll down a page, b to scroll up.

b. git log --oneline

For a more concise view:

Bash
git log --oneline

Expected Output:

Bash
<short_hash_4> (HEAD -> main) Add eggs to ingredients
<short_hash_3> Add ingredients and update README
<short_hash_2> Add chapter 3 info to README
<short_hash_1> Initial commit: Add README file

Explanation of Output:

  • Shows the first 7 characters of the SHA-1 hash (usually enough to be unique) and the commit message title.

c. git log --decorate --graph --oneline

To see branch pointers and a simple ASCII graph of the history:

Bash
git log --decorate --graph --oneline

Expected Output (for a linear history):

Bash
* <short_hash_4> (HEAD -> main) Add eggs to ingredients
* <short_hash_3> Add ingredients and update README
* <short_hash_2> Add chapter 3 info to README
* <short_hash_1> Initial commit: Add README file

(The graph * becomes more interesting with branches and merges.)

Explanation of Output:

  • --decorate: Shows branch names, tags, and other refs pointing to commits.
  • --graph: Draws a text-based graph of the commit history on the left side.

d. git log -p or git log --patch

To see the changes (diffs or patches) introduced by each commit:

Bash
git log -p -1 # Show patch for the most recent commit

Expected Output (for the last commit):

Bash
commit <SHA-1_hash_commit_4> (HEAD -> main)
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:30:00 2025 +0300

    Add eggs to ingredients

diff --git a/ingredients.txt b/ingredients.txt
index <hash_before>..<hash_after> 100644
--- a/ingredients.txt
+++ b/ingredients.txt
@@ -1,2 +1,3 @@
 Flour
 Sugar
+Eggs

Explanation of Output:

  • Shows the commit metadata followed by the diff output for the changes in that commit.
  • -1 limits the output to the single most recent commit. You can use -<n> for n commits.

e. git log --stat

Shows abbreviated stats of changes for each commit:

Bash
git log --stat

Expected Output (excerpt for one commit):

Bash
commit <SHA-1_hash_commit_4> (HEAD -> main)
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:30:00 2025 +0300

    Add eggs to ingredients

 ingredients.txt | 1 +
 1 file changed, 1 insertion(+)

Explanation of Output:

  • Lists files modified in the commit and the number of lines added/removed.

f. Filtering Commits

  • By Number: git log -3 (shows the last 3 commits).
  • By Date/Time:git log --since="2 hours ago" git log --until="2025-05-15" git log --since="2025-05-01" --until="2025-05-14"
  • By Author:git log --author="Your Name" # Match author name string
  • By Committer:git log --committer="Your Name"
  • By Commit Message Content (Grep):git log --grep="README" # Finds commits with "README" in the message
    Tip: --grep is case-sensitive by default. Use -i for case-insensitivity (e.g., git log --grep="readme" -i).
  • By File: To see the history of changes affecting a specific file:git log README.md git log --oneline README.md
    This will only show commits where README.md was modified.
  • By Commit Range (SHA-1s): (More on this when we cover branches)git log <older-commit-hash>..<newer-commit-hash> shows commits reachable from <newer-commit-hash> but not from <older-commit-hash>.

Tip: Many of these options can be combined! For example: git log --oneline --graph --author="Your Name" -5

2. Viewing a Specific Commit: git show

To see the full details and patch for a single commit, use git show <commit-hash>:

Bash
# First, get a commit hash (e.g., the second commit)
# git log --oneline
# Let's say the second commit's short hash is <short_hash_2>

git show <short_hash_2> # Replace with an actual short hash from your log

Expected Output:

Bash
commit <SHA-1_hash_commit_2>
Author: Your Name <youremail@example.com>
Date:   Thu May 15 20:20:00 2025 +0300

    Add chapter 3 info to README

diff --git a/README.md b/README.md
index <hash_before>..<hash_after> 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
 # My Git Cookbook
 A collection of delicious Git recipes.
+Chapter 3: Our First Repository

Explanation of Output:

  • git show displays the commit metadata (author, date, message) and the diff of changes introduced by that specific commit compared to its parent.
  • You can use short or full SHA-1 hashes.
  • git show HEAD shows the last commit. git show HEAD~1 shows the commit before HEAD (its parent). HEAD~2 shows two commits before HEAD.

3. Comparing Commits: git diff <commit1> <commit2>

While git log -p and git show show changes introduced by a commit (i.e., diff against its parent), git diff <commit1> <commit2> shows the total difference between the snapshots of two arbitrary commits.

Bash
# Get two commit hashes, e.g., the first and third commit
# git log --oneline
# Let's say <short_hash_1> and <short_hash_3>

git diff <short_hash_1> <short_hash_3> # Replace with actual short hashes

Expected Output (shows all changes between snapshot at commit 1 and snapshot at commit 3):

Bash
diff --git a/README.md b/README.md
index <hash_readme_at_c1>..<hash_readme_at_c3> 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,4 @@
 # My Git Cookbook
 A collection of delicious Git recipes.
+Chapter 3: Our First Repository
+More details coming soon.
diff --git a/ingredients.txt b/ingredients.txt
new file mode 100644
index 0000000..<hash_ingredients_at_c3>
--- /dev/null
+++ b/ingredients.txt
@@ -0,0 +1,2 @@
+Flour
+Sugar

Explanation of Output:

  • This command shows the cumulative changes needed to transform the state of the project at <commit1> to the state at <commit2>.
  • It shows that ingredients.txt was created (diff against /dev/null) and README.md had two lines added compared to its state in the first commit.
Command What it Shows Purpose Typical Use Case
git show <commit> The metadata (author, date, message) and the patch (changes) introduced by the specified <commit> compared to its parent(s). To inspect the details and exact changes of a single, specific commit. “What exactly did commit abc1234 change?”
git log -p
or git log –patch
The commit history (metadata for multiple commits) along with the patch introduced by each of those commits compared to their respective parents. To review a sequence of commits and the changes each one brought in. “Show me the last 3 commits and the diff for each.”
git diff <commit1> <commit2> The cumulative differences between the entire project snapshot at <commit1> and the snapshot at <commit2>. To compare two arbitrary points in history and see what changed overall between them. “What are all the differences between version v1.0 (a tag pointing to a commit) and v1.1?”
“Show me changes between commit abc1234 and def5678.”
git diff <commit> (If only one commit is specified) Shows differences between the working directory and the specified <commit>. To compare your current (potentially uncommitted) work against a specific past commit. “How do my current changes compare to the state at commit abc1234?”

OS-Specific Notes

  • Pager for git log / git show:
    • On Linux, macOS, and Git Bash on Windows, git log and git show typically pipe their output through a pager program like less if the output is longer than your screen.
    • Navigating less:
      • q: Quit
      • Spacebar or f: Page forward
      • b: Page backward
      • /pattern: Search forward for pattern (press n for next match, N for previous)
      • ?pattern: Search backward
      • h: Help
    • On Windows Command Prompt or PowerShell (without Git Bash’s less), Git might output directly, or use a simpler pager if available. You can configure Git to use a specific pager.
  • Terminal Colors:
    • Many git log options (like --graph, --decorate, and diffs) use colors to enhance readability. These colors work best in terminals that support ANSI escape codes (most modern terminals, including Git Bash, macOS Terminal, Linux terminals).
    • If colors don’t appear or look strange, your terminal might not support them, or Git’s color settings might be turned off (git config --global color.ui auto usually enables them).
  • SHA-1 Hash Copy-Pasting: Be careful when copy-pasting SHA-1 hashes, especially from terminals that might wrap lines or add extra characters.

Common Mistakes & Troubleshooting Tips

Git Issue / Error Symptom(s) Troubleshooting / Solution
Misinterpreting git log order Thinking commits are listed oldest first by default. Solution: Remember git log shows newest commits first. Use git log –reverse for chronological order (oldest first).
Incorrect/Ambiguous SHA-1 Git reports “ambiguous argument” or “unknown revision” when using a short SHA-1. Solution: Use at least 4-7 characters for a short hash, or the full hash. Check for typos. git log –oneline helps get usable short hashes.
Confusing git diff <c1> <c2> with git show Expecting git diff <c1> <c2> to show only changes in <c2>. Diff output is larger than expected. Solution:
  • git show <commit>: Changes by <commit> vs. its parent.
  • git diff <c1> <c2>: Total difference between snapshots at <c1> and <c2>.
git log missing commits Not seeing commits known to be on other branches. Solution: Default git log shows history from HEAD. Use git log –all to see commits from all branches. git log –all –graph –oneline –decorate is very useful.
Trouble with date formats git log –since or –until doesn’t filter as expected or errors. Solution: Use clear formats like “YYYY-MM-DD”, “2 weeks ago”, “yesterday”. Check git help log (DATE FORMATS section).
Pager (e.g., less) navigation issues Stuck in git log output; unsure how to scroll or quit. Solution: Common less commands: q (quit), Spacebar (page down), b (page up), /pattern (search).

Exercises

Use the my-git-cookbook-ch4 repository you set up earlier for these exercises.

  1. Exploring History:
    1. View the entire commit history in a compact, one-line format, showing any branch or HEAD pointers.
    2. Display the last 2 commits, including the patches (diffs) they introduced.
    3. Find all commits authored by you in the last week that contain the word “README” (case-insensitive) in their commit message.
  2. Inspecting Specific Commits:
    1. From the git log --oneline output, pick the SHA-1 hash of your second commit (“Add chapter 3 info to README”).
    2. Use git show to display the full details and changes for this specific commit.
    3. Use git show HEAD~2 (the third commit from the end). What does it show? How does this relate to one of your earlier commits?
  3. Comparing Commits:
    1. Get the short SHA-1 hashes for your very first commit and your most recent commit.
    2. Use git diff to show all the changes that occurred between the state of your project at the first commit and the state at the most recent commit.
    3. What is the difference between git show <latest-commit-hash> and git diff <second-latest-commit-hash> <latest-commit-hash>? Explain the output of both.

Summary

This chapter delved into the core of Git’s history tracking mechanism—the commit:

  • Git Commits are Snapshots: Git stores a full snapshot of all tracked files with each commit, not just differences.
  • Anatomy of a Commit: Each commit has a unique SHA-1 hash and contains:
    • A pointer to a tree object (the project snapshot).
    • Pointer(s) to parent commit(s) (linking history).
    • Author and Committer information (name, email, timestamp).
    • A commit message.
  • HEAD is a special pointer to the current commit, usually the tip of the current branch.
  • git log is the primary tool for viewing commit history, with many powerful options:
    • --oneline, --graph, --decorate for concise and visual output.
    • -p or --patch to include diffs.
    • --stat for change statistics.
    • Filtering by number, date, author, committer, message content (--grep), and file.
    • --all to see history from all branches.
  • git show <commit-hash> displays detailed information and the patch for a single commit.
  • git diff <commit1> <commit2> shows the cumulative differences between the project states at two specified commits.

Understanding how to read and navigate your project’s history is a fundamental Git skill that enables you to track progress, understand changes, and diagnose issues.

Further Reading

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top