Every change you save to a Git repository starts with one command. Understanding what git commit does is the difference between tracking your code properly and losing work you can’t get back.
Git commit takes a snapshot of your staged changes and records it permanently in your local repository. It’s the core action in any version control workflow, whether you’re working solo or across a team of fifty.
This guide covers how the commit command works internally, how it relates to git add and git push, how to write solid commit messages, and how to undo commits when things go wrong. You’ll also find practical flags, GUI tool options, and best practices that keep your commit history clean and useful.
What Is Git Commit

Git commit is the command that records staged changes to your local repository as a permanent snapshot. Think of it as a save point, except it captures the entire state of your tracked files at that exact moment.
Every commit creates a commit object containing a tree reference (your file structure), a parent pointer (the previous commit), author metadata, and your commit message. That object gets a unique SHA-1 hash, a 40-character string that acts as its ID.
This is different from hitting Ctrl+S. Saving a file only updates the working directory. Running git commit takes what you’ve moved to the staging area and writes it into the repository’s history.
Commits are local. Nothing touches a remote server until you explicitly push. Your entire Git repository lives on your machine, and commits just add new entries to that local history.
According to Stack Overflow’s developer survey, 93% of developers use Git as their primary version control system. And the commit command sits at the center of everything they do with it.
Hutte research found that 85% of developers say Git has improved their collaboration. That collaboration starts with commits. Every pull request, every merge, every code review traces back to individual commit objects in the log.
What Happens When You Run Git Commit

The internal process is more involved than most people realize. But it’s worth understanding because it explains why Git is so fast and reliable.
Step-by-step breakdown
Stage one: Git reads the staging area (also called the index) and builds a tree object. This tree maps every tracked file and directory to its blob hash.
Stage two: Git creates the commit object. This object contains four things: the tree hash, the parent commit hash, the author/committer info with timestamps, and the commit message.
Stage three: Git generates a SHA-1 hash of the entire commit object. That hash becomes the commit hash you see in your log output.
Stage four: The HEAD reference moves forward to point at the new commit.
Your working directory stays untouched. Nothing in your files changes. Git only writes objects to its internal database inside the .git/objects directory.
How Git stores data internally
Git is a content-addressable filesystem at its core. Every piece of data, whether a file, directory, or commit, gets stored as an object identified by its SHA-1 hash.
There are three object types that matter here:
- Blob: raw file contents, no filename, no path information
- Tree: a directory listing that maps filenames to blob hashes and child trees
- Commit: metadata plus a pointer to the root tree of that snapshot
If two files have identical content, Git stores one blob. It deduplicates automatically. This is part of why Git handles large codebases well.
Git Commit vs. Git Add

This trips up almost everyone early on. You edit a file, run git commit, and nothing happens. The file wasn’t staged.
Git add moves changes from your working directory into the staging area. Git commit takes what’s in the staging area and writes it to the repository. Two separate steps, by design.
Why Git separates staging from committing
The staging area exists so you can build selective commits. Maybe you changed five files but only three are related to the bug you just fixed. You stage those three, commit them, then deal with the other two separately.
This is how teams keep their commit history clean. One logical change per commit. Took me a while to actually practice this instead of just knowing it was a good idea.
Hutte data shows developers make an average of 7 commits before a push. That pattern works because staging in Git lets you break your work into small, focused chunks before anything reaches the remote.
The shortcut and when to avoid it
Running git commit -a stages all modified tracked files and commits them in one step. It skips untracked files entirely.
It’s fine for solo work on a small project. On a team, though, you lose the ability to be selective about what goes into each commit. Most experienced developers I’ve worked with avoid -a on shared branches.
| Command | What It Does | Best For |
|---|---|---|
| git add . then git commit | Stages everything, then commits | When all changes relate to one task |
| git add file.js then git commit | Stages one file, then commits | Partial commits, selective history |
| git commit -a | Auto-stages tracked files and commits | Quick solo work, small repos |
How to Write a Git Commit Message

