Python • Getting Started and Tooling

Git Commits — Commit source code changes with meaningful messages (conceptual workflow)

Learn how developers save snapshots of their code and write clear messages that explain every change.

Code braces with terminal and markup symbols representing Python programming.
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

Imagine writing a ten-page essay and accidentally deleting three pages with no way to get them back. Before version control systems existed, programmers faced exactly that risk every day. Early developers would copy entire folders of code and rename them with dates like project_backup_March5, which quickly became a chaotic mess. The need for a reliable way to track changes, undo mistakes, and collaborate with teammates drove the creation of increasingly sophisticated tools.

1972 • SCCS — Source Code Control System

Bell Labs created one of the first version control tools, allowing programmers to save sequential snapshots of individual files. It was slow and limited to one user at a time.

1986 • CVS — Concurrent Versions System

CVS introduced the ability for multiple developers to work on the same project simultaneously by merging changes. This was a game-changer for team projects.

2000 • Subversion (SVN)

Apache Subversion improved on CVS by tracking changes to entire directories rather than individual files, and it required a central server to store the project history.

2005 • Git Created by Linus Torvalds

Linus Torvalds, the creator of Linux, built Git to be fast, distributed, and reliable. Every developer gets a full copy of the project history on their own machine.

2008 • GitHub Launches

GitHub provided a web-based platform for hosting Git repositories, making collaboration and open-source development accessible to millions of developers worldwide.

Today, Git is the most widely used version control system in the world, and the commit is its fundamental building block. But what exactly is a commit, how does it capture your work, and why does writing a good commit message matter so much? Those are the questions this lesson will answer.

SECTION 2

Core Principles & Definitions

A Git commit is a permanent snapshot of your project at a specific moment in time. Think of it like pressing the save button in a video game — it records exactly where everything stands so you can return to that point later. Each commit also carries a commit message, a short description written by the developer that explains what changed and why. Understanding a few foundational ideas will make the entire commit workflow click.

1

Repository (Repo)

A repository is the folder that contains all of your project files plus a hidden .git directory where Git stores the full history of every change ever made.
2

Working Directory

The working directory is where you actively edit files. Changes here are not yet tracked by Git until you tell Git to pay attention to them.
3

Staging Area (Index)

The staging area is a preparation zone. You pick which changed files should be included in the next commit by "staging" them, giving you precise control over each snapshot.
4

Commit (Snapshot)

A commit permanently records everything in the staging area along with a unique ID (hash), the author's name, a timestamp, and a commit message.
5

Commit Message

A commit message is the human-readable note attached to every commit. It should be concise yet descriptive enough that anyone (including your future self) can understand the change.
✦

KEY TAKEAWAY

Think of Git like a photo album for your code. The working directory is where you take the photos, the staging area is where you select which photos to print, and a commit is the printed page glued permanently into the album with a caption (your commit message) describing the memory.

SECTION 3

Visual Explanation — The Commit Workflow

The diagram below shows the three zones that every file passes through on its way to becoming part of a commit. Understanding this flow is the single most important concept in using Git effectively.

Git Commit Workflow — Three ZonesWORKING DIRECTORYEdit your files heremain.py (modified)utils.py (new)readme.md (modified)STAGING AREASelect changes for commitmain.py ✓utils.py ✓REPOSITORYPermanent historya3f7c2d"Add login feature"b8e1f04"Fix typo in header"older commits…git addgit commitFiles flow left → right: edit, stage, then commit.
The three zones of Git: files are edited in the working directory, selected for inclusion via git add into the staging area, and permanently saved to the repository via git commit. Each commit receives a unique hash ID and the developer's commit message.

Notice that readme.md was modified in the working directory but was not staged. This is intentional — Git lets you be selective about which changes go into each commit. You might fix a bug in one file and start a new feature in another; by staging only the bug fix, you keep each commit focused on a single purpose. This practice, called making atomic commits, makes your project history much easier to read and debug.

