Complete git commands cheat sheet for developers. Learn 30 essential commands organized by workflow: setup, branching, merging, undoing, and collaboration.

You’ve memorized git add, git commit, and git push. When something goes wrong, you Google “how to undo git commit” and copy-paste Stack Overflow answers without understanding them.
Most developers use 5 git commands daily and panic when they need anything beyond that basic workflow. The problem isn’t that Git is complicated – it’s that most Git tutorials dump 100 commands on you alphabetically without explaining when you’d actually use them.
This guide covers 30 git commands organized by real-world use cases. Each command includes the syntax, when to use it, a practical example, and the common pitfalls that trip up developers. Master these 30 commands and you’ll handle 95% of daily Git workflows confidently.
TL;DR
Git is the de facto version control system for modern software development. Every developer uses it. Most developers don’t understand it.
The typical learning path: follow a tutorial that teaches git init, git add, git commit, and git push. Everything works fine until you accidentally commit to the wrong branch, encounter a merge conflict, or need to undo changes. Then you’re stuck Googling error messages and hoping Stack Overflow has the answer.
Git commands aren’t intuitive. git reset and git revert both undo changes but work completely differently. git pull is actually two commands combined. git checkout does three different things depending on how you use it.
This guide organizes git commands by workflow: setup commands you run once, daily commands you use constantly, branch commands for feature development, collaboration commands for team work, undo commands for fixing mistakes, and advanced commands for specific situations.
Each command follows the same format: what it does, when you’d use it, a concrete example, and the common mistakes developers make with it. Skip the commands you don’t need yet. Return to this guide when you hit a specific problem.
These git commands run once per machine or once per project. You don’t memorize them – you reference them during initial setup.
Purpose: Set the name that appears in commit history.
When to use: First time setup on a new machine or when changing your identity.
Example:
git config --global user.name "Alex Developer"
git config --global user.email "[email protected]"
Common pitfall: Forgetting the --global flag sets the name only for the current repository, not for all Git repositories on your machine. You’ll wonder why some repos show the right name and others don’t.
Purpose: Convert a regular folder into a Git repository.
When to use: Starting a new project from scratch on your local machine.
Example:
mkdir myproject
cd myproject
git init
The command creates a hidden .git folder that stores all version control data. The folder is now a Git repository capable of tracking changes.
Common pitfall: Running git init in the wrong directory. Always verify your current location with pwd (Linux/Mac) or cd (Windows) before initializing. Initializing your home directory or Desktop folder by accident creates chaos.
Purpose: Download an existing repository from a remote server (GitHub, GitLab, Bitbucket).
When to use: Joining an existing project, forking someone else’s code, or downloading open source software.
Example:
git clone https://github.com/username/repository.git
cd repository
The command creates a new folder with the repository name, downloads all files and commit history, and sets up the connection to the remote repository automatically.
Common pitfall: Cloning into a folder that already exists. Git will refuse unless the folder is empty. Either delete the existing folder or clone to a different location.
These git commands form your core workflow. You’ll use them dozens of times per day.
Purpose: Show the current state of your working directory and staging area.
When to use: Before every commit, when debugging, or when you’re unsure what’s happening.
Example output:
On branch main
Changes not staged for commit:
modified: index.js
modified: styles.css
Untracked files:
newfile.js
The output shows which branch you’re on, which files are modified but not staged, which files are staged for commit, and which files Git isn’t tracking yet.
Common pitfall: None – run git status constantly. It’s the fastest way to understand your current situation and Git provides helpful hints about what commands to run next.
Purpose: Move file changes from the working directory to the staging area (preparation for commit).
When to use: After editing files and before committing changes.
Examples:
git add index.js # Stage single file
git add src/ # Stage entire directory
git add *.css # Stage all CSS files
git add . # Stage all changes
The staging area lets you carefully select which changes to include in the next commit. You might have modified 10 files but only want to commit 3 of them.
Common pitfall: Using git add . without checking what you’re staging. This stages EVERYTHING, including files you meant to exclude (like .env with secret keys, or node_modules/ folder). Always run git status first to see what will be staged.
Purpose: Save staged changes to the local repository with a descriptive message.
When to use: After staging files with git add and you’re ready to record the changes.
Example:
git commit -m "Fix login redirect loop after password reset"
Good commit messages describe WHAT changed and WHY. Bad messages like “Update” or “Changes” tell future developers (including you) nothing useful.
Common pitfall: Running git commit without the -m flag opens a text editor (usually Vim or Nano) that confuses beginners. If this happens accidentally, type :q! and press Enter to exit Vim without saving.
Purpose: View commit history for the current branch.
When to use: Reviewing recent changes, finding a specific commit’s hash, or understanding project timeline.
Example output:
commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
Author: Alex Developer <[email protected]>
Date: Thu Feb 20 14:30:00 2026 +0000
Fix login redirect loop after password reset
Each commit shows a unique hash (the long alphanumeric string), the author, date, and commit message.
Common pitfall: Long commit histories are overwhelming. Use git log --oneline for a compact view showing one line per commit, or git log --oneline -10 to see only the last 10 commits.
Purpose: Show line-by-line changes between your working directory and the last commit.
When to use: Before staging changes to review what you edited.
Example output:
-const API_URL = 'http://localhost:3000';
+const API_URL = 'https://api.production.com';
Lines starting with - were deleted. Lines starting with + were added. This lets you catch accidental changes before committing.
Common pitfall: git diff only shows UNSTAGED changes. After running git add, you need git diff --staged to see what’s in the staging area ready to commit.
Branches let you develop features in isolation without breaking the main codebase. These git commands manage branch creation, switching, and deletion.
Purpose: List all branches in the repository OR create a new branch.
When to use: Checking which branches exist or creating a new feature branch.
Examples:
git branch # List all branches (* marks current)
git branch feature-login # Create new branch called feature-login
git branch -d old-feature # Delete branch after merging
Branch names should be descriptive: feature-payment-integration, fix-navbar-mobile, update-dependencies. Avoid generic names like temp or test.
Common pitfall: Creating a branch doesn’t automatically switch to it. After git branch feature-login, you’re still on the previous branch. Use git checkout feature-login to switch, or use git checkout -b feature-login to create and switch in one command.
Purpose: Switch from your current branch to a different branch.
When to use: Moving between features, returning to main branch, or switching to a colleague’s branch for review.
Examples:
git checkout main # Switch to main branch
git checkout feature-login # Switch to feature branch
git checkout -b fix-bug # Create new branch AND switch to it
When you switch branches, Git updates your working directory to match the target branch’s files. Changes from your previous branch disappear (but aren’t lost – they’re still in that branch).
Common pitfall: Uncommitted changes may block the switch if they would conflict with files in the target branch. Git will tell you “error: Your local changes to the following files would be overwritten.” Solution: commit your changes or use git stash (covered later).
Purpose: Delete a branch that’s no longer needed.
When to use: After merging a feature branch into main and you don’t need that branch anymore.
Example:
git checkout main
git merge feature-login
git branch -d feature-login
The -d flag (lowercase) only deletes if the branch has been merged. This protects you from accidentally deleting unmerged work.
Common pitfall: Trying to delete the current branch fails. You can’t delete the branch you’re currently on. Switch to a different branch first, then delete.
For force deletion (dangerous – deletes even unmerged branches): git branch -D feature-login
These git commands handle working with remote repositories and integrating changes from other developers.
Purpose: Combine changes from another branch into your current branch.
When to use: Integrating a completed feature branch into main, or pulling updates from main into your feature branch.
Example workflow:
git checkout main
git merge feature-login
This brings all commits from feature-login into main. If no conflicts exist, Git automatically creates a merge commit.
Common pitfall: Merge conflicts occur when the same line of code was modified differently in both branches. Git marks conflicts in the file with <<<<<<< HEAD, =======, and >>>>>>> feature-login markers. You must manually edit the file to resolve the conflict, then git add the file and git commit to complete the merge.
Purpose: Download changes from a remote repository and merge them into your current branch.
When to use: Daily synchronization with your team (run git pull at the start of each work session to get updates).
Example:
git pull origin main
This is actually two commands: git fetch origin (download changes) + git merge origin/main (merge them into your branch).
Common pitfall: Merge conflicts can happen during pull if your local changes conflict with remote changes. Resolve conflicts the same way as with git merge.
Purpose: Upload your local commits to a remote repository.
When to use: Sharing work with your team, backing up changes to GitHub/GitLab, or deploying code.
Examples:
git push origin main # Push main branch to remote
git push -u origin new-feature # First push of new branch (sets upstream)
git push # Shorthand after upstream is set
The -u flag (or --set-upstream) connects your local branch to the remote branch. After setting it once, you can use git push without specifying the remote and branch name.
Common pitfall: The first push of a new branch fails without -u: “fatal: The current branch has no upstream branch.” Solution: git push -u origin <branch-name>.
Purpose: Download changes from remote repository WITHOUT automatically merging them.
When to use: When you want to see what’s new on the remote before deciding whether to merge it into your work.
Example:
git fetch origin
git log origin/main # View remote commits
git merge origin/main # Merge if you want them
git fetch is safer than git pull because it gives you a chance to review changes before merging. This matters when working on shared branches.
Common pitfall: None – git fetch is read-only and can’t break anything. It’s the cautious way to check for updates.
These git commands fix mistakes. Use them carefully – some are destructive.
Purpose: Remove file from staging area (opposite of git add).
When to use: Accidentally staged the wrong file and want to unstage it.
Example:
git add . # Staged everything
git reset config/secrets.js # Unstage secrets file
git commit -m "Update config" # Commit everything except secrets
Common pitfall: This is NOT the same as git reset --hard (which is destructive). Plain git reset <file> only unstages – your changes remain in the working directory.
Purpose: Discard ALL uncommitted changes and return to the last commit state.
When to use: Experimental code failed badly and you want a clean slate.
Example:
git reset --hard HEAD
This is the nuclear option. Every modification since your last commit disappears permanently.
Common pitfall: THIS IS PERMANENT. No undo. Git doesn’t save your discarded changes anywhere. Only use this when you’re absolutely certain you want to destroy your uncommitted work.
Purpose: Create a NEW commit that undoes a specific previous commit.
When to use: Undoing a commit that’s already been pushed to a shared repository.
Example:
git log --oneline # Find commit hash
git revert a1b2c3d # Create revert commit
Unlike git reset, which rewrites history, git revert adds a new commit that undoes the old one. This is safe for shared branches because it doesn’t delete commits that others might have based work on.
Common pitfall: None – this is the safe way to undo commits. Always prefer git revert over git reset when working with shared branches.
Purpose: Temporarily save uncommitted changes and revert to a clean working directory.
When to use: Need to switch branches but current work isn’t ready to commit.
Example workflow:
# Working on feature-login, boss needs urgent fix
git stash # Save work-in-progress
git checkout main # Switch to main
# Fix bug, commit, push
git checkout feature-login # Return to feature
git stash pop # Restore saved work
Stashed changes are stored in a stack. Use git stash list to see all stashes, git stash pop to restore the most recent stash, or git stash drop to delete a stash without applying it.
Common pitfall: Forgetting you have stashed changes. Run git stash list periodically to check if you have work saved. Stashes persist across sessions until explicitly popped or dropped.
These git commands handle specific situations. You won’t use them daily but they’re essential when you need them.
Purpose: Move or combine a sequence of commits to a new base commit (alternative to merge that creates cleaner history).
When to use: Working alone on a feature branch and want linear history before merging to main.
Example:
git checkout feature-login
git rebase main # Replay feature commits on top of latest main
Rebasing rewrites commit history, making it appear as if your feature branch started from the current main branch instead of where it actually started.
Common pitfall: NEVER rebase commits that have been pushed to a shared branch. Rebasing rewrites history, which breaks other developers’ work if they based changes on the old commits.
Purpose: Copy a single commit from another branch without merging the entire branch.
When to use: Need one specific fix from a feature branch but don’t want all the other changes yet.
Example:
git log feature-experimental --oneline # Find commit hash
git checkout main
git cherry-pick a1b2c3d # Apply just that commit
Common pitfall: Cherry-picking can create duplicate commits if you later merge the source branch. Use sparingly for emergency fixes.
Purpose: List remote repository URLs connected to your local repository.
When to use: Verifying which remote repository you’re pushing to (especially after forking or cloning).
Example output:
origin https://github.com/username/repo.git (fetch)
origin https://github.com/username/repo.git (push)
Common pitfall: None – this is a read-only inspection command.
Purpose: Connect a local repository to a remote repository.
When to use: Created a local repo with git init and now want to push it to GitHub/GitLab.
Example:
git remote add origin https://github.com/username/new-repo.git
git push -u origin main
Common pitfall: Trying to add a remote that already exists. Git will error “fatal: remote origin already exists.” Use git remote remove origin first, or use a different name instead of “origin”.
Purpose: Mark a specific commit as a release version.
When to use: Creating an official release for production deployment or version tracking.
Example:
git tag v1.0.0
git push origin v1.0.0 # Push tag to remote
Tags are immutable references to specific commits. Unlike branches, they don’t move forward with new commits.
Common pitfall: Forgetting to push tags separately. Tags don’t push automatically with commits – use git push --tags to push all tags at once.
Purpose: View commit history in compact format (one line per commit).
When to use: Quick history scan without the full details of git log.
Example output:
a1b2c3d Fix login bug
d4e5f6g Add password reset
g7h8i9j Update dependencies
Common pitfall: None – this is just a more compact view of git log. Combine with -10 to limit output: git log --oneline -10.
Purpose: Show who last modified each line of a file.
When to use: Finding who wrote specific code (to ask questions, not to assign blame).
Example:
git blame index.js
Output shows commit hash, author, date, and line content for every line in the file.
Common pitfall: Using this for actual blame/punishment. The command’s name is unfortunate – use it constructively to understand code history, not to shame developers.
Purpose: Remove file from Git tracking AND delete from filesystem.
When to use: Deleting files that should no longer be part of the repository.
Example:
git rm obsolete.js
git commit -m "Remove obsolete script"
To stop tracking a file but keep it locally: git rm --cached <file>
Common pitfall: Regular file deletion (using OS commands) doesn’t tell Git the file is gone. Git will see it as a deleted file that needs to be staged. Using git rm handles both the deletion and the staging in one command.
Purpose: Rename or move a file while preserving Git history.
When to use: Renaming tracked files.
Example:
git mv oldname.js newname.js
git commit -m "Rename oldname to newname"
Common pitfall: Renaming files with OS commands creates confusion in Git. Git sees it as deleting one file and creating a new unrelated file. Use git mv to preserve the file’s history across the rename.
Purpose: Display the changes introduced by a specific commit.
When to use: Investigating what a particular commit changed.
Example:
git log --oneline # Find commit hash
git show a1b2c3d # View that commit's changes
Common pitfall: None – this is a read-only inspection command useful for code review and debugging.
These scenarios demonstrate how git commands combine to solve actual problems developers encounter.
Situation: You made commits on main but they should have been on a feature branch.
Solution:
git branch feature-name # Create branch where you are
git checkout feature-name # Switch to new branch
git checkout main # Return to main
git reset --hard HEAD~3 # Remove last 3 commits from main
The commits still exist on feature-name. You’ve just moved them off main.
Situation: Committed something broken or accidentally committed secrets.
Solution (keep changes):
git reset HEAD~1 # Undo commit, keep changes in working directory
Solution (delete changes):
git reset --hard HEAD~1 # Undo commit, delete all changes PERMANENTLY
HEAD~1 means “one commit before HEAD.” Use HEAD~2 for two commits, etc.
Situation: Committed .env file with API keys to the repository.
Solution:
git rm --cached .env # Stop tracking file
echo ".env" >> .gitignore # Add to gitignore
git commit -m "Remove .env from tracking"
Important: If you already pushed the commit, the secrets are in Git history. Rotation of compromised credentials is required. Git history rewriting tools like git filter-branch can remove it but are complex.
Situation: Been working on feature branch for days while main has moved forward.
Solution:
git checkout main
git pull origin main # Get latest main
git checkout feature-branch
git merge main # Merge main into feature
This brings your feature branch up to date with main. Fix any merge conflicts if they occur.
Situation: Modified a file but want to revert just that file to the last committed version.
Solution:
git checkout -- filename.js # Restore file from last commit
This only affects the specified file. Other changes remain untouched.
Situation: Git says “CONFLICT (content): Merge conflict in index.js”
Solution:
<<<<<<< HEAD
const API_URL = 'http://localhost:3000';
=======
const API_URL = 'https://api.production.com';
>>>>>>> feature-branch
const API_URL = 'https://api.production.com';
<<<<<<<, =======, >>>>>>>)git add index.jsgit commitGit mastery isn’t about memorizing 100 commands. It’s about understanding which command solves which problem and knowing where to look when you encounter something new.
The 30 git commands in this guide handle 95% of daily developer workflows. Print this guide. Keep it visible while coding. Reference it when you hit a problem. Over time, the most common commands become muscle memory while the less frequent ones remain available when needed.
Next steps after mastering these basics: explore git hooks for automation, git bisect for bug hunting, and git submodules for managing dependencies. But master these 30 first.
WebHostMost supports Git-based deployments natively. Push your code to production using git commands instead of FTP:
git remote add production <your-webhostmost-git-url>
git push production main
Your code deploys automatically. No file managers. No manual uploads. Just git push.
Learn more about WebHostMost hosting plans optimized for modern development workflows.
More developer resources: WebHostMost Blog
Master these 30 git commands and the panic of “I broke something in Git” transforms into “I know exactly how to fix this.”