Skip to content
Kordu Tools

Git Commands Cheat Sheet: From Basics to Advanced

Complete git cheat sheet with 50+ commands, real examples, and ASCII branch diagrams. Used by 100M+ developers worldwide. Bookmark this reference.

I
iyda
15 min read
git git cheat sheet git commands version control git rebase

Git is the version control system behind virtually every software project on Earth. Over 100 million developers use it daily (GitHub Octoverse, 2024). Yet most developers only know a handful of commands. This cheat sheet covers everything from first-time setup to advanced techniques like bisect and reflog, with real examples you can copy and run. Bookmark it. You’ll be back.

Key Takeaways

  • Git's daily workflow (add, commit, push, pull) covers about 80% of what most developers do.
  • Rebase rewrites history into a clean line. Merge preserves it. Pick based on your team's convention.
  • Destructive commands (reset --hard, force push) can't be undone easily. Use reflog as your safety net.
  • Over 100 million developers use Git daily (GitHub Octoverse, 2024).

How Do You Set Up Git for the First Time?

Git requires a username and email before your first commit. According to Stack Overflow’s 2024 Developer Survey, 93.9% of developers use Git for version control (Stack Overflow, 2024). Getting the config right from the start saves headaches later.

Identity


git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Editor and defaults

# Set VS Code as default editor
git config --global core.editor "code --wait"

# Set default branch name to main
git config --global init.defaultBranch main

# Enable colored output
git config --global color.ui auto

Check your config

# List all settings
git config --list

# Check a specific value
git config user.name

Tip

Use --global for settings that apply to all repos. Drop it to set per-repo overrides. Your global config lives at ~/.gitconfig.

SSH key setup

# Generate an ED25519 key (recommended over RSA)
ssh-keygen -t ed25519 -C "you@example.com"

# Start the SSH agent and add your key
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

# Copy public key to clipboard (macOS)
pbcopy < ~/.ssh/id_ed25519.pub

Then paste the public key into your GitHub/GitLab SSH settings. Test with ssh -T git@github.com.

What Are the Essential Daily Git Commands?

The daily workflow boils down to five commands: status, add, commit, push, and pull. A 2024 JetBrains survey found that 77% of developers commit at least once per day (JetBrains Developer Ecosystem, 2024). Master these first.

Command What It Does Example
git init Create a new repository git init my-project
git clone <url> Copy a remote repo locally git clone git@github.com:user/repo.git
git status Show working tree state git status (run this constantly)
git add <file> Stage changes for commit git add src/app.ts
git add -p Stage changes interactively, hunk by hunk git add -p (then y/n per change)
git commit -m Save staged changes with a message git commit -m 'fix: resolve login bug'
git push Upload commits to remote git push origin main
git pull Fetch + merge from remote git pull origin main

The staging area explained

Git has three states for your files: modified, staged, and committed. The staging area (index) lets you craft commits precisely. You don’t have to commit everything at once.

# Stage specific files
git add src/utils.ts src/helpers.ts

# Stage all changes in current directory
git add .

# Stage only tracked files (skip new untracked files)
git add -u

# Unstage a file (keep the changes, just remove from staging)
git restore --staged src/utils.ts

Tip

git add -p (patch mode) is the most underused Git feature. It lets you stage individual hunks within a file. Perfect for splitting a messy working directory into clean, logical commits.

Writing good commit messages

# Short format (under 72 chars)
git commit -m "fix: prevent null pointer in user lookup"

# Long format with body (opens editor)
git commit
# In your editor:
# fix: prevent null pointer in user lookup
#
# The getUser() function returned undefined when the cache
# expired. Added a null check before accessing .name property.
# Fixes #142

Follow the Conventional Commits spec: type: description. Common types: feat, fix, docs, refactor, test, chore.

How Do You View History and Diffs?

Understanding what changed and when is half of version control. Git’s log and diff commands are powerful but verbose by default. These aliases and flags cut through the noise.

Command What It Does Example
git log --oneline Compact commit history git log --oneline -20
git log --graph Visual branch history git log --oneline --graph --all
git diff Show unstaged changes git diff src/app.ts
git diff --staged Show staged changes git diff --staged
git diff main..feature Compare two branches git diff main..feature -- src/
git show <commit> Show a specific commit's changes git show abc1234
git blame <file> Show who changed each line git blame src/app.ts
git log -S 'text' Search commits for added/removed text git log -S 'TODO' --oneline

Useful log formats

# Pretty one-line graph (add as alias)
git log --oneline --graph --decorate --all

# Commits by a specific author
git log --author="Your Name" --oneline

# Commits in a date range
git log --after="2026-01-01" --before="2026-03-01" --oneline