SECTION 4

How a Commit Works Under the Hood

When you run git commit -m "Your message", Git performs several steps behind the scenes. Understanding this mechanism helps you appreciate why commits are so reliable and why the commit message is important metadata, not just a formality.

Anatomy of a Commit Object

Every commit is stored as a commit object inside the hidden .git folder. This object contains four pieces of information: a pointer to a tree (which records the state of every file at that moment), a pointer to the parent commit (the snapshot that came right before), the author and timestamp, and the commit message. Git generates a unique 40-character SHA-1 hash (like a3f7c2d...) from this content, which acts as the commit's fingerprint.

Anatomy of a Git Commit ObjectCOMMIT OBJECThash: a3f7c2d9e...tree → snapshot of all filesparent → b8e1f04a2...author → Alice, 2025-01-15message → "Add login feature"↑ This is why messages matter!PARENT COMMITb8e1f04a2..."Fix typo in header"parent → c92d...parent linkTREE (File Snapshot)main.py → blob abc123utils.py → blob def456readme.md → blob 789ghitree linkEach commit points to its parent, forming a chain of history.
A commit object stores a tree (file snapshot), a reference to the parent commit, the author's info, and the commit message. The parent links form a chain, creating a complete history timeline.

The Commit Commands in Sequence

Here is the typical command sequence you would type in a terminal. First, git status shows which files have been modified. Next, git add <filename> (or git add . for all changed files) moves them to the staging area. Finally, git commit -m "Fix login validation bug" creates the permanent snapshot with your message. After this, git log lets you view the chain of commits, each with its hash, author, date, and message.

💡

The -m Flag

The -m flag stands for "message." If you run git commit without it, Git will open a text editor so you can type a longer, multi-line message. For quick commits, the -m flag is the most common approach.

SECTION 5

Writing Meaningful Commit Messages

A commit without a good message is like a labeled jar with no label — you will forget what is inside. The commit message is your future self's lifeline and your teammate's guide. Let's break down what makes a commit message meaningful versus useless.

QualityBad Example ✗Good Example ✓
Specific"fixed stuff""Fix crash when user submits empty form"
Concise"I changed the color of the button on the homepage from blue to green because the client asked for it in the meeting last Tuesday""Change homepage button color to green per client request"
Imperative mood"Added new tests""Add unit tests for login module"
Purposeful"update""Update README with installation instructions"
Single-focus"Fix bug and add feature and refactor code""Fix off-by-one error in score calculation"

Good vs. Bad Commit Messages

The Convention: Imperative Mood

The widely accepted convention is to write commit messages in the imperative mood — as if you are giving a command. Instead of "Added tests" or "Adding tests," write "Add tests." A helpful trick: your message should complete the sentence "If applied, this commit will _______." For example, "If applied, this commit will add unit tests for login module." If it reads naturally, you have the right tense.

  • ✓ Keep the subject line under 50 characters — this ensures it displays fully in most Git tools.
  • ✓ Capitalize the first word — treat it like a sentence title.
  • ✓ Do not end with a period — the subject line is a title, not a full sentence.
  • ✓ One commit = one logical change — avoid bundling unrelated changes together.
✦

KEY TAKEAWAY

Imagine moving to a new house and labeling all your boxes. Writing "stuff" on every box would make unpacking a nightmare. But labels like "Kitchen — pots and pans" and "Bedroom — winter blankets" tell you exactly what is inside. Commit messages work the same way: be specific, be concise, and future-you will thank you.

SECTION 6

Worked Example — A Full Commit Workflow

Let's walk through a realistic scenario. You are building a Python calculator app, and you just finished adding a square-root function. Here is exactly how you would create a commit.

