Skip to content
ExponaBLOG
GIT & GITHUB FOR PROFESSIONAL DEVELOPERS · DAY 019 / 100

Amending commits: Git & GitHub best practices explained

Fix the last commit.

Expona Admin7 min read

Introduction

You've just pushed a commit with a typo in the message, or you realized the code change you committed five minutes ago is incomplete. Rather than creating a follow-up commit that clutters your history, Git gives you a powerful way to fix the last commit. Amending commits: Git & GitHub best practices explained is about knowing when and how to use git commit --amend safely, so you can maintain a clean, professional repository without creating noise in your team's workflow.

In this article, we'll walk through the mechanics of amending commits, the critical rules around when it's safe to do so, and the gotchas that catch even experienced developers. By the end, you'll understand not just how to amend, but why the timing and strategy matter.

Understanding git commit --amend: Edit message or content

The git commit --amend command rewrites the most recent commit on your current branch. It does two things: it lets you change the commit message, and it lets you change the files included in that commit. Think of it as a chance to undo the last commit partially or completely, then commit again with corrections.

Here's a real scenario. You're working on a feature branch and commit a set of changes:

bash
$ git commit -m "Add user auth validation"

Moments later, you realize the commit message doesn't capture what you actually did. Or worse, you forgot to stage an important file. Instead of creating a second commit that says "fix: add missing file," you can amend:

bash
$ git add src/validators/auth.ts
$ git commit --amend

This command opens your editor (usually Vim, Nano, or VS Code, depending on your core.editor config). You can edit the message, save, and exit. Git rewrites the commit to include both the original changes and the new staged changes under a single commit object with a new hash.

The key insight: amending doesn't just fix the message. It also lets you add or remove files from the commit without creating extra commits. If you staged the wrong file, you can unstage it before amending. If you forgot a file, you stage it and amend. The result is a single, clean commit that contains exactly what it should.

Using --no-edit to keep the message unchanged

Sometimes you want to add or remove a file from the last commit but you're happy with the message. Typing git commit --amend alone will open your editor, which feels like unnecessary friction. That's where the --no-edit flag comes in.

bash
$ git add src/utils/helpers.ts
$ git commit --amend --no-edit

This amends the commit, includes the newly staged file, and keeps the original commit message intact. No editor opens. It's fast and minimal.

A practical example: you're in a code review feedback loop. Your reviewer asks you to add a missing test file to your last commit. You write the test, stage it, and run:

bash
$ git add tests/auth.test.ts
$ git commit --amend --no-edit

The commit now includes both your original changes and the new test. Your message remains unchanged. You push (following the rules we'll cover next), and the review is cleaner because all related work lives in one commit.

The --no-edit flag is also useful when you've amended the message and now want to add one more file without re-editing the message again:

bash
$ git add one-more-file.ts
$ git commit --amend --no-edit

Only amend unpushed commits: the golden rule

This is where amending shifts from a convenience tool to a critical discipline. You should only amend commits that have not been pushed to a shared repository. Here's why.

When you amend a commit, Git creates a new commit object with a new SHA hash. The old commit still exists locally in your reflog, but it's no longer directly referenced by your branch. If you've already pushed that commit to GitHub or a shared server, other developers may have already pulled it and based their own work on it. If you then force-push your amended commit, you're rewriting history that others have seen. This causes merge conflicts, lost work, and confusion.

In a solo project or a private feature branch that only you're working on, amending unpushed commits is safe and encouraged. It keeps your history clean before you share it:

bash
$ git commit -m "WIP: add auth"
$ git add tests/auth.test.ts
$ git commit --amend -m "Add user authentication with tests"
$ git push origin feature/auth

The remote only ever sees the final, clean commit. No one else has pulled the intermediate "WIP" version.

However, if you've already pushed:

bash
$ git commit -m "Add auth validation"
$ git push origin feature/auth
$ # Oops, typo in message. Teammate is reviewing.
$ git commit --amend -m "Add auth validation (fixed typo)"

Now your local branch has a different commit hash than the remote. If you force-push, your teammate's local branch becomes stale. They'll see confusing error messages and may lose uncommitted work if they pull carelessly.

The rule: amend before you push. Once it's shared, live with the minor flaw or use a new commit to fix it. Some teams enforce this with branch protection rules that prevent force-pushes to main or long-lived branches.

Force-push with lease if you absolutely must

There are rare cases where you need to amend and push simultaneously. Maybe you're on a short-lived feature branch that only you're using, and you've already pushed a draft commit. Or you're in a pair-programming session and you and your partner have agreed to amend a shared commit before anyone else touches it.

In these cases, use git push --force-with-lease, not a bare git push --force.

bash
$ git commit --amend -m "Updated message"
$ git push --force-with-lease origin feature/my-branch

The --force-with-lease flag is safer than --force. It checks whether the remote branch has been updated since you last fetched it. If it has, the push is rejected, protecting you from accidentally overwriting a teammate's recent push. A bare --force will overwrite anything, which is dangerous in shared workflows.

Think of it this way: --force-with-lease says "force-push only if no one else has pushed since I last synced." --force says "overwrite the remote no matter what." In professional teams, the latter is a red flag.

Even with --force-with-lease, communicate with your team. If you're on a branch that's being reviewed or worked on by others, amending and force-pushing creates friction. It's usually better to add a new commit with the fix and let the reviewer re-check it.

Common mistakes

  • Amending after pushing and wondering why git push fails. After you amend locally, your commit hash changes. A regular git push won't work because the remote has a different commit at that ref. You'll get a "rejected" error. Many developers panic and use --force without thinking. Remember: if you've pushed, don't amend. Or use --force-with-lease only in private branches.
  • Using git commit --amend when you meant to stage specific files first. If you run git commit --amend without staging anything new, it only lets you edit the message. If you have unstaged changes, they won't be included. Always double-check what you've staged with git status or git diff --cached before amending.
  • Forgetting that amended commits have new hashes. If you've shared a commit SHA with a teammate (e.g., "check out SHA xyz123 for context"), and you then amend it, that SHA no longer exists on your branch. Your teammate's reference is broken. Avoid sharing unpushed commit SHAs, or warn people that you might amend them.
  • Amending commits with a long history of pushes. If you've pushed commit A, then pushed commit B on top of it, and then realize you need to amend A, don't do it unless you're the only one on the branch. Amending A would require force-pushing, and commit B's parent hash would change, forcing a re-base on anyone pulling that branch.
  • Misunderstanding --force-with-lease as completely safe. It's safer than --force, but it's not a free pass to rewrite shared history. If your teammate pushed five minutes ago and you haven't fetched yet, --force-with-lease will still reject your push (good). But if they haven't pushed yet, it will succeed (possibly bad if they're mid-work). Communicate before force-pushing.

Key takeaways

  • git commit --amend rewrites the last commit, allowing you to change the message, add files, or remove files before sharing your work.
  • Use --no-edit to amend files without opening an editor, keeping the original commit message intact.
  • Only amend commits you haven't pushed to a shared repository. Once pushed, amending and force-pushing risks breaking your teammates' workflows.
  • If you must amend after pushing, use git push --force-with-lease instead of --force. It's a safety check that prevents overwriting unexpected remote changes.
  • Amending unpushed commits is encouraged because it keeps your history clean before you share it with the team.
  • Always communicate with your team about force-pushes, even with --force-with-lease, especially on shared or reviewed branches.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles