Bitdoze Logo

100+ Git Commands Every Developer MUST Know (2026 Guide)

Master 100+ Git commands every developer needs, from git init to git worktree. The ultimate Git cheat sheet covering version control, branching, and modern Git workflows.

DragosDragos61 min read
100+ Git Commands Every Developer MUST Know (2026 Guide)

Git is the backbone of modern version control. Every team I’ve worked with, from solo side projects on a cheap VPS to large-scale CI/CD pipelines, runs on Git. This guide covers 100+ Git commands from basics through advanced workflows, updated for 2026 (Git 2.55, with Git 3.0 on the horizon).

Whether you’re learning Git for the first time or looking for a bookmarkable cheat sheet, this article has you covered. I’ve organized the commands so you can jump to any section and find what you need. If you’re setting up a full dev environment, you’ll also want to check out essential Linux commands and Docker commands every developer should know. These pair well with Git for any development workflow. If you use AI coding tools that integrate with Git, the worktree and automation sections will be especially useful.

  • Basic Git operations: init, clone, add, commit, config
  • Modern branch management with git switch (replaces git checkout)
  • git restore for discarding changes safely
  • git worktree for parallel branch workflows
  • Advanced debugging with git bisect run and git range-diff
  • Repository maintenance with git maintenance and git fsck
  • CI/CD automation commands and scripting snippets
  • Git 3.0 readiness: SHA-256, reftable, and what’s breaking

Section 1: Basic Git Commands

These are the commands you’ll use every day. Master these first.

1.1 git init

Initializes a new Git repository. Creates the .git directory with all the metadata Git needs to track changes.

Example Usage:

mkdir my_project
cd my_project
git init
# Initialized empty Git repository in /path/to/my_project/.git/

Verify: Run git status. You should see “On branch main” (or master, depending on your default branch config) with no commits yet.

1.2 git clone

Creates a local copy of a remote repository.

Example Usage:

git clone https://github.com/user/repository.git
# Cloning into 'repository'...
# remote: Enumerating objects: 10, done.
# remote: Counting objects: 100% (10/10), done.
# remote: Compressing objects: 100% (8/8), done.
# remote: Total 10 (delta 2), reused 10 (delta 2), pack-reused 0
# Unpacking objects: 100% (10/10), done.

Verify: ls -la .git/ should show the repository structure. For extra safety, run git fsck to verify integrity.

For shallow and partial clones (useful on metered VPS or in CI), see Section 3.5.

1.3 git status

Shows the current state of the working directory and staging area.

Example Usage:

git status
# On branch main
# Your branch is up to date with 'origin/main'.
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#     newfile.txt
#
# nothing added to commit but untracked files present (use "git add" to track)

This is the command I run most often. Use it before every commit to make sure you’re staging exactly what you think you are.

1.4 git add

Adds file contents to the staging area for the next commit.

Example Usage:

# Stage a single file
git add newfile.txt

# Stage all changes
git add .

# Stage interactively (pick hunks)
git add -p

git add -p is worth learning early. It lets you stage parts of a file, which leads to cleaner commits.

1.5 git commit

Records staged changes as a new commit.

Example Usage:

git commit -m "Add newfile.txt"
# [main 1a2b3c4] Add newfile.txt
#  1 file changed, 1 insertion(+)
#  create mode 100644 newfile.txt

Amend the last commit (before you’ve pushed):

git commit --amend -m "Updated commit message"

1.6 git config

Configures Git settings. In Git 2.46+ (July 2024), there’s a cleaner subcommand-based syntax:

Git 2.46 config subcommands

The new git config set/get/list/unset syntax is cleaner and easier to read. The old --global/--get flags still work, Git maintains backward compatibility. But if you’re teaching new developers, use the subcommand form. Git 3.0 will lean further in this direction.

1.7 git grep

Searches tracked files for a pattern. Faster than grep -r because it operates on the Git index.

Example Usage:

# Search for "TODO" in all tracked files
git grep "TODO"

# Search with line numbers
git grep -n "function_name"

# Search in a specific commit
git grep "pattern" HEAD~3

# Case-insensitive search
git grep -i "error"

1.8 git rm

Removes files from the working directory and staging area.

Example Usage:

# Remove a tracked file
git rm oldfile.txt

# Remove from tracking but keep the file on disk
git rm --cached secret.env

The --cached flag is useful when you accidentally committed a file that should be in .gitignore.

1.9 git mv

Moves or renames a tracked file.

Example Usage:

git mv old_name.txt new_name.txt

This is equivalent to mv old_name.txt new_name.txt && git add new_name.txt && git rm old_name.txt, but cleaner.


Section 2: Branching and Merging

Branching lets you work on features, fixes, and experiments in isolation. This section uses the modern git switch as the primary command. If you’re still using git checkout for everything, read the legacy note in 2.3.

2.1 git branch

List, create, and delete branches.

Example Usage:

# List local branches
git branch
# * main
#   feature-branch

# List all branches (including remote)
git branch -a

# Create a new branch
git branch new-feature

# Force-delete an unmerged branch
git branch -D experimental

2.2 git switch

The modern way to switch and create branches. Introduced in Git 2.23 (August 2019).

Example Usage:

# Switch to an existing branch
git switch main

# Create and switch to a new branch
git switch -c new-feature

# Switch to the previous branch
git switch -

# Create a branch from a specific commit
git switch -c hotfix abc1234

Why git switch over git checkout

git checkout does two unrelated things: switch branches and restore files. This causes confusion and mistakes. git switch handles branch operations only, making intent clear. Git 3.0 will strongly recommend git switch and git restore over git checkout.

2.3 git checkout (legacy)

Still works, but git switch (branches) and git restore (files) are the recommended replacements since Git 2.23.

# Legacy: switch branch (use git switch instead)
git checkout new-feature

# Legacy: create and switch (use git switch -c instead)
git checkout -b new-feature

# Legacy: restore file (use git restore instead)
git checkout -- file.txt

git checkout conflates two operations

Using git checkout for both branch switching and file restoration is a common source of mistakes. git checkout -- file.txt discards uncommitted changes to a file, while git checkout main switches branch. The same command, completely different outcomes. Use git switch and git restore to make your intent explicit.

2.4 git merge

Combines changes from one branch into the current branch.

Example Usage:

# Merge a branch into current branch
git merge feature-branch

# Merge with an explicit merge commit (even if fast-forward is possible)
git merge --no-ff feature-branch -m "Merge feature-branch"

# Abort a merge with conflicts
git merge --abort

Verify: git log --oneline --graph -10 to see the merge in the commit topology.

Failure mode (merge conflicts): When Git can’t auto-merge, it marks conflicts in the files. Edit the conflicted files, then git add them and git commit. Or git merge --abort to back out completely.

2.5 git rebase

Reapplies commits on top of another base. Creates a linear history (no merge commits).

Example Usage:

# Rebase current branch onto main
git rebase main

# Interactive rebase (squash, reorder, edit commits)
git rebase -i HEAD~5

# Abort a rebase
git rebase --abort

# Continue after resolving conflicts
git rebase --continue

Don't rebase shared branches

Never rebase commits that have been pushed and shared with others. Rebase rewrites commit hashes, which will cause conflicts for anyone else working on those commits. Rebase is safe for local-only branches.

2.6 git worktree

Lets you check out multiple branches simultaneously in separate directories, all linked to the same repository. No need to stash or clone twice.

Example Usage:

# Create a worktree for main at ../hotfix
git worktree add ../hotfix main

# Create a worktree with a new branch
git worktree add -b hotfix-123 ../hotfix-123 main

# List all worktrees
git worktree list
# /home/user/project          abc1234 [main]
# /home/user/hotfix           def5678 [main]

# Remove a worktree
git worktree remove ../hotfix

# Clean up stale worktree metadata
git worktree prune

Worktrees are underrated

Worktrees let you work on a feature branch while quickly fixing a bug on main, no stashing, no second clone. They’re also useful for AI coding tools that can work on parallel feature branches. Each worktree shares the same .git database, so you avoid the disk cost of a full clone. I use worktrees whenever I need to context-switch between branches.

Failure mode (detached HEAD): Running git switch to a specific commit hash (not a branch name) puts you in detached HEAD state. Your work isn’t on any branch. Fix it with:

git switch -c new-branch-name

This saves your work onto a proper branch.


Section 3: Remote Repository Commands

Working with remote repositories, GitHub, GitLab, Gitea, Forgejo, or any Git server. If you’re pushing over SSH, make sure you have your SSH key setup for GitHub configured first.

3.1 git remote

Manages remote repository connections.

Example Usage:

# List remotes
git remote
# origin

# List remotes with URLs
git remote -v
# origin  https://github.com/user/repo.git (fetch)
# origin  https://github.com/user/repo.git (push)

# Add a remote
git remote add upstream https://github.com/original/repo.git

# Remove a remote
git remote remove upstream

# Change a remote URL
git remote set-url origin git@github.com:user/repo.git

# Prune stale remote-tracking branches
git remote prune origin

3.2 git fetch

Downloads objects and refs from a remote repository without merging.

Example Usage:

# Fetch from origin
git fetch

