Mastering Git: Advanced Workflows and Best Practices
Git is one of the most essential tools in a developer's toolkit. While basic git commands get you started, mastering advanced Git techniques can dramatically improve your productivity and collaboration effectiveness.
Git Flow vs GitHub Flow vs GitLab Flow
Understanding different branching strategies helps you choose the right workflow for your team:
Git Flow
# Initialize git flow
git flow init
# Start a new feature
git flow feature start new-feature
# Finish a feature
git flow feature finish new-feature
# Start a release
git flow release start 1.2.0
# Finish a release
git flow release finish 1.2.0
# Start a hotfix
git flow hotfix start critical-bug
git flow hotfix finish critical-bug
GitHub Flow (Simplified)
# Create and switch to feature branch
git checkout -b feature/user-authentication
# Make changes and commit
git add .
git commit -m "Add user authentication system"
# Push to remote
git push origin feature/user-authentication
# Create pull request (via GitHub UI)
# Merge via GitHub after review
# Delete branch after merge
git branch -d feature/user-authentication
Interactive Rebase: Cleaning Up History
Rewrite commit history for cleaner, more professional repositories:
# Interactive rebase for last 3 commits
git rebase -i HEAD~3
# Interactive rebase since a specific commit
git rebase -i abc123
# Common rebase commands:
# pick = use commit as-is
# reword = change commit message
# edit = stop to modify commit
# squash = combine with previous commit
# fixup = like squash but discard commit message
# drop = remove commit entirely
Example interactive rebase session:
pick abc123 Add user model
squash def456 Fix typo in user model
reword ghi789 Add user authentication
drop jkl012 Debug print statements
Advanced Commit Techniques
Partial Commits with Patch Mode
# Interactively choose which changes to stage
git add -p
# Options in patch mode:
# y - stage this hunk
# n - skip this hunk
# s - split this hunk into smaller parts
# e - manually edit this hunk
# q - quit patch mode
Commit Message Templates
# Set up a commit message template
git config commit.template ~/.gitmessage
# Example ~/.gitmessage template:
# [type]: [subject]
#
# [body]
#
# [footer]
#
# Types: feat, fix, docs, style, refactor, test, chore
# Subject: 50 chars max, imperative mood
# Body: Wrap at 72 chars, explain what and why
# Footer: Reference issues/PRs
Semantic Commit Messages
# Feature addition
git commit -m "feat: add user authentication system"
# Bug fix
git commit -m "fix: resolve memory leak in image processing"
# Documentation
git commit -m "docs: update API documentation for v2.0"
# Refactoring
git commit -m "refactor: extract utility functions to separate module"
# Performance improvement
git commit -m "perf: optimize database queries for user search"
# Breaking change
git commit -m "feat!: redesign user authentication API
BREAKING CHANGE: Authentication endpoints have been redesigned.
See migration guide for updating existing integrations."
Advanced Merging and Conflict Resolution
Merge Strategies
# Fast-forward merge (default when possible)
git merge feature-branch
# No fast-forward merge (always create merge commit)
git merge --no-ff feature-branch
# Squash merge (combine all commits into one)
git merge --squash feature-branch
# Octopus merge (merge multiple branches)
git merge branch1 branch2 branch3
Advanced Conflict Resolution
# Use different merge strategies
git merge -X theirs feature-branch # Favor their changes
git merge -X ours feature-branch # Favor our changes
git merge -X ignore-space-change # Ignore whitespace changes
# Rerere (reuse recorded resolution)
git config rerere.enabled true
# When conflicts occur, resolve once, and git remembers
git rerere
# View available merge tools
git mergetool --tool-help
# Use specific merge tool
git mergetool --tool=vimdiff
Stashing Like a Pro
Advanced stashing techniques for managing work in progress:
# Stash with a message
git stash push -m "WIP: working on user profile feature"
# Stash specific files
git stash push -m "Stash config changes" config/ .env
# Stash including untracked files
git stash -u
# List all stashes with details
git stash list --stat
# Apply specific stash
git stash apply stash@{2}
# Create branch from stash
git stash branch feature-branch stash@{0}
# Stash interactively
git stash -p
Powerful Git Aliases
Set up aliases for common complex commands:
# Add to ~/.gitconfig
[alias]
# Logs
lg = log --oneline --graph --decorate --all
lga = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all
# Status and branches
st = status -sb
br = branch -v
bra = branch -va
# Commits
cm = commit -m
ca = commit -am
amend = commit --amend --no-edit
# Stashing
sl = stash list
sa = stash apply
ss = stash save
# Undoing
unstage = reset HEAD --
last = log -1 HEAD
undo = reset --soft HEAD~1
# Diffs
df = diff --color-words
dfs = diff --staged --color-words
# Remote operations
pl = pull --rebase
ps = push
psu = push -u origin HEAD
# Interactive operations
rb = rebase -i
cp = cherry-pick
# Shortcuts
co = checkout
cob = checkout -b
sw = switch
swc = switch -c
Git Hooks for Automation
Automate tasks with git hooks:
Pre-commit Hook (.git/hooks/pre-commit
)
#!/bin/sh
# Run linter
npm run lint
if [ $? -ne 0 ]; then
echo "Linting failed. Commit aborted."
exit 1
fi
# Run tests
npm test
if [ $? -ne 0 ]; then
echo "Tests failed. Commit aborted."
exit 1
fi
# Check for console.log statements
if grep -r "console.log" src/ --exclude-dir=node_modules; then
echo "console.log statements found. Please remove them before committing."
exit 1
fi
echo "Pre-commit checks passed!"
Commit Message Hook (.git/hooks/commit-msg
)
#!/bin/sh
# Check commit message format
commit_regex='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}'
if ! grep -qE "$commit_regex" "$1"; then
echo "Invalid commit message format!"
echo "Format: type(scope): description"
echo "Example: feat(auth): add user login system"
exit 1
fi
Advanced Git Commands
Bisect for Bug Hunting
# Start bisecting
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 middle commit
# Test and mark as good or bad
git bisect good # or git bisect bad
# Continue until bug is found
# Reset when done
git bisect reset
Cherry-picking and Reverting
# Cherry-pick a commit from another branch
git cherry-pick abc123
# Cherry-pick multiple commits
git cherry-pick abc123 def456 ghi789
# Cherry-pick a range of commits
git cherry-pick abc123..def456
# Revert a commit (creates new commit that undoes changes)
git revert abc123
# Revert a merge commit
git revert -m 1 abc123
Working with Submodules
# Add a submodule
git submodule add https://github.com/user/repo.git libs/external
# Initialize submodules after cloning
git submodule init
git submodule update
# Or do both in one command
git submodule update --init --recursive
# Update submodules to latest
git submodule update --remote
# Remove a submodule
git submodule deinit libs/external
git rm libs/external
Git Performance and Maintenance
Repository Maintenance
# Clean up unnecessary files and optimize repository
git gc --aggressive --prune=now
# Check repository integrity
git fsck
# Count objects and disk usage
git count-objects -vH
# Clean up remote-tracking branches
git remote prune origin
# Remove untracked files and directories
git clean -fd
# See what would be removed (dry run)
git clean -fdn
Large File Handling
# Track large files with Git LFS
git lfs track "*.pdf"
git lfs track "*.mp4"
git lfs track "assets/**"
# See tracked patterns
git lfs track
# See LFS files in repo
git lfs ls-files
# Pull LFS files
git lfs pull
Best Practices Summary
- Write meaningful commit messages following conventional commit format
- Use feature branches for all development work
- Rebase feature branches before merging to maintain clean history
- Use pull requests for code review and collaboration
- Tag releases with semantic versioning
- Set up git hooks to enforce code quality
- Regular maintenance with
git gc
and cleanup commands - Use
.gitignore
effectively to exclude unnecessary files - Sign commits for security in important repositories
- Backup important branches regularly
Conclusion
Mastering these advanced Git techniques will make you a more effective developer and collaborator. The key is to practice these commands in safe environments and gradually incorporate them into your daily workflow.
Remember, Git is a powerful tool, and with great power comes great responsibility. Always be cautious when rewriting history on shared branches, and communicate with your team about workflow conventions.