Oreoluwa
Mastering Git: Advanced Workflows and Best Practices
February 1, 2024
11 min read

Mastering Git: Advanced Workflows and Best Practices

Git
Version Control
DevOps
Workflow

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

  1. Write meaningful commit messages following conventional commit format
  2. Use feature branches for all development work
  3. Rebase feature branches before merging to maintain clean history
  4. Use pull requests for code review and collaboration
  5. Tag releases with semantic versioning
  6. Set up git hooks to enforce code quality
  7. Regular maintenance with git gc and cleanup commands
  8. Use .gitignore effectively to exclude unnecessary files
  9. Sign commits for security in important repositories
  10. 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.