# Fetch from a specific remote
git fetch upstream

# Fetch and prune deleted remote branches
git fetch --prune

# Fetch a specific branch
git fetch origin feature-branch

I use git fetch --prune as a habit. It cleans up remote-tracking branches that have been deleted on the server.

3.3 git pull

Fetches and merges changes from a remote branch. Equivalent to git fetch followed by git merge.

Example Usage:

# Pull and merge
git pull

# Pull with rebase instead of merge (cleaner history)
git pull --rebase

# Pull from a specific remote and branch
git pull upstream main

3.4 git push

Uploads local commits to a remote repository.

Example Usage:

# Push current branch to origin
git push

# Push and set upstream tracking
git push -u origin new-feature

# Delete a remote branch
git push --delete origin old-branch

3.5 git push –force-with-lease (safe force push)

Never use --force on shared branches

git push --force overwrites the remote branch unconditionally. If someone pushed commits after your last fetch, those commits are gone. Always use --force-with-lease. It checks that the remote ref hasn’t changed since your last fetch, and aborts if it has.

Example Usage:

# Safe force push (checks remote state first)
git push --force-with-lease origin main

# Even safer (also checks local reflog)
git push --force-with-lease --force-if-includes origin main

--force-with-lease has saved me more than once. It’s the difference between “I rewrote history safely” and “I just destroyed my teammate’s work.”

3.6 Shallow and partial clones

When you’re on a metered VPS, running CI, or working with a huge repo, full clones waste bandwidth and disk. These flags help.

Example Usage:

# Shallow clone  -  only latest commit (great for CI)
git clone --depth 1 https://github.com/user/large-repo.git

# Partial clone  -  download blobs on demand (saves disk)
git clone --filter=blob:none https://github.com/user/large-repo.git

# Convert a shallow clone to full history later
git fetch --unshallow

Shallow clones for CI/CD

A --depth 1 clone downloads only the latest commit and tree - no history. This cuts clone time dramatically for large repos. In CI pipelines where you only need the latest code for building/testing, shallow clones are the default for a reason. For VPS deployments, partial clones (--filter=blob:none) are a good middle ground: you get history but download file contents on demand.


Section 4: Viewing History and Comparing Changes

Understanding what happened and when. These commands are your time machine.

4.1 git log

Shows commit history. The default output is verbose - learn the flags that matter.

Example Usage:

# Basic log
git log

# One-line format (my daily driver)
git log --oneline

# Visual branch graph
git log --graph --oneline --all

# Limit output
git log -10

# Show files changed per commit
git log --stat

# Search for commits that introduced/removed a string (pickaxe)
git log -S"buggy_function"

# Trace the history of a specific function
git log -L :function_name:file.c

# Show commits since a date
git log --since="2026-01-01"

# Show commits by author
git log --author="Dragos"

# Cap graph lane width (Git 2.55+)
git log --graph --oneline --all --graph-lane-limit=5

Pickaxe search is powerful

git log -S"string" finds every commit that added or removed that string. It’s like git blame but across the entire history. I use this when tracking down when a bug was introduced. For regex matching, use git log -G"pattern" instead.

4.2 git diff

Shows changes between commits, branches, or the working directory.

Example Usage:

# Changes not yet staged
git diff

# Changes staged for commit
git diff --cached

# Diff between two branches
git diff main..feature-branch

# Summary of changes (files and line counts)
git diff --stat

# Diff for a specific file
git diff HEAD -- file.txt

4.3 git show

Displays details of a specific commit (diff, message, author).

Example Usage:

# Show the latest commit
git show

# Show a specific commit
git show abc1234

# Show only the files changed
git show --stat abc1234

4.4 git blame

Shows who last modified each line of a file and when.

Example Usage:

# Show blame for a file
git blame file.txt

# Blame a specific line range
git blame -L 10,20 file.txt

# Use a different diff algorithm (Git 2.54+)
git blame --diff-algorithm=patience file.txt

4.5 git shortlog

Summarizes git log output by author. Useful for seeing contributor activity.

Example Usage:

# Summary by author
git shortlog -sn

# Summary since a date
git shortlog -sn --since="2026-01-01"

4.6 git describe

Generates a human-readable identifier from the nearest tag.

Example Usage:

git describe --tags
# v1.2.3-14-gabc1234
# (14 commits after tag v1.2.3, commit starting with abc1234)

Use this in build scripts for versioning: the output is always unique and tells you exactly how far you are from the last release.

4.7 git range-diff

Compares two versions of a commit range. The primary use case: verifying a rebase didn’t lose or alter anything.

Example Usage:

# Compare old and new branch versions after rebase
git range-diff origin/main..old-branch origin/main..new-branch

Verify after rebase: Run git range-diff after rebasing to confirm that each commit’s diff is the same (or intentionally different). If commits are missing or their diffs changed unexpectedly, something went wrong.


Section 5: Undoing Changes and Fixing Mistakes

Everyone makes mistakes. These commands are your safety net.

5.1 git reset

Moves HEAD and optionally modifies the staging area and working directory.

Example Usage:

# Soft reset  -  keep changes staged
git reset --soft HEAD~1

# Mixed reset (default)  -  keep changes unstaged
git reset HEAD~1

# Hard reset  -  discard everything since that commit
git reset --hard HEAD~1

git reset --hard is destructive

git reset --hard discards uncommitted changes and moves HEAD. But commits aren’t gone immediately - they’re still in the reflog. If you accidentally hard reset, see the recovery section below.

Recovering from git reset --hard

If you just ran git reset --hard and lost commits, they’re still in the reflog:

# View the reflog (your safety net)
git reflog
# abc1234 HEAD@{0}: reset: moving to HEAD~3
# def5678 HEAD@{1}: commit: Important work here

# Restore to the commit before the reset
git reset --hard HEAD@{1}
# or
git reset --hard def5678

The reflog keeps entries for 90 days by default. As long as the garbage collector hasn’t run, you can recover.

5.2 git restore

The modern way to discard working directory changes or unstage files. Replaces git checkout -- <file>.

Example Usage:

# Discard changes to a file (restore to last committed state)
git restore file.txt

# Unstage a file (move it out of the staging area)
git restore --staged file.txt

# Restore a file from a specific commit
git restore --source=HEAD~2 file.txt

# Restore all files in the working directory
git restore .

5.3 git revert

Creates a new commit that undoes a specific commit. Unlike reset, it doesn’t rewrite history.

Example Usage:

# Revert a specific commit
git revert abc1234

# Revert without committing (stage the revert)
git revert --no-commit abc1234

Use git revert on shared branches where you can’t rewrite history. Use git reset on local-only branches.

5.4 git clean

Removes untracked files from the working directory.

Example Usage:

# Dry run  -  show what would be deleted
git clean -n

# Remove untracked files
git clean -f

# Remove untracked files and directories
git clean -fd

# Include ignored files too
git clean -fdx

Always run with -n first to preview. There’s no undo for git clean.

5.5 git stash

Temporarily shelves changes so you can switch branches or work on something else.

Example Usage:

# Stash current changes
git stash

# Stash with a descriptive message
git stash push -m "WIP: login feature"

# List all stashes
git stash list
# stash@{0}: On main: WIP: login feature
# stash@{1}: On main: experimental changes

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

# Apply and remove the most recent stash
git stash pop

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

# Create a branch from a stash
git stash branch new-feature-branch stash@{0}

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

# Delete all stashes
git stash clear

# Show stash contents
git stash show -p stash@{0}

5.6 git cherry-pick

Applies a specific commit from one branch to the current branch.

Example Usage:

# Cherry-pick a single commit
git cherry-pick abc1234

# Cherry-pick without committing
git cherry-pick --no-commit abc1234

# Cherry-pick a range of commits
git cherry-pick abc1234..def5678

Section 6: Advanced Git Commands

Debugging, automation, and power-user workflows.

6.1 git bisect

Uses binary search to find the commit that introduced a bug.

Manual bisect:

git bisect start
git bisect bad          # current commit is broken
git bisect good v1.0    # this tag/commit was working

# Git checks out a middle commit. Test it, then:
git bisect good         # this commit works
# or
git bisect bad          # this commit is broken

# Git narrows down until it finds the bad commit
# When done:
git bisect reset

Automated bisect with a script:

git bisect start HEAD v1.0
git bisect run ./test-script.sh

The test script should exit 0 for “good” and non-zero for “bad.” Git will automatically check out commits and run the script until it finds the first bad commit. This is the real power of bisect - let the computer do the work.

git bisect run saves hours

Write a test script that reproduces the bug, make it executable, and hand it to git bisect run. It will binary-search through hundreds of commits in minutes. I’ve used this to track down regressions across months of commit history.

6.2 git tag

Creates named references to specific commits (typically for releases).

Example Usage:

# Lightweight tag
git tag v1.0.0

# Annotated tag (recommended  -  includes metadata)
git tag -a v1.0.0 -m "Release 1.0.0"

# Tag a specific commit
git tag -a v1.0.0 abc1234

# List tags
git tag

# List tags with messages
git tag -n

# Push tags to remote
git push origin v1.0.0