Committing a New Feature in a Python Project

  1. 1

    Step 1 — Check What Changed

    Run git status in your terminal. Git responds showing that calculator.py has been modified and tests/test_sqrt.py is a new untracked file. This tells you exactly which files have been touched since the last commit.
    Two files detected: one modified, one new.
  2. 2

    Step 2 — Stage the Relevant Files

    Run git add calculator.py tests/test_sqrt.py to move both files into the staging area. If you only wanted to commit one file, you would add just that file. This gives you fine-grained control over your snapshot.
    Both files are now staged and ready for commit.
  3. 3

    Step 3 — Verify the Staging Area

    Run git status again. Now Git shows both files under "Changes to be committed" in green. This confirmation step prevents you from accidentally including (or forgetting) a file.
    Staging area matches your intention — two files ready.
  4. 4

    Step 4 — Write a Meaningful Message and Commit

    Run git commit -m "Add square root function with input validation". Notice the message uses imperative mood ("Add" not "Added"), describes the specific change ("square root function"), and mentions a key detail ("with input validation"). Git responds with the new commit's hash, the branch name, and a summary of changes.
    Commit e4a9b71 created. 2 files changed, 24 insertions, 0 deletions.
  5. 5

    Step 5 — Verify the Commit in the Log

    Run git log --oneline to see a compact list of recent commits. Your new commit appears at the top with its short hash and message. This is the history that your teammates will read to understand how the project evolved.
    e4a9b71 Add square root function with input validation — your commit is now permanently recorded.

SECTION 7

Best Practices & Common Mistakes

Knowing how to commit is the first step, but knowing when and what to commit separates beginners from effective developers. The table below contrasts strong habits with common pitfalls.

Best Practice ✓Common Mistake ✗
Commit after each logical unit of work (one feature, one bug fix).Wait until the end of the day and dump everything into one massive commit.
Write descriptive messages that explain what and why.Use vague messages like "update" or "WIP" for permanent commits.
Review staged files with git status before committing.Blindly run git add . and commit without checking what is staged.
Keep sensitive data (passwords, API keys) out of commits.Accidentally commit a file containing passwords — it stays in history forever.
Use a .gitignore file to exclude generated files and dependencies.Commit large binary files or virtual environment folders that bloat the repository.

Best Practices vs. Common Mistakes

✦

KEY TAKEAWAY

Think of commits like chapters in a book, not one giant dump of text. Each chapter (commit) should tell one part of the story. A reader (or teammate) should be able to read the table of contents (git log) and understand the project's journey without opening a single file.

SECTION 8

Connection to Advanced Git Concepts

Once you are comfortable with basic commits, you will encounter more advanced Git features that build directly on the commit workflow. The table below gives you a preview of where this foundational skill leads.

Basic Concept (This Lesson)Advanced Concept (Future Learning)
Single linear chain of commitsBranching — create parallel timelines to develop features independently
Commits stay on your local machinePushing & Pulling — sync commits with a remote server like GitHub
One person making commitsMerge & Pull Requests — combine work from multiple developers and review code
Viewing history with git logGit Blame & Bisect — trace which commit introduced a specific bug
Writing messages with -mConventional Commits — a structured format like feat: or fix: used in professional teams

From Basic Commits to Advanced Git

Every one of these advanced tools depends on having a clean, well-documented commit history. If your commit messages are vague or your commits mix unrelated changes, features like git bisect (which finds the exact commit that caused a bug) become unreliable. The habits you build now — atomic commits and meaningful messages — are the foundation for professional software development.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

In your own words, explain the difference between the working directory, the staging area, and the repository. Why does Git use a staging area instead of committing all changes directly?
Show answer
The working directory is where you actively edit files — Git monitors this area but does not automatically save changes. The staging area is a preparation zone where you select exactly which changes should go into the next commit. The repository is the permanent storage of all committed snapshots. Git uses a staging area so you can control what goes into each commit. For example, if you fixed a bug in one file and started a new feature in another, you can stage only the bug fix, creating a focused commit. This separation gives you precision and keeps your history clean and readable.

Question 2: BASIC CALCULATION