# Files changed in each commit
git log --stat --oneline -10

How Does Git Branching Work?

Branches are Git’s killer feature. They’re lightweight pointers to commits, not copies of your codebase. Creating a branch takes microseconds. The 2024 GitHub Octoverse report shows the average active repo has 8 branches (GitHub Octoverse, 2024). Use them aggressively.

Command What It Does Example
git branch List local branches git branch
git branch -a List all branches (local + remote) git branch -a
git branch <name> Create a new branch git branch feature/login
git checkout <branch> Switch to a branch git checkout feature/login
git checkout -b <name> Create and switch in one step git checkout -b fix/header-bug
git switch <branch> Switch branches (modern syntax) git switch main
git switch -c <name> Create and switch (modern syntax) git switch -c feature/search
git branch -d <name> Delete a merged branch git branch -d feature/login
git branch -D <name> Force-delete an unmerged branch git branch -D experiment

Branch naming conventions

Most teams follow a pattern: type/short-description. Common prefixes:

  • feature/ for new functionality
  • fix/ or bugfix/ for bug repairs
  • hotfix/ for urgent production fixes
  • release/ for release preparation
  • chore/ for maintenance tasks
# Good branch names
git checkout -b feature/user-authentication
git checkout -b fix/cart-total-rounding
git checkout -b hotfix/security-patch-2026-03

# Bad branch names (too vague)
git checkout -b update
git checkout -b fix
git checkout -b johns-branch

What’s the Difference Between Git Merge and Rebase?

This is the most debated question in Git workflows. Merge preserves history as it happened. Rebase rewrites it into a clean line. According to a 2023 GitKraken survey, 75% of development teams use a merge-based strategy, while 25% prefer rebase (GitKraken Git Report, 2023). Neither is wrong. Pick one and be consistent.

Merge: preserve history

git checkout main
git merge feature/login
# Before merge:
      A---B---C  feature/login
     /
D---E---F---G    main

# After merge:
      A---B---C
     /         \
D---E---F---G---H  main (H = merge commit)

Merge creates a new commit (H) that ties the branches together. The full history of both branches stays intact. This is the safe, conservative choice.

Rebase: rewrite onto a clean line

git checkout feature/login
git rebase main
# Before rebase:
      A---B---C  feature/login
     /
D---E---F---G    main

# After rebase:
              A'--B'--C'  feature/login
             /
D---E---F---G             main

Rebase replays your commits (A, B, C) on top of the latest main. The result is a perfectly linear history. The tradeoff: it rewrites commit hashes (A becomes A’).

Warning

Never rebase commits that other people have pulled. Rewriting shared history forces everyone to re-sync, which creates duplicate commits and confusion. Only rebase your own local, unpushed work.

When to use which?

  • Merge when you want a clear record that a feature branch existed.
  • Rebase when you want a clean, linear history before merging.
  • Squash merge (git merge --squash) when the feature branch has messy interim commits.

A common workflow: rebase your feature branch onto main locally, then merge with --no-ff to create a merge commit on main. You get clean history and a clear merge point.

# Clean workflow
git checkout feature/login
git rebase main              # Clean up your branch
git checkout main
git merge --no-ff feature/login  # Merge with a merge commit
git branch -d feature/login

How Do You Undo Mistakes in Git?

Everyone messes up. Git’s safety net is deep if you know where to look. The key distinction: some commands are safe (they don’t destroy work), and some are destructive (they permanently discard changes).

Command What It Does Destructive?
git restore <file> Discard unstaged changes to a file Yes, changes are lost
git restore --staged <file> Unstage a file (keep changes) No
git commit --amend Edit the last commit message or add files Rewrites last commit
git revert <commit> Create a new commit that undoes a past commit No (safe)
git reset --soft HEAD~1 Undo last commit, keep changes staged No
git reset --mixed HEAD~1 Undo last commit, keep changes unstaged No
git reset --hard HEAD~1 Undo last commit, discard all changes Yes, data loss

Amending the last commit

# Fix the message
git commit --amend -m "fix: correct the login redirect URL"

# Add a forgotten file to the last commit
git add forgotten-file.ts
git commit --amend --no-edit

Reverting a pushed commit

# Safely undo a specific commit (creates a new "undo" commit)
git revert abc1234

# Revert a merge commit (specify which parent to keep)
git revert -m 1 abc1234

Revert is the safe option for shared branches. It doesn’t rewrite history.

Warning

git reset --hard permanently destroys uncommitted changes. There’s no undo. If you’ve already committed the work, reflog can save you. But unstaged changes lost to --hard are gone forever.

The three flavors of reset