# Push all tags
git push origin --tags

6.3 git submodule

Manages external repositories embedded in your repository.

Example Usage:

# Add a submodule
git submodule add https://github.com/user/library.git libs/library

# Initialize submodules after cloning
git submodule init
git submodule update

# Or combine both
git submodule update --init --recursive

# Update submodules to latest remote commits
git submodule update --remote

6.4 git archive

Creates a tar or zip archive of a repository at a specific point.

Example Usage:

# Create a tar archive of HEAD
git archive --format=tar HEAD > project.tar

# Create a zip of a specific tag
git archive --format=zip v1.0.0 > project-v1.0.0.zip

# Archive specific paths only
git archive --format=tar HEAD src/ > src-only.tar

6.5 git reflog

Shows a log of where HEAD has been. Your safety net for recovery operations.

Example Usage:

# View reflog
git reflog
# abc1234 HEAD@{0}: commit: Latest change
# def5678 HEAD@{1}: reset: moving to HEAD~1
# ghi9012 HEAD@{2}: commit: Important work

# Reset to a reflog entry
git reset --hard HEAD@{2}

6.6 git notes

Attaches metadata to commits without rewriting history. Think of it as comments on commits.

Example Usage:

# Add a note to a commit
git notes add -m "Reviewed-by: Jane" abc1234

# View notes for a commit
git notes show abc1234

# List all notes
git notes list

# Push notes to remote (not pushed by default)
git push origin refs/notes/commits

Use cases: attaching CI results, code review metadata, or test coverage info to specific commits.

6.7 git commit –fixup and –autosquash

Clean up commit history before merging.

Example Usage:

# Create a fixup commit targeting a specific commit
git commit --fixup=abc1234

# Interactive rebase that automatically squashes fixup commits
git rebase -i --autosquash main

This is my preferred workflow for pull requests: make fixup commits as reviewers request changes, then squash them into the right places before merging.

6.8 git bundle

Creates a portable archive of a repository that can be cloned. Useful for air-gapped environments, offline transfers, or backups.

Example Usage:

# Create a bundle of all branches
git bundle create repo.bundle --all

# Create a bundle of specific branches
git bundle create repo.bundle main feature-branch

# Clone from a bundle
git clone repo.bundle new-repo

# Verify a bundle is valid
git bundle verify repo.bundle

6.9 git am

Applies patches from a mailbox (email-based workflows). Still used by the Linux kernel and other projects that rely on email-based code review.

Example Usage:

# Apply a patch file
git am < patch-file.patch

