Skip to main content

What is a Commit?

A commit is a snapshot of your project at a specific point in time. It records the complete state of all tracked files, along with metadata about who made the changes, when, and why. Commits are the building blocks of Git’s history, forming a directed acyclic graph (DAG) that represents your project’s evolution.
Unlike many version control systems that store diffs, Git stores complete snapshots. This makes operations like checkout and branch switching extremely fast.

Anatomy of a Commit

Every commit is a Git object with a unique SHA-1 identifier. From commit.h and the Git data model, commits contain:
struct commit {
    struct object object;           // Base object properties
    timestamp_t date;              // Commit timestamp
    struct commit_list *parents;   // Parent commit(s)
    struct tree *maybe_tree;       // Root directory tree
    unsigned int index;            // Position in commit graph
};

Commit Contents

A commit stores these required fields:
1

Tree ID

A reference to the root directory tree object, which represents the complete directory structure and file contents at commit time:
tree 1b61de420a21a2f1aaef93e38ecd0e45e8bc9f0a
2

Parent(s)

SHA-1 hash(es) of the parent commit(s):
  • First commit: 0 parents
  • Regular commit: 1 parent
  • Merge commit: 2+ parents
parent 4ccb6d7b8869a86aae2e84c56523f8705b50c647
3

Author

Who wrote the changes and when:
author Maya <[email protected]> 1759173425 -0400
4

Committer

Who created the commit object (may differ from author in workflows using patches):
committer Maya <[email protected]> 1759173425 -0400
5

Commit Message

A description of the changes:
Add README

This commit adds initial project documentation
including setup instructions and usage examples.

Example Commit Object

Here’s how Git stores a commit internally (viewable with git cat-file -p <commit-id>):
tree 1b61de420a21a2f1aaef93e38ecd0e45e8bc9f0a
parent 4ccb6d7b8869a86aae2e84c56523f8705b50c647
author Maya <[email protected]> 1759173425 -0400
committer Maya <[email protected]> 1759173425 -0400

Add README

This commit adds initial project documentation.

Creating Commits

Basic Commit Workflow

From git-commit.adoc, the standard workflow is:
1

Stage your changes

$ git add file1.txt file2.txt
Adds file contents to the staging area.
2

Create the commit

$ git commit -m "Add new features"
Creates a new commit containing staged changes.

Commit Options

-a, --all

Automatically stage all modified and deleted files:
$ git commit -a -m "Update all tracked files"
This doesn’t stage new (untracked) files. Use git add for those first.

--amend

Modify the most recent commit:
$ git commit --amend -m "Better commit message"
Creates a new commit with the same parent, replacing the old one.

-v, --verbose

Show diff in the commit message editor:
$ git commit -v
Helps you write more accurate commit messages by seeing what changed.

--author

Override the author field:
$ git commit --author="Jane Doe <[email protected]>"

Commit Messages

Good commit messages are essential for maintainable projects. Git’s own guidelines from SubmittingPatches:
1

Summary line

First line: concise summary (≤50 characters)
Add user authentication module
2

Blank line

Separate summary from body:
Add user authentication module
                              ← blank line
3

Detailed description

Explain what and why (not how):
Add user authentication module

Implements JWT-based authentication to secure API endpoints.
This replaces the previous session-based approach, which had
scalability issues in distributed deployments.

The new system supports:
- Token refresh
- Role-based access control
- OAuth2 integration
The summary line appears in git log --oneline, email subjects (git format-patch), and GitHub’s commit list. Make it count!

Commit History

The Commit Graph

Commits form a directed acyclic graph (DAG) where:
  • Each commit points to its parent(s)
  • The graph has no cycles (you can’t travel back to the same commit)
  • Multiple paths can exist (from branches and merges)
    A---B---C  (main)
         \
          D---E  (feature)
From glossary-content.adoc:
A directed acyclic graph of commit objects forms the definitive commit graph. This structure enables Git’s powerful history traversal and branching capabilities.

Viewing History

git log

Basic commit history:
$ git log
commit 750b4ead9c87ceb3ddb7a390e6c7074521797fb3
Author: Maya <[email protected]m>
Date:   Mon Sep 29 15:17:05 2025 -0400

    Add README

git log --oneline

Condensed view:
$ git log --oneline
750b4ea Add README
4ccb6d7 Initial commit

git log --graph

Visualize branching:
$ git log --graph --oneline --all
* 750b4ea (HEAD -> main) Add README
* 4ccb6d7 Initial commit

git show <commit>

View a specific commit:
$ git show 750b4ea

Commit Internals

How Git Stores Commits

When you run git commit, Git performs these steps (implemented in commit.c):
1

Create tree objects

Convert the staging area into a tree structure representing directories and files.
2

Write commit object

Create a commit object containing:
  • Tree SHA-1
  • Parent commit SHA-1(s)
  • Author and committer info
  • Commit message
3

Calculate SHA-1

Hash the commit contents to generate its unique ID:
sha1("commit " + size + "\0" + content)
4

Update refs

Move the current branch reference to point to the new commit.

Commit Immutability

Commits are immutable. Once created, a commit object can never be changed.
Operations that appear to modify commits actually create new ones:
  • git commit --amend: Creates a new commit with the same parent
  • git rebase: Creates new commits with different parents
  • git cherry-pick: Creates new commits with different parents
The old commits remain in the object database until garbage collected.

Special Commit Types

Initial Commit

The first commit in a repository has no parents:
$ git log --oneline
4ccb6d7 (root-commit) Initial commit

Merge Commits

Merge commits have multiple parents, recording where branches joined:
tree abc123...
parent commit1...
parent commit2...
author Maya <[email protected]> ...

Merge branch 'feature' into main
Visualized:
    A---B---C---F  (main)
         \     /
          D---E    (feature)
Commit F is a merge commit with parents C and E.

Root Commits

Orphan branches start with a root commit (no parent):
$ git checkout --orphan new-root
$ git commit -m "New independent history"

Commit References

Git provides many ways to reference commits:
ReferenceDescriptionExample
SHA-1Full or abbreviated hash750b4ea
Branch nameLatest commit on branchmain
HEADCurrent commitHEAD
RelativeParent/ancestorHEAD^, HEAD~2
DateBy timestampmain@{2.days.ago}
ReflogBy positionmain@{1}

Relative References

# Parent of HEAD
$ git show HEAD^

# Grandparent of HEAD
$ git show HEAD~2

# Second parent of a merge commit
$ git show HEAD^2

Best Practices

1

Commit early and often

Make small, focused commits rather than large, monolithic ones. Each commit should represent a logical unit of change.
2

Write clear messages

Your future self (and colleagues) will thank you. Explain why the change was made, not just what changed.
3

Keep commits atomic

Each commit should be self-contained and should not break the build. This makes git bisect and cherry-picking more effective.
4

Review before committing

Use git diff --cached to review staged changes before committing.
5

Don't commit generated files

Exclude build outputs, dependencies, and IDE files using .gitignore.

Commit Operations

Amending the Last Commit

# Fix commit message
$ git commit --amend -m "Correct message"

# Add forgotten files
$ git add forgotten-file.txt
$ git commit --amend --no-edit

Reverting Commits

Create a new commit that undoes changes:
$ git revert 750b4ea
This creates a new commit that reverses the specified commit’s changes.

Resetting to a Previous Commit

# Keep working directory unchanged
$ git reset --soft HEAD~1

# Update working directory
$ git reset --hard HEAD~1
--hard discards all changes. Use with caution!

Further Reading

  • git help commit - Complete commit command reference
  • git help log - Viewing commit history
  • git help revisions - All ways to specify commits

Build docs developers (and LLMs) love