git reset --soft HEAD~1
# Commit is undone. Changes are staged. Ready to re-commit.

git reset --mixed HEAD~1    (default)
# Commit is undone. Changes are in working directory but unstaged.

git reset --hard HEAD~1
# Commit is undone. Changes are gone. Working directory is clean.

How Do You Work with Remote Repositories?

Remote operations connect your local repo to GitHub, GitLab, Bitbucket, or any hosted Git server. As of 2024, GitHub hosts over 420 million repositories (GitHub About Page, 2024). Understanding remotes is essential for collaboration.

Command What It Does Example
git remote -v List remotes with URLs git remote -v
git remote add <name> <url> Add a new remote git remote add upstream git@github.com:org/repo.git
git fetch Download remote changes (don't merge) git fetch origin
git pull Fetch + merge git pull origin main
git pull --rebase Fetch + rebase (cleaner) git pull --rebase origin main
git push Upload local commits git push origin main
git push -u origin <branch> Push and set upstream tracking git push -u origin feature/login
git push --force-with-lease Force push safely (checks remote first) git push --force-with-lease origin feature/login

Fetch vs pull

git fetch downloads new commits from the remote but doesn’t touch your working directory. It’s always safe. git pull is git fetch + git merge (or git rebase if you pass --rebase). When in doubt, fetch first and inspect.

# Safe workflow
git fetch origin
git log HEAD..origin/main --oneline  # See what's new
git merge origin/main                # Merge when ready

Warning

git push --force overwrites the remote branch with your local version. If a teammate pushed changes you haven’t fetched, their work vanishes. Always use --force-with-lease instead. It fails if the remote has commits you haven’t seen.

Tracking branches

# See which local branches track which remotes
git branch -vv

# Set an existing branch to track a remote
git branch --set-upstream-to=origin/main main

How Do You Use Git Stash?

Stash temporarily shelves your changes so you can switch context. It’s a developer’s quick-save button. We’ve found it’s one of the most practical yet underused features, especially when you need to pull changes or switch branches mid-task.

# Stash everything (staged + unstaged)
git stash

# Stash with a descriptive message
git stash push -m "WIP: half-finished search bar"

# Stash including untracked files
git stash -u

# List all stashes
git stash list

# Apply the most recent stash (keep it in the stash list)
git stash apply

# Apply and remove from stash list
git stash pop

# Apply a specific stash
git stash apply stash@{2}

# Drop a specific stash
git stash drop stash@{0}

# Clear all stashes
git stash clear

Tip

Always use git stash push -m "description" instead of plain git stash. Future you will have no idea what stash@{3} contains without a message.

How Does Git Cherry-Pick Work?

Cherry-pick copies a single commit from one branch to another. It doesn’t move or merge anything. It creates a new commit with the same changes. This is useful when a bugfix lands on the wrong branch, or you need one specific change without merging an entire feature.

# Copy a single commit to your current branch
git cherry-pick abc1234

# Cherry-pick without committing (stage the changes instead)
git cherry-pick --no-commit abc1234

# Cherry-pick a range of commits
git cherry-pick abc1234..def5678
# Before cherry-pick (you're on main):
      A---B---C  feature
     /
D---E---F        main

# After cherry-picking commit B:
      A---B---C  feature
     /
D---E---F---B'   main  (B' has the same changes as B)

When to cherry-pick

  • Backporting a bugfix from main to a release branch.
  • Pulling one commit from a feature branch that isn’t ready to merge.
  • Recovering a commit from a deleted branch (find it with git reflog).

But don’t overuse it. If you’re cherry-picking multiple commits, a merge or rebase is usually cleaner.

How Do You Debug with Git Bisect?

Git bisect uses binary search to find the exact commit that introduced a bug. Instead of checking commits one by one, it cuts the search space in half each step. On a branch with 1,000 commits, bisect finds the culprit in roughly 10 steps instead of 500.

# Start bisecting
git bisect start

# Mark the current commit as bad (has the bug)
git bisect bad

# Mark a known good commit (before the bug existed)
git bisect good v2.0.0

# Git checks out a middle commit. Test it, then:
git bisect good   # if this commit works fine
git bisect bad    # if this commit has the bug

# Repeat until Git identifies the first bad commit
# When done:
git bisect reset  # Return to your original branch

Automated bisect

If you have a test script that exits 0 for good and non-zero for bad, you can automate the entire process.

git bisect start
git bisect bad HEAD
git bisect good v2.0.0
git bisect run npm test

Git runs the test at each step automatically. In our experience, automated bisect has saved hours of debugging on large codebases where manual testing would be painful.

Tip