# Apply a series of patches from a directory
git am patches/*.patch

# Abort if something goes wrong
git am --abort

# Apply with 3-way merge (resolves more cases)
git am --3way < patch-file.patch

Section 7: Collaboration and Patch Workflows

Working with patches, email submissions, and code review.

7.1 git cherry

Finds commits that haven’t been applied upstream.

Example Usage:

# Show commits in the current branch not in upstream
git cherry upstream/main

# Verbose output with commit messages
git cherry -v upstream/main

7.2 git apply

Applies a patch created by git diff or git format-patch.

Example Usage:

# Verify a patch without applying
git apply --check changes.patch

# Apply a patch
git apply changes.patch

# Apply with reverse (undo a patch)
git apply -R changes.patch

Always run git apply --check first to verify the patch applies cleanly.

7.3 git format-patch

Creates patch files from commits. Each commit becomes a separate .patch file with the commit message.

Example Usage:

# Create patches for the last 3 commits
git format-patch -3

# Create patches for a range
git format-patch main..feature-branch

# Create patches in a directory
git format-patch -3 -o patches/

7.4 git send-email

Sends patch files via email. Used in projects that do email-based code review (Linux kernel, Git itself).

Example Usage:

# Send a patch series
git send-email patches/*.patch

# Send to a specific recipient
git send-email --to=maintainer@example.com patches/*.patch

7.5 git request-pull

Generates a pull request message for email-based workflows.

Example Usage:

git request-pull v1.0 https://github.com/user/repo.git main

Section 8: Repository Maintenance and Performance

Keep your repositories fast and healthy. Especially important if you’re hosting repos on a VPS with limited disk and I/O.

8.1 git gc

Garbage collection - cleans up unnecessary files and optimizes the repository.

Example Usage:

# Standard garbage collection
git gc

# Aggressive (slower but more thorough  -  use occasionally)
git gc --aggressive

# Auto-gc with higher thresholds (less frequent packing)
git gc --auto

Verify: Run git log -1 after gc to confirm the repo still works.

git gc --aggressive can be slow

--aggressive rewrites pack files for better compression. On large repos, this can take minutes to hours. Use it occasionally, not as a daily task. For routine maintenance, plain git gc or git maintenance is better.

8.2 git fsck

Verifies the integrity of the repository database.

Example Usage:

# Check for corrupt objects
git fsck

# Check and report dangling objects
git fsck --dangling

Run git fsck after a suspicious clone or when you suspect corruption. If it reports errors, re-clone from a known good source.

8.3 git maintenance

Schedules background tasks to keep repositories fast. Introduced in Git 2.30.

Example Usage:

# Enable background maintenance (schedules via cron/systemd)
git maintenance start

# Run maintenance tasks manually
git maintenance run

# Disable background maintenance
git maintenance stop

# Run a specific task
git maintenance run --task=commit-graph

git maintenance avoids auto-packing pauses

Without git maintenance, Git runs gc --auto during certain operations (push, merge, etc.), which can pause for seconds or minutes on large repos. With git maintenance start, background tasks run on a schedule so those operations stay fast. Since Git 2.54, geometric repacking is the default strategy - better performance for most repos.

8.4 git rerere

“Reuse recorded resolution” - remembers how you resolved a conflict and applies the same resolution automatically next time.

Example Usage:

# Enable rerere
git config set rerere.enabled true

# Once enabled, Git automatically records conflict resolutions
# and re-applies them during rebases or merges

If you rebase frequently or maintain long-lived branches, rerere saves significant time.

8.5 git count-objects

Shows disk usage of the Git object database.

Example Usage:

# Basic count
git count-objects

# Human-readable with verbose details
git count-objects -vH
# count: 0
# size: 0 bytes
# in-pack: 1523
# packs: 1
# size-pack: 2.34 MiB
# garbage: 0
# size-garbage: 0 bytes

Useful for monitoring repo size on VPS instances with limited disk.

8.6 git prune

Removes unreachable objects from the database. Normally handled by git gc, but useful for manual cleanup.

Example Usage:

# Dry run
git prune -n

# Prune unreachable objects
git prune

Section 9: Scripting and Automation Commands

Commands you’ll use in CI/CD pipelines, build scripts, and automation. If you’re writing deployment scripts or integrating Git into your CI pipeline, these are essential.

9.1 git rev-parse

Parses revision specifications. The go-to for extracting info in shell scripts.

Example Usage:

# Get full commit hash
git rev-parse HEAD
# a1b2c3d4e5f6...

# Get short hash
git rev-parse --short HEAD
# a1b2c3d

# Get current branch name
git rev-parse --abbrev-ref HEAD
# main

# Get the repository root directory
git rev-parse --show-toplevel
# /home/user/project

9.2 git rev-list

Lists commit objects in reverse chronological order.

Example Usage:

# Count total commits
git rev-list --count HEAD

# Count commits since a date
git rev-list --since="2026-01-01" --count HEAD

# List commits between two refs
git rev-list main..feature-branch

9.3 git ls-files / git ls-tree / git cat-file

Low-level inspection commands.

# List files in the index (staging area)
git ls-files

# List tree contents at a commit
git ls-tree HEAD

# Show object type and content
git cat-file -t HEAD    # "commit"
git cat-file -p HEAD    # commit details

# Show blob content
git cat-file -p HEAD:file.txt

9.4 CI/CD snippets

Copy-pasteable CI/CD Git snippets
# Get changed files in the last commit (for selective CI jobs)
git diff --name-only HEAD~1

# Generate version string from tags
git describe --tags --always

# List commits between deploys (for release notes)
git log --oneline <previous-deploy-ref>..<new-deploy-ref>

# Create a deploy artifact
git archive --format=tar HEAD | gzip > deploy.tar.gz

# Get the commit count since last tag (for build numbers)
git rev-list $(git describe --tags --abbrev=0)..HEAD --count

# Fast CI clone
git clone --depth 1 --branch main https://github.com/user/repo.git

# Verify repo integrity in CI
git fsck --no-dangling

Section 10: Modern Git: Switch, Restore, Worktrees, and Beyond

This section consolidates the modern Git features that have matured since 2019. If you’re still running Git workflows like it’s 2015, start here.

10.1 git sparse-checkout

Work with a subset of a large repository. Essential for monorepos.

Example Usage:

# Clone with sparse checkout
git clone --filter=blob:none --sparse https://github.com/large/repo.git
cd repo

# Set which directories you want
git sparse-checkout set src/frontend docs/

# Add more directories later
git sparse-checkout add src/shared/

# List current sparse-checkout paths
git sparse-checkout list

# Disable sparse-checkout (get everything)
git sparse-checkout disable

Combined with partial clone (--filter=blob:none), you only download the files you need. Great for monorepos where you only work on one service.

10.2 SSH commit signing

GPG signing has been the traditional way to sign commits, but SSH-based signing is much simpler to set up and is supported by GitHub, GitLab, and Gitea.

SSH signing is simpler: you already have the keys, no key management beyond what you use for push/pull, and no GPG agent to configure. If you’re starting fresh, use SSH.

10.3 git history command (Git 2.54+)

New in Git 2.54, the git history command simplifies interactive rebase workflows.

# Reword a commit message (replaces interactive rebase for simple edits)
git history reword HEAD~3

# Split a commit into multiple commits
git history split HEAD~2

# Create a fixup commit and prepare for autosquash
git history fixup HEAD~5

git history is experimental

The git history command is still experimental as of Git 2.55. It works, but the interface may change. If you need stable behavior, use git rebase -i for now. But keep an eye on this - it’s where Git is heading.

10.4 Config-based hooks (Git 2.54+)

Hooks can now be configured via git config instead of placing scripts in .git/hooks/. This makes hooks easier to share across a team.

# Set a hook via config
git config set core.hooksPath .githooks

Place your hook scripts in .githooks/ and commit that directory. Everyone who clones the repo gets the hooks automatically.

10.5 git stash export/import

Transfer stashes between repositories or machines.

# Export stash to a file
git stash export > stash.bundle

# Import in another repo
git stash import < stash.bundle

Zsh plugins for Git productivity

Shell plugins and aliases can speed up your Git workflow significantly. If you use Zsh, check out Zsh plugins for Git productivity for tab completion, prompt integration, and shortcut aliases.


Section 11: Git 3.0 - What’s Coming

Git 3.0 is targeting late 2026. Here’s what you need to know to prepare.

11.1 SHA-256 default hash algorithm

Git has used SHA-1 since its creation, but SHA-1 has known collision attacks (the SHAttered attack in 2017 made this practical). Git 3.0 will make SHA-256 the default for new repositories.

What changes:

  • Hash length goes from 40 hex characters to 64 hex characters
  • New repos created with Git 2.51+ already default to SHA-256
  • Existing SHA-1 repos continue to work (no forced migration)

The catch: GitHub, GitLab, and other forges don’t yet support SHA-256 repositories. The ecosystem needs to catch up before SHA-256 becomes practical for most teams.

11.2 Reftable reference backend

Reftable is a new format for storing Git references (branches, tags). It’s available today:

# Create a repo with reftable backend
git init --ref-format=reftable

Why it matters:

  • Up to 22x faster fetch and 18x faster push in repos with 10,000+ references
  • Atomic reference updates (no more partial writes on crash)
  • No more filesystem-level branch name conflicts (case-insensitive filesystems)
  • Smaller disk footprint for reference storage

For repos with many branches (monorepos, large teams), reftable is a significant improvement. If you’re self-hosting Git with Forgejo, check its reftable support status.

11.3 Rust build requirement

Git 3.0 will require Rust as a build dependency. This enables memory-safe implementations of performance-critical code paths. The Meson build system integration continues.

Impact: Most users won’t notice - they install Git from package managers. But building Git from source on platforms without Rust toolchains will require an extra step.

11.4 Breaking changes

  • git-whatchanged removed. Use git log --raw instead (same output, more flags).
  • git switch and git restore no longer experimental. Git 3.0 will strongly recommend them over git checkout. Start migrating now.
  • Various deprecated options removed. Check BreakingChanges.txt in the Git source for the full list.

Verify the Git 3.0 timeline

The late 2026 target is aspirational. Check git-scm.com for the latest status before relying on any Git 3.0 features in production.

Git 3.0 readiness checklist
  • Switch to git switch and git restore - stop using git checkout for branch/file operations
  • Use the new git config set/get/list syntax - the old flags still work but the new form is cleaner
  • Test git init --ref-format=reftable on a non-production repo to see if it works for your workflow
  • Update CI scripts to handle SHA-256 hashes (64 chars vs 40) if they parse commit hashes
  • Monitor your forge (GitHub, GitLab, Gitea) for SHA-256 repo support announcements
  • Keep Git updated - security fixes and features land in every release

Section 12: Security Essentials

Git security matters for every team. These commands and configs help protect your repository.

12.1 Verifying objects on fetch/push

Catches corrupted or malicious objects during transfer.

# Enable object verification for all fetches/pushes
git config set transfer.fsckObjects true

With this enabled, Git verifies the integrity of every object received from a remote. Enable it globally or per-repository.

12.2 Commit and tag verification

Verify that commits and tags are signed by trusted keys.

# Verify a commit's signature
git verify-commit abc1234

# Verify a tag's signature
git verify-tag v1.0.0

12.3 Keeping Git updated

Recent security vulnerabilities you should be aware of:

Update Git immediately if you're on an old version

CVE-2025-48384 (July 2025): Arbitrary file write on Linux/macOS via git clone. This is in the CISA KEV catalog - actively exploited. CVE-2024-50349 and CVE-2024-52006 (October 2024): Credential handling issues affecting all prior versions. Always upgrade to the latest stable Git release.

# Check your Git version
git --version

# Update on Ubuntu/Debian
sudo apt update && sudo apt install git

# Update on macOS
brew upgrade git

# Update on Fedora/RHEL
sudo dnf update git

Section 13: Quick Reference Table

Bookmark this section. Every command listed here works in Git 2.50+. Commands marked with ★ are especially worth learning.

Category Command What It Does
File operations git rm <file> Remove a tracked file
git rm --cached <file> Untrack a file (keep on disk)
git mv <old> <new> Rename/move a tracked file
git grep <pattern> Search tracked files
Staging git add -p Stage changes interactively (hunks)
git diff --cached Show staged changes
git restore --staged <file> Unstage a file
Commit git commit --amend Edit the last commit
git commit --fixup=<hash> Create a fixup commit ★
git rebase -i --autosquash Auto-squash fixup commits ★
Branching git branch -D <branch> Force-delete an unmerged branch
git switch - Switch to previous branch ★
git worktree add <path> <branch> Check out branch in new directory ★
git worktree list List all worktrees
git worktree remove <path> Remove a worktree
Remotes git remote prune origin Clean up stale remote-tracking refs
git fetch --prune Fetch and prune ★
git push --delete origin <branch> Delete a remote branch
git push --force-with-lease Safe force push ★
History git log --oneline --graph --all Visual branch map ★
git log -S"string" Find commits that changed a string ★
git log --follow <file> Follow file renames
git log -L :func:file Trace function history
git describe --tags Human-readable version string ★
git range-diff <old> <new> Verify rebase correctness ★
git shortlog -sn Commits per author
git blame -L 10,20 <file> Who changed lines 10–20
Undo git stash push -m "msg" Stash with a message
git stash pop Apply and remove stash ★
git stash branch <name> Create branch from stash
git stash show -p Show stash diff
git revert --no-commit <hash> Revert without committing
git clean -fd Remove untracked files + dirs
git merge --abort Abort a merge
git rebase --abort Abort a rebase
Security git verify-commit <hash> Verify commit signature
git verify-tag <tag> Verify tag signature
git config set transfer.fsckObjects true Verify objects on transfer ★
Maintenance git gc Garbage collect
git gc --aggressive Thorough repack (slow)
git fsck Verify repo integrity ★
git count-objects -vH Disk usage summary
git maintenance start Enable background maintenance ★
Low-level git rev-parse HEAD Get current commit hash
git rev-parse --abbrev-ref HEAD Get current branch name
git rev-list --count HEAD Count commits
git ls-files List files in index
git ls-tree HEAD List tree at commit
git cat-file -p <hash> Show object content
git hash-object <file> Compute blob hash
git update-index Register file in index
Networking git daemon Simple Git server
git update-server-info Update info for dumb HTTP servers
git bundle create <file> Pack repo into portable file ★
git clone <bundle> Clone from a bundle
Diff/merge tools git difftool Open diff in external tool
git mergetool Open merge tool for conflicts
Patches git am < patch Apply mailbox patch
git format-patch -N Create patches from last N commits
git send-email Send patches via email
Inspection git instaweb Browse repo in local gitweb
git notes add -m "text" Attach metadata to commit
git interpret-trailers Parse/add commit trailers
git rerere Reuse recorded resolutions ★

That’s 100+ commands covering every workflow from basic operations to advanced automation.


Conclusion

Git is one of those tools where knowing 15 commands well gets you through 90% of your day, but knowing 100+ gives you options when things go sideways or when you need to automate something.

  • git init / clone / status / add / commit - the daily workflow
  • git switch / restore - stop using git checkout for everything
  • git log –oneline –graph –all - always know where you are
  • git stash - context-switch without losing work
  • git rebase -i - clean up before merging
  • git reflog - your safety net when things go wrong
  • git push –force-with-lease - the only safe way to force push
  • git bisect run - automate bug hunting
  • git worktree - work on multiple branches at once
  • git maintenance start - keep repos fast automatically

If you’re building out your development environment, these companion guides are worth bookmarking:

Bookmark this Git cheat sheet

Table of Contents