DEV Community

Alex Chen
Alex Chen

Posted on

Git Advanced: The Commands I Wish I Knew Earlier (2026)

Git Advanced: The Commands I Wish I Knew Earlier (2026)

Beyond add, commit, push. These commands save hours of frustration.

Interactive Staging

# Review every change before committing
git add -p

# This opens an interactive prompt for EACH changed hunk:
# y - stage this hunk
# n - don't stage
# s - split into smaller hunks
# e - edit the hunk manually
# q - quit

# Why this matters:
# → You made 3 unrelated changes in one file
# → add -p lets you commit them separately
# → Clean commit history = easier debugging, easier code review

# Stage a file piece by piece
git add -p feature.js
# (y/n/s/e for each change)

# Unstage a file
git restore --staged file.js    # Unstage but keep changes
git restore file.js              # Discard changes entirely (DANGEROUS!)

# Stash management
git stash                        # Save current changes temporarily
git stash push -m "WIP: auth feature"  # Stash with message
git stash list                   # List all stashes
git stash pop stash@{0}         # Apply and remove stash
git stash apply stash@{0}       # Apply but keep stash
git stash drop stash@{0}        # Remove stash without applying
git stash clear                 # Remove ALL stashes
Enter fullscreen mode Exit fullscreen mode

Commit History Magic

# View commit history (my favorite variations)
git log --oneline --graph -15
# * abc1234 (HEAD -> main) feat: add user auth
# * def5678 fix: resolve login bug
# | * ghi9012 (feature/login) feat: login flow
# |/

git log --oneline --all --graph
# See ALL branches and their relationship

git log --since="1 week ago" --author="you"
# Filter by date and author

git log -p                       # Show actual code changes
git log --stat                   # Show file change statistics

# Find the commit that introduced a bug
git bisect start                 # Start bisection
git bisect bad                   # Mark current commit as broken
git bisect good v1.0             # Mark known-good commit
# Git checks out middle commit → you test → mark good/bad
# Binary search narrows to the exact commit!
git bisect reset                 # Stop bisecting

# Find which commit changed a specific line
git log -L 10,20:src/auth.js    # History of lines 10-20
git blame src/auth.js            # Who changed what, when

# Pick specific commits (copy changes from one branch to another)
git cherry-pick abc1234           # Apply commit abc1234 to current branch
git cherry-pick abc1234 def5678   # Apply multiple commits

# Edit the LAST commit (fix typo, add forgotten file)
git commit --amend               # Modify last commit message + add staged changes
# ⚠️ Never amend pushed commits! Creates different history.

# Undo things safely
git revert abc1234               # Create NEW commit that undoes abc1234
# Safe: doesn't rewrite history, OK for shared branches

git reset --soft HEAD~1           # Undo last commit, keep changes staged
git reset --mixed HEAD~1          # Undo last commit, keep changes unstaged (default)
git reset --hard HEAD~1           # Undo last commit AND discard changes (DANGEROUS!)

# Recover from git reset --hard
git reflog                       # Shows ALL HEAD movements
git reset --hard HEAD@{1}         # Go back to previous state
Enter fullscreen mode Exit fullscreen mode

Branching Strategies

# Create and switch (the modern way)
git switch -c feature/user-auth   # New branch + switch to it
git switch main                     # Switch to main
git switch -                        # Switch to previous branch

# Rename current branch
git branch -m new-name

# Delete branch
git branch -d feature/old         # Safe: only if merged
git branch -D feature/old         # Force: even if not merged

# Track remote branch
git switch --track origin/feature/xyz

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

# Find merged branches (safe to delete)
git branch --merged main           # Branches already in main
git branch --no-merged main        # Branches NOT yet in main
Enter fullscreen mode Exit fullscreen mode

Rebase: Clean History

# ⚠️ GOLDEN RULE: Never rebase shared/public branches!
# Only rebase YOUR feature branch.

# Rebase onto latest main
git switch feature/my-feature
git fetch origin
git rebase origin/main
# Your feature commits now come AFTER latest main commits
# Resolves: "merge commit" clutter in history

# Interactive rebase (SUPER powerful)
git rebase -i HEAD~5               # Edit last 5 commits
# Opens editor with:
# pick abc1234 feat: add login
# pick def5678 fix: typo in login
# pick ghi9012 feat: add validation
# pick jkl3456 fix: edge case
# pick mno7890 refactor: clean up

