Hello, I'm Shrijith Venkatramana. I’m building LiveReview, a private AI code review tool that runs on your LLM key (OpenAI, Gemini, etc.) with highly competitive pricing -- built for small teams. Do check it out and give it a try!
In this post, we'll explore advanced commands that can clean up your history, debug issues faster, and handle complex workflows. No fluff—just practical details, examples, and tips to level up your Git game. Let's jump in.
Why Go Beyond Basic Git Commands?
Git's core commands like commit
, push
, and pull
get the job done for simple projects, but advanced ones shine in team settings or large codebases. They help avoid messy histories, recover from mistakes, and isolate changes without breaking things.
For instance, imagine a feature branch that's diverged wildly from main. Instead of a tangled merge, advanced tools let you rewrite history cleanly. Key benefit: These commands reduce conflicts and make code reviews easier.
A quick table of when to use advanced vs basic:
Scenario | Basic Command | Advanced Alternative |
---|---|---|
Combining branches | git merge |
git rebase for linear history |
Debugging | Manual checks |
git bisect for automated bug hunting |
Recovering work | None built-in |
git reflog to undo deletions |
Check out the official Git documentation for the full command reference—it's a solid starting point.
Rebasing Branches: Keeping History Linear and Clean
Rebasing moves your branch's commits onto another branch, creating a straight-line history instead of merge commits. It's great for feature branches before merging to main.
Bold tip: Always rebase on a clean working directory to avoid conflicts.
Example: Suppose you have a feature branch off main, and main has new commits.
# Create a repo and main branch
git init my-repo
cd my-repo
echo "Initial content" > file.txt
git add file.txt
git commit -m "Initial commit"
# Create feature branch
git checkout -b feature
echo "Feature change" >> file.txt
git commit -am "Add feature"
# Switch back to main and add a change
git checkout main
echo "Main update" >> file.txt
git commit -am "Update on main"
# Now rebase feature onto main
git checkout feature
git rebase main
# Output after rebase (as comment):
# Current branch feature is up to date. (if no conflicts)
# file.txt now has: Initial content\nMain update\nFeature change
If conflicts arise, resolve them in the editor, then git rebase --continue
. Use this over merge when you want a tidy log.
Interactive Rebase: Rewriting Commit History Like a Pro
Interactive rebase lets you edit, squash, or drop commits in your branch. It's perfect for consolidating small fixes into meaningful commits before pushing.
Key point: Run it on local branches only—never on shared ones to avoid rewriting public history.
Steps: Use git rebase -i HEAD~n
where n is the number of commits back.
Example: Cleaning up three messy commits.
# Setup repo
git init rebase-demo
cd rebase-demo
echo "Base" > doc.txt
git add doc.txt
git commit -m "Initial"
# Add commits
echo "Fix 1" >> doc.txt
git commit -am "Quick fix"
echo "Fix 2" >> doc.txt
git commit -am "Another fix"
echo "Feature" >> doc.txt
git commit -am "Add feature"
# Interactive rebase last 3 commits
git rebase -i HEAD~3
# In the editor, change to:
# pick <hash> Quick fix
# squash <hash> Another fix
# pick <hash> Add feature
# After saving and editing message, git log --oneline shows:
# <new-hash> Add feature
# <new-hash> Quick fix (squashed with Another fix)
# <initial-hash> Initial
This makes your history readable. For more options like edit
or drop
, see the interactive prompt.
Hunting Bugs with Git Bisect: Binary Search for Commits
Git bisect automates finding the commit that introduced a bug by binary-searching your history. It's efficient for large repos.
Important: Mark good and bad commits accurately.
Process: Start with git bisect start
, tag bad and good points, then test midway commits.
Example: Simulating a bug in a script.
# Init repo
git init bisect-demo
cd bisect-demo
# Good commit
echo 'print("Hello")' > script.py
git add script.py
git commit -m "Good commit"
# More commits, one bad
echo 'print("Hello world")' > script.py
git commit -am "Still good"
echo 'print("Hello world!' > script.py # Bug: missing quote
git commit -am "Bad commit"
# Start bisect
git bisect start
git bisect bad # Current is bad
git bisect good <first-commit-hash> # Replace with actual hash from git log
# Git checks out midway; test with python script.py
# If error: git bisect bad
# If good: git bisect good
# Ends with: <bad-hash> is the first bad commit
# Then: git bisect reset
This can save hours in debugging. Link to Git bisect docs for advanced scripting.
Recovering from Mistakes: The Power of Git Reflog
Reflog tracks all HEAD movements, letting you recover deleted branches or undone commits. It's a safety net for "oops" moments.
Tip: Reflog is local-only, so use it before pushing changes.
View with git reflog
, then reset to a past state.
Example: Deleting a commit and recovering.
# Setup
git init reflog-demo
cd reflog-demo
echo "Content" > file.txt
git add file.txt
git commit -m "Commit 1"
echo "More" >> file.txt
git commit -am "Commit 2"
# Oops, reset hard to previous
git reset --hard HEAD~1 # Deletes Commit 2
# Check reflog
git reflog
# Shows: <hash> HEAD@{0}: reset: moving to HEAD~1
# <hash2> HEAD@{1}: commit: Commit 2
# Recover
git reset --hard <hash2> # Use the hash from reflog
# Now git log shows both commits again
Always check git reflog
after destructive commands.
Cherry-Picking Commits: Applying Changes Selectively
Cherry-pick applies a specific commit from one branch to another. Useful for hotfixes without merging everything.
Key warning: It can duplicate commits, so watch for conflicts.
Command: git cherry-pick <commit-hash>
.
Example: Picking a fix from feature to main.
# Init
git init cherry-demo
cd cherry-demo
echo "Base" > app.js
git add app.js
git commit -m "Initial"
# Feature branch
git checkout -b feature
echo "Feature code" >> app.js
git commit -am "Add feature"
echo "Fix bug" >> app.js
git commit -am "Bug fix" # This is the one to pick
# Back to main
git checkout main
# Cherry-pick the fix
git cherry-pick <bug-fix-hash> # Replace with hash from git log --oneline
# app.js now has "Base\nFix bug"
# git log shows the picked commit on main
Great for backporting fixes.
Advanced Stashing: Managing Work in Progress
Beyond basic git stash
, use options like --include-untracked
or apply to specific files. Pop multiple stashes with indexes.
Point: Stash is temporary—don't rely on it long-term.
Example: Stashing with message and applying selectively.
# Setup
git init stash-demo
cd stash-demo
echo "Tracked" > tracked.txt
git add tracked.txt
git commit -m "Initial"
echo "Change" >> tracked.txt
echo "Untracked" > untracked.txt
# Stash with untracked and message
git stash push -u -m "WIP changes"
# List stashes
git stash list
# stash@{0}: WIP changes
# Apply
git stash apply stash@{0}
# Or pop to remove from list
git stash pop stash@{0}
# Files restored, including untracked.txt
Use git stash show
to preview.
Working with Git Worktrees: Parallel Branches Without Switching
Worktrees let you checkout multiple branches in separate directories from one repo. Ideal for reviewing PRs or testing features side-by-side.
Benefit: No constant switching, keeps your main dir clean.
Create with git worktree add <path> <branch>
.
Example: Setting up two worktrees.
# Init
git init worktree-demo
cd worktree-demo
echo "Main" > file.txt
git add file.txt
git commit -m "On main"
git branch feature
# Add worktree for feature
git worktree add ../feature-worktree feature
# In ../feature-worktree
cd ../feature-worktree
echo "Feature" >> file.txt
git commit -am "Feature change"
# Back in main dir, git log doesn't show feature yet until fetch/pull
# But you can work in both dirs independently
Remove with git worktree remove <path>
. See Git worktree docs for pruning.
Integrating These Commands into Daily Workflows
To make advanced Git a habit, start small: Use rebase for personal branches, bisect for bugs in stable projects, and reflog as your undo button. Combine them—like cherry-picking after a bisect find—or use worktrees for multi-tasking. Track your history with git log --graph
to see improvements. Over time, these tools cut down on errors and speed up collaboration, turning Git from a chore into a powerful ally in your dev toolkit. Experiment in a test repo first to build confidence.
Top comments (0)