You have modified three files: app.py, style.css, and index.html. You only want to commit the changes to app.py and index.html. Write the exact Git commands you would type, including a good commit message, assuming the change was fixing a broken navigation menu.
Show answer
First, run git add app.py index.html to stage only the two relevant files. Then run git commit -m "Fix broken navigation menu links". Notice that style.css is deliberately left out of the staging area because it is not related to the navigation fix. The commit message uses imperative mood ("Fix" not "Fixed"), is specific about what was broken ("navigation menu links"), and stays under 50 characters. You could later commit style.css separately with its own descriptive message.

Question 3: INTERMEDIATE

A teammate sends you the following git log --oneline output from their project. Identify which commit messages are poorly written and rewrite them following best practices. f3a12bc asdfasdf d92e1f4 Fix email validation to reject addresses without @ symbol a81bc90 updated stuff c44de21 Added homepage banner and fixed footer and changed database schema
Show answer
Commit d92e1f4 is well-written — it uses imperative mood, is specific, and focuses on one change. The other three need improvement. Commit f3a12bc is meaningless gibberish; without knowing what the change was, you might rewrite it as "Add password reset form to settings page" (assuming that was the actual change). Commit a81bc90 is too vague; a better version might be "Update user profile page layout." Commit c44de21 bundles three unrelated changes into one commit. It should have been split into three separate commits, such as "Add homepage banner image," "Fix footer alignment on mobile," and "Add email column to users table." Each commit should represent one logical change.

Question 4: APPLIED

You are working on a Python group project for school. Your partner pushed their code to GitHub yesterday. Today, you discover a bug: the function calculate_average() divides by zero when the input list is empty. You add a check for an empty list and also write a new test in test_stats.py. Describe your complete commit workflow, including which files to stage together and what your commit message should say. Should this be one commit or two?
Show answer
This is a judgment call, but the best practice here is to make this one commit because the bug fix and its test are logically related — the test verifies the fix. First, run git status to confirm which files changed. Then run git add stats.py test_stats.py to stage both files. Finally, run git commit -m "Fix division by zero in calculate_average for empty lists". This message explains the specific bug (division by zero), the function affected (calculate_average), and the trigger condition (empty lists). If you had also refactored an unrelated function during the same coding session, that refactor should be a separate commit with its own message.

Question 5: CRITICAL THINKING

A developer argues: "I don't need to write good commit messages because I remember what I changed." Present at least three arguments for why this mindset is problematic, drawing on concepts from this lesson. Consider both individual and team scenarios, as well as what happens over time.
Show answer
First, human memory is unreliable. After a few weeks — let alone months — you will not remember the details of every change you made. Good commit messages serve as documentation that your future self can search through. Second, software development is almost always a team activity. Teammates who review your code or take over a project need to understand the reasoning behind changes without asking you personally. The commit message is their primary window into your thought process. Third, debugging depends heavily on commit history. Tools like git bisect can automatically find the exact commit that introduced a bug, but this only works if commits are atomic and clearly labeled. A massive commit with the message "various changes" makes pinpointing the source of a bug nearly impossible. Finally, professional employers and open-source maintainers often evaluate developers partly by their commit history. Clean, well-documented commits signal professionalism and thoughtfulness.

SUMMARY

Lesson Summary

Summary

A Git commit is a permanent snapshot of your project that records the state of all staged files, the author, a timestamp, and a commit message. The workflow flows through three zones: you edit files in the working directory, select files for the next snapshot using git add to move them into the staging area, and then run git commit to permanently save them to the repository. Each commit is identified by a unique SHA-1 hash and links to its parent commit, forming a chain of project history.

Writing meaningful commit messages is just as important as making the commit itself. Good messages use the imperative mood, stay under 50 characters, describe a single logical change, and explain what was changed and why. Following the practice of atomic commits — one commit per logical change — keeps your project history clean and prepares you for advanced Git features like branching, merging, and collaborative workflows.

Varsity Tutors • Python • Git Commits — Commit source code changes with meaningful messages (conceptual workflow)