Staging and Committing
Recording work in Git is a two-step loop: git add selects changes into the index, and git commit writes them as a permanent snapshot with a message. The split feels like a chore at first, but the staging step is exactly what lets you turn a messy working tree into a series of clean, reviewable commits.
The commit is the unit everything downstream depends on — git log, code review, git revert, and git bisect all operate on commits. A commit that bundles three unrelated changes cannot be reverted surgically or reviewed cleanly, so the discipline you apply at this step is what makes the history worth reading later.
The Add-Then-Commit Loop
git add <paths> copies the current content of those paths into the index; git commit then writes whatever is in the index as a new commit and advances the branch. The two steps are separate because the index is a real layer you build up deliberately — you can stage some changes, leave others alone, and commit only the coherent subset, instead of being forced to commit the whole working tree at once.
Partial Staging
git add -p walks you through each changed hunk and asks whether to stage it. This is the lever that turns one chaotic afternoon of edits into separate commits: stage the hunks belonging to the bug fix, commit, then stage the refactor hunks and commit those separately. The result is a history where each commit is one logical change, which is what makes review and a later git revert precise rather than all-or-nothing.
Writing Commit Messages
A good message is a summary line under about 50 characters, a blank line, then a body that explains why the change exists — the diff already shows what changed. Future-you reading git log or git blame needs the reasoning, not a restatement of the patch. Conventions like Conventional Commits (fix:, feat:) add machine-readable structure on top, useful for generating changelogs, but the body explaining intent is the part that pays off.
Amending the Last Commit
git commit --amend replaces the most recent commit — to fix a typo in the message or add a file you forgot to stage. It does not edit the commit in place; it creates a new commit with a new hash and moves the branch to it. That is why it is safe only before pushing: once others have pulled the original commit, amending rewrites history they already have, and their next pull diverges.
Shortcuts and Their Traps
git commit -a auto-stages modified tracked files and commits in one step. The trap is in the word "tracked": it does nothing for new, untracked files, so a brand-new file is silently left out of the commit. It also skips the staging review the index gives you, so you lose the chance to confirm exactly what is going in. Convenient for a quick edit to known files, dangerous as a reflex.
- Reaching for
git commit -amreflexively, which skips staging review and never includes new untracked files, so a just-created file is left out and the build breaks on the remote. - Writing one-word messages like "fix" or "wip", which makes
git loguseless for ever finding when and why a change happened. - Running
git commit --amendon a commit already pushed to a shared branch, rewriting history others have pulled and forcing them into divergence conflicts. - Bundling unrelated changes into one large commit, so
git revertcannot undo just one of them and review has to untangle them by hand. - Forgetting to
git adda new file and committing only the tracked edits, leaving the remote build broken because a referenced file is missing.
- Stage deliberately with
git add -pand confirm withgit statusso each commit is one coherent change. - Write a summary under 50 characters in imperative mood, plus a body explaining why rather than what.
- Use
git commit --amendonly to fix the most recent commit before it has been pushed. - Commit small and often, since a series of focused commits reverts and reviews far better than one large one.
- Run
git diff --stagedimmediately before committing to see exactly what will be recorded.
hg commit commits the working copy directly; hg commit --amend matches GitSubversion svn commit sends the working copy with no stagingPerforce submits a changelist of grouped filesFossil fossil commit records the checkoutKnowledge Check
You created a new file, edited an existing tracked file, then ran git commit -am "update". What gets committed?
- Only the tracked file's edit —
-astages modified tracked files but ignores new untracked ones - Both files, since the
-aflag automatically stages everything currently present in the whole working tree - Only the brand-new file, because untracked files take priority during a commit
- Nothing at all — Git refuses
-aoutright when any untracked file is present
Why is git commit --amend safe locally but a problem after pushing to a shared branch?
- Amend creates a new commit with a new hash; once others have the original, replacing it makes their history diverge
- Amend deletes the entire remote branch on the server and recreates it from scratch, silently dropping everyone's unpushed work
- Amend only edits the commit message text, which the server rejects outright after a push
- It is equally safe in both of these cases; the warning about it is purely cosmetic
What does the separate staging step buy you that committing the whole working tree at once does not?
- The ability to select exactly which changes — even individual hunks via
git add -p— go into each commit - Noticeably faster commits overall, because the staged index is held cached entirely in memory for quick writes
- Automatic conflict resolution against the remote branch as you stage each file
- A durable backup of the working tree that survives even a
git reset --hard
Why does commit granularity matter for git revert and review months later?
- A focused commit can be reverted on its own and reviewed in isolation; a commit bundling unrelated changes cannot be undone surgically
- Smaller, single-purpose commits compress noticeably better than large ones, which steadily reduces the overall repository size on disk over time
- Git refuses to revert any commit larger than a configured maximum number of changed lines
- Granularity only affects how fast
git logrenders its output, not any actual behavior
You got correct