Write a small shell script that reproduces the bug and returns exit code 0 (good) or 1 (bad). Then git bisect run ./test-bug.sh does all the work. This is dramatically faster than manual bisecting.

What Is Git Reflog and How Does It Save You?

Reflog is Git’s hidden undo history. It records every time HEAD moves, even operations like reset --hard and rebase. If you’ve committed something and then “lost” it, reflog almost certainly still has it. Entries persist for 90 days by default.

# View reflog
git reflog

# Example output:
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: add search feature
# 789abcd HEAD@{2}: commit: update homepage
# ...

# Recover a "lost" commit after a bad reset
git reset --hard HEAD@{1}

# Or create a branch from the lost commit
git branch recovery-branch HEAD@{1}

Common rescue scenarios

Accidentally ran git reset --hard:

git reflog                          # Find the commit before the reset
git reset --hard HEAD@{1}          # Jump back to it

Deleted a branch with unmerged work:

git reflog                          # Find the last commit on that branch
git checkout -b recovered HEAD@{5}  # Recreate it

Messed up a rebase:

git reflog                          # Find the commit before the rebase
git reset --hard HEAD@{4}          # Restore pre-rebase state

Tip

Think of reflog as your local time machine. It only exists on your machine (it’s not pushed to remotes), and entries expire after 90 days. But within that window, almost nothing is truly lost.

What Are the Most Useful Git Aliases?

Aliases turn verbose commands into quick shortcuts. They go in your ~/.gitconfig file. In our experience, a good set of aliases can cut your daily typing by half without hiding what Git is actually doing.

# Add these aliases
git config --global alias.s "status --short"
git config --global alias.co "checkout"
git config --global alias.br "branch"
git config --global alias.cm "commit -m"
git config --global alias.lg "log --oneline --graph --decorate --all -20"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.wip "stash push -m"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.unstage "restore --staged"

After setup, your workflow becomes:

git s                    # Quick status
git lg                   # Visual log
git cm "fix: typo"       # Fast commit
git undo                 # Undo last commit (keep changes)
git amend                # Add to last commit silently

Quick Reference: Git Commands by Category

Here’s every command from this guide in one scannable table, organized by workflow phase.

Category Command One-Liner
Setup git config --global user.name Set your identity
Setup git init New repository
Setup git clone <url> Copy remote repo
Daily git add -p Stage interactively
Daily git commit -m 'msg' Save with message
Daily git push / pull Sync with remote
Branch git checkout -b <name> Create + switch
Branch git switch -c <name> Create + switch (modern)
Merge git merge <branch> Combine branches
Merge git rebase <branch> Rewrite onto branch
Undo git revert <commit> Safe public undo
Undo git reset --soft HEAD~1 Undo commit, keep staged
Remote git fetch Download without merge
Remote git push --force-with-lease Safe force push
Advanced git stash push -m 'msg' Shelve work temporarily
Advanced git cherry-pick <commit> Copy one commit
Advanced git bisect start Binary search for bugs
Advanced git reflog Local undo history

Frequently Asked Questions

What’s the difference between git pull and git fetch?

git fetch downloads new commits from the remote without touching your working directory. It’s always safe. git pull runs git fetch followed by git merge (or git rebase with --rebase). Use fetch when you want to inspect changes before integrating them. Use pull when you trust the incoming changes.

How do I undo the last git commit?

Use git reset --soft HEAD~1 to undo the commit while keeping all changes staged. Use git reset --mixed HEAD~1 (the default) to undo and unstage. Use git commit --amend to edit the last commit message or add files. If the commit is already pushed, use git revert instead to avoid rewriting shared history.

Should I use merge or rebase?

It depends on your team’s convention. Merge preserves the full branch history and is safer for shared branches. Rebase creates a cleaner, linear history but rewrites commit hashes. A popular middle ground: rebase locally to clean up your feature branch, then merge into main with --no-ff. According to GitKraken’s 2023 report, 75% of teams use merge-based workflows (GitKraken, 2023).

How do I recover a deleted branch?

Use git reflog to find the last commit on the deleted branch, then git checkout -b branch-name HEAD@{n} to recreate it. Reflog entries persist for 90 days by default, so you have a generous window. This works even after git branch -D.

What does git reset —hard actually do?

It moves your branch pointer to the specified commit, updates the staging area to match, and overwrites your working directory. Any uncommitted changes are permanently destroyed. Committed work can still be recovered via git reflog, but unstaged modifications are gone for good. Always run git stash before reset --hard if you’re unsure.

Git is deep. You won’t memorize all of this, and that’s fine. The daily commands become muscle memory within a week. The advanced ones are here for when you need them. Bookmark this page and come back when things get weird.