# You can:
# pick     - Keep commit as-is
# squash   - Combine with previous commit
# fixup    - Combine (discard message)
# drop     - Remove commit entirely
# reword   - Change commit message
# edit     - Pause to amend the commit

# Example: Squash fixup commits into feature commits
# pick abc1234 feat: add login
# fixup def5678 fix: typo in login        ← merges into above
# pick ghi9012 feat: add validation
# fixup jkl3456 fix: edge case           ← merges into above
# pick mno7890 refactor: clean up
# → Result: 3 clean commits instead of 5 messy ones

# Abort a rebase gone wrong
git rebase --abort

# Continue after resolving conflicts
git rebase --continue
Enter fullscreen mode Exit fullscreen mode

Conflict Resolution

# When conflicts happen (during merge or rebase):

# 1. See what conflicts exist
git status
# both modified:   src/auth.js
# both modified:   src/utils.js

# 2. Open the files and look for conflict markers:
# <<<<<<< HEAD
# your version
# =======
# their version
# >>>>>>> feature-branch

# 3. Choose a resolution strategy:

# Strategy A: Use THEIR version entirely
git checkout --theirs src/auth.js
git add src/auth.js

# Strategy B: Use YOUR version entirely
git checkout --ours src/auth.js
git add src/auth.js

# Strategy C: Manual resolution (most common)
# Edit the file, remove conflict markers, keep what you want
# Then:
git add src/auth.js
git rebase --continue  # or git commit for merge

# 4. Use a merge tool (much easier than manual!)
git mergetool            # Opens VS Code/Beyond Compare/etc.

# Configure your tool:
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
Enter fullscreen mode Exit fullscreen mode

Worktree: Multiple Branches at Once

# Problem: You're on feature-A and need to fix a bug on feature-B
# Without worktree: stash → switch → fix → switch back → unstash
# With worktree: both branches checked out simultaneously!

git worktree add ../hotfix main
# Creates ../hotfix directory with main branch checked out
# Your original directory keeps feature-A

cd ../hotfix
# Work on the hotfix independently
git commit -m "hotfix: critical bug"
git push origin main

# When done:
cd ../original-project
git worktree remove ../hotfix

# List all worktrees
git worktree list
Enter fullscreen mode Exit fullscreen mode

Hooks: Automate Your Workflow

# Pre-commit hook: Run linter before every commit
# .git/hooks/pre-commit (make executable with chmod +x)
#!/bin/sh
# Run ESLint on staged files
npx eslint --staged
if [ $? -ne 0 ]; then
  echo "❌ ESLint found errors. Fix them before committing."
  exit 1
fi

# Pre-push hook: Run tests before pushing
#!/bin/sh
npm test
if [ $? -ne 0 ]; then
  echo "❌ Tests failed. Not pushing."
  exit 1
fi

# Install hooks automatically (with husky)
npx husky init
# Then add hooks:
echo "npx eslint ." > .husky/pre-commit
echo "npm test" > .husky/pre-push

# Commit-msg hook: Enforce conventional commits
#!/bin/sh
commit_msg=$(cat "$1")
if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore|perf)(\(.+\))?: "; then
  echo "❌ Use conventional commit format: type(scope): message"
  echo "   Types: feat, fix, docs, style, refactor, test, chore, perf"
  exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Searching Git History

# Find commits by message content
git log --all --grep="password" --oneline

# Find commits that changed a specific word
git log -S "password" --oneline
# "pickaxe" search: finds commits that added/removed the string

# Find which commit last modified a function
git log -L :functionName:src/file.js

# Show diff between branches
git diff main...feature-branch    # Changes on feature branch since diverging
git diff main feature-branch      # All differences between branches

# Show changes staged for next commit
git diff --staged

# Show only filenames that changed
git diff --name-only HEAD~3

# Beautiful patch output (for code review)
git format-patch HEAD~1..HEAD      # Generate patch file
git send-email *.patch            # Email patches (for mailing list projects)
Enter fullscreen mode Exit fullscreen mode

Which git command here will you use tomorrow? What's your most-used git trick?

Follow @armorbreak for more practical developer guides.

Top comments (0)