Two commands, git add and git commit -m, build a snapshot in the local repository. A third, git push, is what puts that snapshot on GitHub.
The same routine covers a one-line README fix and a full feature branch.
A commit stays on your own machine until the push. The one exception is the GitHub web editor, where Commit changes writes straight to the remote branch (GitHub Docs).
GitHub Desktop and VS Code keep commit and upload as separate steps. Their upload buttons are Push origin and Sync Changes.
How to Commit to GitHub from the Command Line

The commit is a snapshot stored on your machine. Nothing reaches GitHub until the push.
- Run
git statusto see which files are modified or untracked. - Stage the files you want with
git add filenameorgit add . - Create the snapshot with
git commit -m "Fix redirect loop after login" - Upload it with
git push origin main
Stage the Changes
Staging decides what goes into the next commit. The git add command handles it, one file at a time or in bulk.
git add notes.md stages a single file and git add src/ a whole folder. git add . stages everything in the current directory that .gitignore does not exclude. It’s handy, but look at git status before you trust it.
Run git status again after staging. Anything listed under “Changes to be committed” goes into the snapshot, and the rest stays behind in the working directory.
Create the Commit
One command, one snapshot.
With -m the message goes inline, so git commit -m "Add rate limit to password reset" finishes without opening anything. Leave it off and Git opens your configured editor, then aborts the commit if you save an empty message.
When it works, Git prints the short commit hash and a file count. That hash is how you find this exact snapshot later.
Push the Commit to GitHub
A commit that has not been pushed exists only on your computer.
The git push command uploads new commits on the current branch to the remote named origin, which by convention is the URL of your GitHub repository.
On the first push of a branch, add the upstream flag, git push -u origin main. After that a plain git push is enough.
What to Set Up Before the First Commit
Before the first commit, the machine needs Git, a repository, a remote called origin and an author identity.
| Requirement | Command | Quick check |
|---|---|---|
| Git installed | git --version | Prints a version number |
| Repository | git init or git clone URL | A hidden .git folder appears |
| Remote | git remote add origin URL | git remote -v lists origin |
| Identity | git config --global user.name and user.email | git config --list shows both |
Git for Windows ships Git Bash, a terminal that runs every command in this article. If git --version fails, a walkthrough for installing Git covers each operating system.
git init suits a project that only exists on your disk, while git clone is for a repository already on GitHub, and it sets origin for you.
For a local project, create an empty repository on GitHub first. Copy its URL and run git remote add origin with it.
Every commit gets stamped with the name and email in your Git configuration.
GitHub reads the email to link commits to your account and to count them in your contributions graph (GitHub Docs). Commits made before an email change keep the old address.
To keep a personal address out of public history, use the GitHub-provided noreply address, which takes the form ID+username@users.noreply.github.com. GitHub also offers a setting that blocks command line pushes exposing a private email.
One trap: commits authored with the older username-only noreply address (username@users.noreply.github.com) lose their link to your account if you later change your GitHub username. The ID-based address does not have this problem.
Write the ignore rules before the first git add. A .gitignore file keeps dependencies, build output and .env files out of the snapshot.
Order matters here. A file that was committed once stays tracked and stays in history, even after you add its name to .gitignore.
How to Write a Commit Message
A good message starts with a short imperative subject line. A blank line follows, then an optional body that says what changed and why.
The git commit manual describes the same layout: one short summary line, a blank line, then the detail.
Subject lines should run 50 characters or less, capitalized, with no trailing period. Chris Beams’ widely cited guide calls 50 a rule of thumb and treats 72 as the hard limit before tools truncate it.
A quick test is whether the subject completes the sentence “If applied, this commit will \\\_”. “Add rate limit to password reset” passes. “Added rate limit” does not.
In the body, wrap lines at 72 characters and explain what and why. The diff already shows how.
Real projects enforce this. The Spring Web Flow contributing guide asks for an imperative subject of 50 characters or less if possible and a body wrapped at 72 characters or less.
| Weak | Specific |
|---|---|
| fixed stuff | Fix redirect loop after login |
| update | Add rate limit to password reset endpoint |
| changes | Remove unused Stripe webhook handler |
The subject line is what git log --oneline prints. Teams scanning the git log output for a regression read nothing else, so “changes” costs them real time.
Conventional Commits Prefixes
Conventional Commits 1.0.0 adds a type before the description, in the form type(scope): description, for example feat(auth): add login functionality.
feat marks a new feature and fix a bug fix. A BREAKING CHANGE goes in an uppercase footer, or as a “!” after the type, and it’s valid on any type.
Under semantic versioning, the specification maps feat to a MINOR release and fix to a PATCH release. Types such as docs, chore, refactor and test are allowed but carry no version effect on their own.
Adopt prefixes when release tooling or an automated changelog reads them. On a solo repository nobody enforces, plain imperative subjects are enough.
How to Authenticate When Pushing to GitHub
Pushes need a personal access token over HTTPS or an SSH key, because GitHub stopped accepting account passwords for Git operations on August 13, 2021 (GitHub changelog).
Push with a password today and Git answers “Support for password authentication was removed on August 13, 2021.”
A personal access token goes in the password prompt when you push over HTTPS.
The process of generating a GitHub token takes a few clicks in account settings. As of October 2026, GitHub Docs recommends fine-grained tokens over classic ones whenever possible.
A fine-grained token can be limited to specific repositories, and revoking one never touches your account password. Expiry is the annoying part. GitHub Docs highly recommends setting an expiration, so the token may need rotating. Fine-grained tokens also cannot access Packages, and any token leaks like a password if you paste it into a script.
An SSH key is a key pair. The public half sits on GitHub and the private half never leaves your machine.
Follow a guide on adding an SSH key to GitHub once per computer, then switch the remote to the SSH URL.
Nothing secret gets typed after setup. The cost is one setup per machine, and the remote URL has to change from HTTPS.
With GitHub CLI, run gh auth login, choose HTTPS, and answer yes when asked to authenticate Git with your GitHub credentials. Login and credential storage happen in one step, at the price of installing one more tool.
For HTTPS without the CLI, GitHub Docs recommends Git Credential Manager to store the token securely.
Which Method Fits Which Machine
On a personal laptop, an SSH key or gh auth login is the way to go. Shared or borrowed machines and automation both want tokens: a short expiration and no caching on the shared box, a fine-grained token scoped to one repository for automation.
Skip the classic token with every scope ticked. It is the most copied answer online and the riskiest one to leave on disk.
One failure shows up often on Windows. An expired token cached in Credential Manager keeps failing every push until you delete the GitHub entry under User Accounts, then Credential Manager (GitHub Docs).
GitHub also caps fine-grained tokens at 50 per account, which matters if you mint one per project and never clean up.
Terminal, GitHub Desktop, VS Code or the Web Editor: Which to Commit From
Use the web editor for a one-file fix and the terminal once you need to amend or reset history. GitHub Desktop and VS Code sit in between.
| Interface | Commit step | Push step | Best for |
|---|---|---|---|
| Terminal | git commit -m | git push | History edits, scripts |
| GitHub Desktop | Commit to BRANCH button | Push origin button | Working without a terminal |
| VS Code | Commit in Source Control panel | Sync Changes | Already coding in the editor |
| github.com editor | Commit changes dialog | None, the commit lands on GitHub | README typos, small edits |
GitHub Desktop commits locally and holds the upload until you click Push origin in the repository bar (GitHub Docs).
The GitHub Desktop client also shows a warning and blocks the commit when it breaks a repository ruleset. The terminal only tells you at push time.
In VS Code, the Source Control panel creates the commit in your local repository and Sync Changes sends it up. Skip the sync and the work never leaves your laptop.
If the editor is not signed in to GitHub yet, a guide on connecting VS Code to GitHub covers the setup.
The web editor behaves differently from the other three. Clicking Commit changes writes the commit straight to the remote.
You type the commit message in the dialog and, if you have more than one verified address, pick the author email. Then either commit directly to the branch, or choose a new branch and use Propose changes to open a pull request.
Protected branches reject web edits entirely. GitHub Docs points those cases to GitHub Desktop, which can move the changes to a new branch and commit them there.
Prefer the terminal for anything beyond routine commits. Amending, resetting and rewriting history are all command line operations.
How to Check, Amend or Undo a Commit
Check with git status and git log --oneline, then confirm the commit on GitHub. Fix a mistake with git commit --amend before pushing, and with a revert after.
Confirm the Commit Reached GitHub
git status reports whether your branch is ahead of origin/main, which means a push is still pending. git log --oneline lists the newest commit first, with its short hash and subject line. Then open the commit history on GitHub, where the same short hash should appear under the branch with your author name.
A matching hash on both sides settles it.
Amend the Last Commit
git commit --amend replaces the tip of the current branch with a new commit.
The editor opens with the old message pre-filled. The new commit keeps the same parents and author unless you add --reset-author (Git manual).
To fix the wording, run git commit --amend -m "Add rate limit to password reset". To add a forgotten file, stage it with git add and then run git commit --amend --no-edit.
Amend only commits you have not pushed. The Git manual warns about the implications of rewriting history that is already published.
If you amend a pushed commit anyway, the next push needs --force-with-lease. It aborts when someone pushed since your last fetch, which a bare --force does not.
Undo a Commit
git reset comes in soft, mixed and hard modes. All of them remove the commit from the branch, and they differ in what happens to your changes.
| Mode | Staging area | Working files |
|---|---|---|
--soft | Changes stay staged | Untouched |
--mixed (default) | Cleared | Changes kept |
--hard | Cleared | Changes discarded |
The git reset command moves the branch back, so git reset --soft HEAD~1 undoes the last commit and leaves everything staged for another try.
Use --hard rarely. It deletes uncommitted work with no undo.
For a commit that is already on GitHub and shared, reverting the commit is the safer route. It adds a new commit that cancels the old one, and the original stays in history.
Verified Commits
GitHub marks a commit Verified when its GPG, SSH or S/MIME signature checks out cryptographically, and Unverified when the signature cannot be verified (GitHub Docs).
GPG signing is more involved to set up but has features SSH signing lacks. SSH signing needs Git 2.34 or later, and S/MIME needs Git 2.19 or later.
GitHub Docs suggests GPG or SSH for most individual users. If an SSH key already authenticates your pushes, reusing the idea for signing is the lower-effort choice.
Once a signature verifies on push, it stays verified within the repository network, so a later key rotation does not flip old badges.
Why a Commit or Push Fails and What Breaks It
Most failed pushes come down to a remote that moved ahead, a bad credential, an oversized file, a committed secret or a detached HEAD.
| Symptom | Cause | Fix |
|---|---|---|
| [rejected] (fetch first) or (non-fast-forward) | Remote has commits you lack | Pull, resolve conflicts, push again |
| Authentication failed | Wrong remote URL or expired token | Check git remote -v, issue a new token |
| Push blocked on a large file | One file over the size limit | Move it to Git LFS or remove it from history |
| Commit sits on no branch | Detached HEAD | Create a branch from it at once |
| Key visible in history | Secret was committed | Rotate first, then rewrite history |
A rejected push means Git refuses to overwrite commits the remote has and you do not.
Run git pull, or git pull --rebase for a straighter history, fix any conflicts, then push. Forcing the push on a shared branch deletes your teammate’s commits.
GitHub counts file sizes in MiB, so the hard block sits at 104,857,600 bytes. Older tutorials say 100 MB, which is a slightly smaller number.
Browser upload accepts files up to 25 MiB. Git starts warning at 50 MiB and blocks at 100 MiB in regular Git history, and a single push tops out at 2 GB.
All four numbers come from GitHub Docs. Deleting the big file in a new commit does not clear the block, because the blob still sits in an earlier commit. Rewrite that commit, or track the file with Git LFS.
GitHub’s guidance on committed secrets is to treat anything in a pushed commit as compromised.
- Rotate or revoke the credential at its source.
- Rewrite history with git filter-repo or BFG Repo-Cleaner.
- Force push the cleaned branches.
- Ask GitHub Support to purge cached views if pull requests exposed the data.
Rewriting changes commit hashes, which disrupts open branches and pull requests. It also cannot reach existing clones or forks, which is why rotation comes first.
Prevention costs less than cleanup. Guides on keeping an API key out of a repository cover environment files and secret stores, and GitHub’s push protection blocks supported secret types before they reach the remote.
Checking out a specific commit instead of a branch puts you in a detached HEAD state, and any new commits belong to no branch.
Run git switch -c rescue-branch before checking out anything else. Switch away first and those commits become hard to find.
Committing to GitHub FAQ
What does git commit -a do?
It stages every modified and deleted file Git already tracks, then commits them in one step. New untracked files are skipped, so a freshly created file still needs git add first.
How often should I commit?
Whenever one self-contained change works, such as a fixed bug or a finished function. Small logical commits are easier to review, amend and revert than one large end-of-day commit.
How do I commit to a new branch instead of main?
Run git switch -c feature-name before committing. The commit lands on whichever branch is checked out. Push it with git push -u origin feature-name.
Can I commit part of a changed file?
Yes. Run git add -p and Git walks through each changed hunk, asking whether to stage it. Only the hunks you accept go into the next commit.
Can I commit an empty folder?
No. Git tracks files, not folders, so an empty directory never appears in a commit. Put a placeholder file inside it, commonly named .gitkeep, and commit that.
What Changes When Others Share the Repository
Committing directly on main works for a solo project and stops working once a second person pushes to the same branch. Each rejected push after that point costs both people a pull and a conflict check.
Create the branch before the first commit, so main stays untouched while a change is half finished. Branch from main, commit in small steps, then push the branch to origin.
The trade-off is one extra step per change and a merge at the end, accepted in return for a review before anything reaches main.
GitHub does not require branches by default, but branch protection can enforce them (verified October 2026). Once a reviewer is involved, opening a pull request on GitHub is the step that follows the push.
- Show Hidden Characters, Spaces, and Line Endings in Notepad++ - October 19, 2026
- Military and Defense UI/UX Design Services Firms to Know in 2026 - October 19, 2026
- How to Manage Your Google Play Subscriptions - October 17, 2026




