Advanced Git: Beyond the Basics
Git is far more powerful than most developers realize. While most users know the basics of commit, push, and pull, mastering Git’s advanced features can significantly improve your workflow and help you recover from complex situations.
This guide covers advanced Git techniques that will help you work more efficiently, maintain cleaner histories, and collaborate more effectively with teams.
Interactive Staging
When you have multiple changes in a file but only want to commit some of them, interactive staging allows you to select specific hunks.
git add -p filename
Git will show each change and prompt you with options:
y- stage this hunkn- skip this hunks- split into smaller hunkse- manually edit the hunkq- quit
This is particularly useful when you’ve made multiple unrelated changes to the same file and want to create atomic commits.
Rewriting History with Interactive Rebase
Interactive rebase is one of Git’s most powerful features. It allows you to modify commits in your branch before pushing.
git rebase -i HEAD~5
This opens an editor showing the last 5 commits:
pick abc1234 First commit
pick def5678 Second commit
pick ghi9012 Third commit
Available commands:
| Command | Action |
|---|---|
| pick | Use commit as-is |
| reword | Change commit message |
| edit | Stop to amend the commit |
| squash | Merge into previous commit |
| fixup | Like squash but discard message |
| drop | Remove commit entirely |
Squashing Commits
To combine multiple commits into one:
pick abc1234 Add user authentication
squash def5678 Fix typo in auth
squash ghi9012 Add missing import
This creates a single, clean commit from three messy ones.
Reordering Commits
Simply change the order of lines in the editor:
pick ghi9012 Third commit
pick abc1234 First commit
pick def5678 Second commit
Be cautious when reordering commits that depend on each other.
Finding Bugs with Bisect
Git bisect performs a binary search through your commit history to find the commit that introduced a bug.
# Start bisect
git bisect start
# Mark current commit as bad
git bisect bad
# Mark a known good commit
git bisect good v1.0.0
Git will checkout commits for you to test. After each test:
# If the bug is present
git bisect bad
# If the bug is not present
git bisect good
Git will eventually identify the exact commit that introduced the bug.
Automated Bisect
If you have a test script that returns 0 for good and non-zero for bad:
git bisect start HEAD v1.0.0
git bisect run ./test-script.sh
Git will automatically run the script on each commit and find the problematic one.
Stashing Work
Stash allows you to save uncommitted changes without committing them.
# Save current changes
git stash
# Save with a message
git stash save "Work in progress on feature X"
# List all stashes
git stash list
# Apply most recent stash
git stash pop
# Apply specific stash
git stash apply stash@{2}
# Create a branch from stash
git stash branch new-branch stash@{0}
Partial Stashing
Stash only some files:
git stash push -m "Partial stash" file1.py file2.py
Stash interactively:
git stash -p
Working with Remotes
Multiple Remotes
You can have multiple remotes for different purposes:
# Add upstream remote (original repo)
git remote add upstream https://github.com/original/repo.git
# Fetch from upstream
git fetch upstream
# Merge upstream changes
git merge upstream/main
Tracking Branches
Create a local branch that tracks a remote branch:
git checkout -b feature-branch origin/feature-branch
# Or with newer Git versions
git switch -c feature-branch origin/feature-branch
Reflog: Your Safety Net
The reflog records every change to HEAD, even ones that don’t appear in normal history.
git reflog
Output:
abc1234 HEAD@{0}: commit: Add new feature
def5678 HEAD@{1}: checkout: moving from main to feature
ghi9012 HEAD@{2}: reset: moving to HEAD~3
Recovering Lost Commits
If you accidentally reset or deleted commits:
# Find the commit in reflog
git reflog
# Recover it
git checkout -b recovery-branch abc1234
Cherry-Pick
Apply specific commits from another branch:
# Apply single commit
git cherry-pick abc1234
# Apply multiple commits
git cherry-pick abc1234 def5678
# Apply range of commits
git cherry-pick abc1234..ghi9012
Useful for backporting fixes to maintenance branches.
Worktrees
Work on multiple branches simultaneously without stashing:
# Create a new worktree
git worktree add ../project-hotfix hotfix-branch
# List worktrees
git worktree list
# Remove worktree
git worktree remove ../project-hotfix
Each worktree is a separate directory with its own working copy.
Hooks
Git hooks are scripts that run at specific points in the Git workflow.
Location: .git/hooks/
Common hooks:
| Hook | Trigger |
|---|---|
| pre-commit | Before commit is created |
| commit-msg | After commit message is entered |
| pre-push | Before push to remote |
| post-merge | After merge completes |
Example: Pre-commit Hook
Create .git/hooks/pre-commit:
#!/bin/bash
# Run linter before commit
if ! npm run lint; then
echo "Linting failed. Commit aborted."
exit 1
fi
Make it executable:
chmod +x .git/hooks/pre-commit
Aliases
Create shortcuts for common commands in ~/.gitconfig:
[alias]
st = status
co = checkout
br = branch
ci = commit
lg = log --oneline --graph --decorate
unstage = reset HEAD --
last = log -1 HEAD
amend = commit --amend --no-edit
Usage:
git lg
git st
git amend
Cleaning Up
Remove Untracked Files
# Preview what will be deleted
git clean -n
# Delete untracked files
git clean -f
# Delete untracked files and directories
git clean -fd
# Delete ignored files too
git clean -fdx
Prune Remote Branches
# Remove references to deleted remote branches
git fetch --prune
# Or configure automatic pruning
git config --global fetch.prune true
Submodules
Include other repositories within your repository:
# Add submodule
git submodule add https://github.com/user/repo.git path/to/submodule
# Clone repo with submodules
git clone --recurse-submodules https://github.com/user/main-repo.git
# Update submodules
git submodule update --remote
Best Practices
Commit Messages
Write clear, descriptive commit messages:
Short summary (50 chars or less)
More detailed explanation if necessary. Wrap at 72 characters.
Explain what and why, not how. The code shows how.
- Use bullet points for multiple changes
- Reference issues: Fixes #123
Branch Naming
Use consistent naming conventions:
feature/user-authentication
bugfix/login-error
hotfix/security-patch
release/v2.0.0
Keep History Clean
- Squash work-in-progress commits before merging
- Use meaningful commit messages
- Avoid committing generated files
- Use
.gitignoreproperly
Troubleshooting
Undo Last Commit (keep changes)
git reset --soft HEAD~1
Undo Last Commit (discard changes)
git reset --hard HEAD~1
Fix Commit to Wrong Branch
# Save the commit hash
git log -1
# Reset current branch
git reset --hard HEAD~1
# Switch and apply
git checkout correct-branch
git cherry-pick <commit-hash>
Resolve Merge Conflicts
# See conflicting files
git status
# After resolving manually
git add resolved-file.py
git commit
Conclusion
Mastering these advanced Git techniques will make you more efficient and confident when working with version control. Practice these commands in a test repository before using them on important projects.
Key takeaways:
- Interactive rebase keeps history clean
- Bisect automates bug hunting
- Reflog is your safety net
- Hooks automate quality checks
- Aliases save time
The more comfortable you become with these tools, the more naturally they’ll integrate into your daily workflow.