The basic syntax is git commit -m "your message here". But “basic” and “good” are different things.
An aCompiler analysis of over one million Git commits found that 79% were related to feature development and bug fixes. Your commit messages need to clearly communicate which category a change falls into.
The 50/72 rule
Keep the subject line under 50 characters. If you need a body, wrap it at 72 characters per line.
The subject is what shows up in git log --oneline, in pull request lists, and in notification emails. If it gets truncated, you’ve already lost context.
Use imperative mood. Write “Add login validation” not “Added login validation.” Git itself follows this convention in its auto-generated messages (like “Merge branch ‘main'”), and your messages should match.
Conventional Commits format
The Conventional Commits specification structures messages like this: feat: add user authentication or fix: resolve null pointer in checkout.
A 2025 study analyzing over 3,000 top GitHub projects found 116 had explicitly declared their adoption of Conventional Commits (Wikipedia). In the NPM ecosystem specifically, roughly 94.5% of 381 popular projects contained commits following this standard.
The format lets automated tools generate changelogs, determine semantic version bumps, and trigger build pipelines. That’s why adoption keeps climbing.
Common commit message mistakes
- Vague one-word messages like “fix” or “update” that tell you nothing three months later
- Describing which file changed instead of why (“updated main.js” vs. “fix cart total calculation on empty cart”)
- Bundling unrelated changes into one commit with a message that only covers half of them
If you can’t summarize the commit in one clear sentence, you’re probably trying to commit too many things at once.
Git Commit Options and Flags
The base git commit command has a bunch of flags. Most developers only use three or four regularly.
The flags you’ll actually use
git commit -m "message" writes the message inline without opening an editor. Fast, but limits you to a subject line unless you chain multiple -m flags.
git commit --amend rewrites your last commit. Hutte research indicates 50% of developers use this regularly to fix typos in messages or add a file they forgot to stage.
git commit -v opens your editor and includes the full diff below the message template. Useful when you want to double-check what you’re about to commit.
Flags for specific situations
--no-edit pairs with --amend when you want to add staged changes to the last commit without changing the message. Clean and quick.
--allow-empty creates a commit with no file changes. Sounds useless, but it’s common for triggering CI/CD pipelines or marking milestones in the log.
Hutte data also shows 55% of developers use pre-commit hooks to catch problems before they get committed. These hooks run automatically when you execute git commit, checking for things like trailing whitespace, secrets in code, or linting failures.
| Flag | Purpose | Usage Frequency |
|---|---|---|
| -m | Inline message | Very high |
| –amend | Rewrite last commit | 50% of developers (Hutte) |
| -a | Auto-stage tracked files | High for solo work |
| -v | Show diff in editor | Moderate |
| –allow-empty | Commit with no changes | CI triggers, markers |
How Git Commit Fits Into the Git Workflow

Git commit doesn’t work in isolation. It’s one step in a longer chain, and where it sits matters.
The four-stage flow
Everything in Git moves through four areas:
- Working directory where you edit files
- Staging area where you prepare changes
- Local repository where commits live
- Remote repository where your team accesses the code
Git commit moves data from stage 2 to stage 3. That’s it. Getting code to the remote requires git push. Pulling code from the remote uses git pull or git fetch.
Commits and branches
Every branch in Git is just a pointer to a commit. When you commit on a branch, the branch pointer moves forward to the new commit. The old commit stays exactly where it was.
This is why branching in Git is so cheap. Creating a branch doesn’t copy files. It just creates a new pointer. Your commits build the actual branch history.
Over 90% of Fortune 100 companies use GitHub for their development workflows, according to Kinsta. All of those workflows depend on commits flowing through branches into pull requests.
Commits and the log
Running git log walks backward through the parent chain of commits. Each commit points to its parent. That linked chain is your project’s revision history.
You can filter the log by author, date range, file path, or message content. The usefulness of git log depends entirely on how well your team writes commit messages. Bad messages make the history almost worthless for debugging.
A related set of Git commands like git diff, git blame, and git status all interact with commit data. Understanding commits makes these tools click into place.
How to Undo a Git Commit

You will mess up a commit at some point. Everyone does. Hutte research shows 80% of developers regularly use git reset or git revert to undo changes.
The question is always: do you want to erase the commit from history, or add a new commit that reverses it?
Git reset and its three modes
Git reset moves the branch pointer backward and rewrites history. It has three modes, and each one handles your changes differently.
| Mode | Commit | Staging Area | Working Directory |
|---|---|---|---|
| –soft | Removed | Changes kept staged | Untouched |
| –mixed (default) | Removed | Changes unstaged | Untouched |
| –hard | Removed | Cleared | Cleared |
Soft reset is the safest. Your code stays exactly where it is, just uncommitted. Good for when the commit message was wrong or you forgot to include a file.
Hard reset destroys everything. Use it only when you’re sure. There’s no going back unless you dig into the reflog, and most people don’t know how to do that comfortably.
Git revert for shared branches
If your commit has already been pushed to a remote, reset is the wrong tool. Rewriting shared history breaks things for everyone on the team.
git revert creates a new commit that undoes the changes from a previous commit. History stays intact. Your teammates won’t have conflicts when they pull.
Hutte data shows nearly 90% of developers have faced merge conflicts. Using revert instead of reset on shared branches helps avoid creating even more of them.
The Linux kernel project, managed by Linus Torvalds (who also created Git), uses git revert as standard practice when backing out merged patches, specifically because it preserves the full commit trail for thousands of contributors.
When to use which
- Unpushed commit with a typo in the message?
git commit --amend - Unpushed commit that shouldn’t exist?
git reset --soft HEAD~1 - Pushed commit that introduced a bug?
git revert <commit-hash>
If you need to revert a commit in Git on a public branch, always reach for git revert. Save git reset for local work that hasn’t left your machine yet.
Git Commit in GUI Tools and IDEs

Not everyone works in the terminal. 65% of developers still prefer the command line for Git operations, according to Hutte. That leaves a solid 35% who rely on graphical interfaces, and plenty of developers switch between both.
VS Code source control
Visual Studio Code holds 75.9% of the developer market as of the 2025 Stack Overflow survey. Git support is built in, not an extension.
The Source Control panel lets you stage files, write commit messages, and commit without touching the terminal. You click the + icon to stage, type your message, and hit the checkmark. Same git commit command running underneath.
VS Code also shows inline diff views, gutter indicators for changed lines, and a Timeline view for per-file commit history.
GitHub Desktop and JetBrains IDEs
GitHub Desktop: Designed specifically for GitHub workflows. It handles staging, committing, branching, and pushing through a clean visual interface. Good for developers who want Git without memorizing commands.
JetBrains tools (IntelliJ IDEA, WebStorm, PyCharm) have a commit dialog that shows changed files, lets you review diffs, run inspections before committing, and write structured messages. IntelliJ IDEA usage sits at 27.1% in 2025, per Stack Overflow.
The underlying Git command is identical regardless of the interface. A commit made in GitHub Desktop and a commit made in Bash produce the exact same object in the repository.
Sourcetree and GitKraken
Both are standalone Git GUI clients that support multiple source control providers.
Sourcetree (by Atlassian) gives you a visual branch graph and interactive rebase tools. GitKraken adds drag-and-drop merge and a built-in code editor.
For teams that mix experience levels, GUI tools lower the barrier to using Git properly. Junior developers who might avoid committing because they’re scared of the terminal can commit confidently through a visual interface.
Git Commit Best Practices

Knowing how the command works is step one. Using it well is where teams actually see the difference.
Commit early, commit often
Small, frequent commits are easier to review, easier to revert, and less likely to cause merge conflicts.
A code review study cited by xdg.me found that defect discovery drops sharply when reviews exceed 200 lines of changed code. Keeping commits small keeps each review manageable.
Hutte data shows 92% of projects using Git enforce code review before merging. If your commits are bloated, those reviews take longer and catch fewer problems.
One logical change per commit
This is what “atomic commits” means. Each commit should represent a single, complete change, whether it touches one file or twenty.
Good commit: “Fix cart total calculation on empty cart”
Bad commit: “Fix cart bug, update header styles, remove unused imports”
The second one mixes three unrelated changes. If the header styles cause a regression, you can’t revert them without also losing the cart fix. Took me forever to discipline myself into this habit, but it pays off when you need to bisect through your history to find which commit broke something.
Write messages for your future self
aCompiler’s analysis of over 1 million Git commits revealed that 57% carry positive sentiment. But sentiment doesn’t matter if the message is vague.
Three months from now, “fix bug” tells you nothing. “Fix null pointer when user has no shipping address” tells you everything. The extra ten seconds you spend writing a clear message saves hours of investigation later.
Use branches to isolate work
Don’t commit experimental work directly to the main branch. Create a new branch, commit there, and merge through a pull request after review.
Hutte research shows 85% of collaborative projects use pull or merge requests in their workflow. That process only works when you’ve committed your changes to a feature branch first.
A Git workflow like Git Flow or trunk-based development defines exactly how branches and commits should interact. Pick one and stick with it across the team.
Sign commits on shared projects
GPG-signed commits verify that the commit actually came from who it says it came from. On open-source projects with hundreds of contributors, this matters.
GitHub shows a green “Verified” badge next to signed commits. It’s not hard to set up, but most developers skip it on private repos. For anything public, especially production software, it’s worth the few minutes of configuration through git config.
FAQ on What Does Git Commit Do
What does git commit actually do?
Git commit saves a snapshot of your staged changes to the local repository. It creates a commit object with a unique SHA-1 hash, a pointer to the parent commit, author metadata, and your message. Nothing reaches the remote until you push.
What is the difference between git add and git commit?
Git add moves file changes into the staging area. Git commit records whatever is staged as a permanent snapshot. They’re two separate steps, and skipping git add means your changes won’t be included in the commit.
Does git commit push code to GitHub?
No. Git commit only writes to your local repository. To send commits to a remote like GitHub or GitLab, you need to run git push afterward. Commits stay on your machine until then.
How do I write a good git commit message?
Keep the subject under 50 characters and use imperative mood. Write “Fix login bug” not “Fixed login bug.” Add a body wrapped at 72 characters if more context is needed. Clear messages make your commit history useful.
How do I undo the last git commit?
Use git reset --soft HEAD~1 to remove the commit but keep changes staged. Use --mixed to unstage them too. If the commit was already pushed, use git revert instead to preserve shared history.
What does git commit -m do?
The -m flag lets you write the commit message inline without opening a text editor. You type git commit -m "your message" directly in the terminal. For multi-line messages, you can chain multiple -m flags.
What does git commit –amend do?
It rewrites your most recent commit. You can change the message, add forgotten files, or both. The old commit gets replaced with a new one. Only use amend on commits that haven’t been pushed to a shared branch.
Can I commit without staging files first?
Yes. Running git commit -a stages all modified tracked files and commits them in one step. It skips untracked files entirely. Most teams avoid this on shared branches because it removes the ability to build selective commits.
What happens to my working directory after a commit?
Nothing changes. Your files stay exactly as they are. Git commit only writes data to the .git/objects directory internally. The working directory and your open editor remain untouched after the commit finishes.
How often should I commit in Git?
Commit after each logical change, not at the end of the day. Small, focused commits are easier to review, revert, and debug. Think of each commit as one complete task, whether that’s a bug fix, a feature addition, or a refactoring pass.
Conclusion
Knowing what git commit does gives you control over your project’s entire revision history. Every snapshot you save, every message you write, every branch you merge traces back to this single command.
The commit object sits at the center of Git’s distributed version control system. It connects your staging area to your local repository, stores SHA-1 hashes for data integrity, and builds the commit history that your team relies on for code reviews and debugging.
Get the basics right. Write clear commit messages. Keep commits atomic. Use –amend for local fixes and git revert` for shared branches.
Whether you work through the command line or a GUI like GitHub Desktop, the underlying process is the same. Master it once, and every other Git operation makes more sense.
- How to Clear All App Data on Android at Once - May 14, 2026
- How to Prep Your Codebase for M&A Due Diligence - May 13, 2026
- TypeScript Cheat Sheet - May 12, 2026



