Git Workflow Guide: From Chaos to Clarity

December 10, 2024

Git Workflow Guide: From Chaos to Clarity

Git is powerful, but teams usually struggle because they don't agree on a few basics. A simple workflow keeps history readable, reviews focused, and releases less stressful. This comprehensive guide will take you from Git chaos to clarity with battle-tested workflows used by top engineering teams.

Git branching visualization

Why Git Workflow Matters

A well-defined Git workflow is the backbone of effective collaboration. Without it, you risk:

  • Merge conflicts that take hours to resolve
  • Lost code from force pushes and rebases gone wrong
  • Unclear history that makes debugging impossible
  • Blocked deployments due to untested code in main
  • Team friction from inconsistent practices

Core Git Concepts

Understanding the DAG

Git stores history as a Directed Acyclic Graph (DAG). Every commit has:

  • A unique hash (SHA-1)
  • Parent pointer(s) to previous commit(s)
  • A tree representing file state
  • Author and committer metadata
# Visualize your history git log --oneline --graph --all # Pretty format with branches git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

The Three States

Git operates in three main areas:

AreaPurposeCommands
Working DirectoryYour actual filesEdit files here
Staging Area (Index)Pre-commit snapshotgit add
RepositoryCommitted historygit commit

Branching Strategies

1. Trunk-Based Development

Best for: High-velocity teams, CI/CD practices

# Main branch is always deployable main ├── feature/auth-login # Short-lived (hours to days) ├── feature/payment-gateway # Short-lived └── hotfix/security-patch # Immediate fix

Rules:

  • Feature branches live less than 24 hours ideally
  • All changes go through pull requests
  • Main branch is always green (all tests pass)

2. Git Flow

Best for: Scheduled releases, versioned software

main # Production releases develop # Integration branch ├── feature/user-profiles ├── feature/email-notifications └── release/v2.1.0 hotfix # Emergency fixes to main

Rules:

  • Main branch reflects production
  • Develop branch is the integration point
  • Features branch from develop
  • Releases are prepared in release branches
  • Hotfixes branch from main

3. GitHub Flow

Best for: Web applications, continuous deployment

main ├── add-dark-mode ├── refactor-checkout └── update-dependencies

Rules:

  • Main branch is deployable
  • Create feature branch from main
  • Open pull request for review
  • Merge to main after approval
  • Deploy immediately

Essential Branch Commands

# Create and switch to new branch git checkout -b feature/my-feature git switch -c feature/my-feature # Newer syntax # List branches git branch # Local branches git branch -a # All branches (local + remote) git branch -vv # With tracking info # Switch branches git checkout main git switch main # Newer, clearer syntax # Delete branches git branch -d feature/old-feature # Safe delete (merged) git branch -D feature/abandoned # Force delete # Rename branch git branch -m old-name new-name

A Simple Team Workflow

Daily Development Cycle

  1. Start your day
# Get latest changes git checkout main git pull origin main # Create your feature branch git checkout -b feature/description
  1. Make regular commits
# Stage and commit changes git add . git commit -m "feat: add user authentication" # Or granular commits git add src/auth/ git commit -m "feat: implement JWT token generation" git add tests/auth/ git commit -m "test: add authentication unit tests"
  1. Keep your branch updated
# Rebase onto latest main (cleaner history) git checkout main git pull origin main git checkout feature/description git rebase main # Or merge main into your branch (preserves history) git merge main
  1. Open a pull request early
# Push your branch git push -u origin feature/description # Create PR with template gh pr create --title "feat: user authentication" --body-file .github/pull_request_template.md
  1. After review, merge back to main
# Squash merge (clean linear history) git checkout main git merge --squash feature/description # Or merge commit (preserves branch history) git merge --no-ff feature/description

Commit Message Best Practices

Conventional Commits

<type>[optional scope]: <description> [optional body] [optional footer(s)]

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style (formatting, missing semi colons)
  • refactor: Code refactoring
  • perf: Performance improvements
  • test: Adding or correcting tests
  • chore: Build process, dependencies
# Good commit messages git commit -m "feat(auth): implement JWT token refresh" git commit -m "fix(api): handle null response from payment gateway git commit -m "fix: resolve memory leak in user session handler - Clear interval on component unmount - Add cleanup in useEffect return - Update tests to verify cleanup Fixes #456"

Commit Message Checklist

  • Start with a clear verb (add, fix, remove, refactor)
  • Keep the first line under 50 characters
  • Use present tense ("Add feature" not "Added feature")
  • Reference issues/PRs in the body
  • Explain "why" not just "what"

Advanced Git Techniques

Interactive Rebase

Clean up your commit history before merging:

# Rebase last 5 commits git rebase -i HEAD~5 # Commands in interactive mode: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit

Stashing Work

# Quick stash git stash push -m "WIP: refactoring user service" # Stash with untracked files git stash push -u # List stashes git stash list # Apply stash (keeps it in the list) git stash apply stash@{0} # Pop stash (removes from list) git stash pop stash@{0} # Drop stash git stash drop stash@{0} # Clear all stashes git stash clear

Cherry-Picking

Apply specific commits from other branches:

# Cherry-pick a commit git cherry-pick abc123 # Cherry-pick without committing git cherry-pick -n abc123 # Cherry-pick multiple commits git cherry-pick abc123 def456

Reflog: Your Safety Net

# View all HEAD movements git reflog # Recover a lost commit git checkout HEAD@{5} # Reset to before a bad operation git reset --hard HEAD@{3}

Handling Merge Conflicts

Prevention Strategies

  1. Pull frequently from the base branch
  2. Keep branches short-lived (hours to days)
  3. Communicate with teammates working on similar areas
  4. Use feature flags for long-running features

Conflict Resolution

# When conflict occurs during merge git merge main # Auto-merging file.txt # CONFLICT (content): Merge conflict in file.txt # See conflicted files git status # Open file and resolve (look for <<<<<<< markers) # <<<<<<< HEAD # your changes # ======= # their changes # >>>>>>> branch-name # Mark as resolved git add file.txt # Complete the merge git commit # Opens editor with merge commit message

Using Merge Tools

# Configure merge tool git config --global merge.tool vscode git config --global mergetool.vscode.cmd "code --wait $MERGED" # Launch merge tool git mergetool

Code Review Checklist

Before requesting review:

  • Code compiles/builds successfully
  • All tests pass locally
  • New code has tests
  • No console.log or debug code
  • Commit messages follow convention
  • Branch is up to date with main
  • PR description explains changes and why
  • Linked related issues

During review, focus on:

  • Code correctness and edge cases
  • Architecture and design patterns
  • Performance implications
  • Security considerations
  • Test coverage
  • Documentation updates

CI/CD Integration

Pre-commit Hooks

# .pre-commit-config.yaml repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/commitlint/commitlint rev: v17.0.0 hooks: - id: commitlint stages: [commit-msg]

Branch Protection Rules

Configure in your Git hosting platform:

  • Require pull request reviews before merging
  • Require status checks to pass (CI tests)
  • Require branches to be up to date before merging
  • Restrict pushes that create files larger than 100MB
  • Require signed commits (for security)

Common Git Scenarios

Scenario 1: Undo Last Commit

# Undo commit, keep changes staged git reset --soft HEAD~1 # Undo commit, keep changes in working directory git reset HEAD~1 # Undo commit, discard changes (DANGEROUS) git reset --hard HEAD~1 # Undo a pushed commit (use carefully!) git revert HEAD git push

Scenario 2: Split a Commit

# Start interactive rebase git rebase -i HEAD~3 # Mark commit with 'edit' # Reset to before the commit, keep changes git reset HEAD^ # Stage and commit separately git add file1.js git commit -m "feat: add user validation" git add file2.js git commit -m "feat: add password hashing" # Continue rebase git rebase --continue

Scenario 3: Move Commit to Different Branch

# Cherry-pick the commit to new branch git checkout target-branch git cherry-pick abc123 # Remove from original branch git checkout original-branch git reset --hard HEAD~1 # If it's the last commit

Best Practices Summary

Do's

  • Commit early, commit often
  • Write meaningful commit messages
  • Pull before pushing
  • Use feature branches for all work
  • Review code before merging
  • Keep branches up to date
  • Tag releases

Don'ts

  • Commit directly to main/production branches
  • Force push to shared branches
  • Commit large binary files
  • Include secrets in commits
  • Make massive, unrelated commits
  • Ignore merge conflicts
  • Use git push --force without --force-with-lease

Tools and Extensions

CLI Tools

# tig: Text-mode interface for Git npm install -g tig # lazygit: Simple terminal UI for Git npm install -g lazygit # gh: GitHub CLI gh pr create gh pr merge gh issue list

VS Code Extensions

  • GitLens - Enhanced Git capabilities
  • Git Graph - Visual Git graph
  • GitHub Pull Requests - Review PRs in editor
  • Git History - View file history

Conclusion

The goal isn't "perfect Git" — it's fewer surprises and faster collaboration. Start simple, write down the rules, and improve them as your team grows.

Key takeaways:

  1. Choose a workflow that fits your team size and release schedule
  2. Keep branches short-lived to minimize conflicts
  3. Write good commit messages for future debugging
  4. Review code thoroughly before merging
  5. Automate checks with pre-commit hooks and CI

Remember: Git is a tool to help you collaborate, not a burden to endure. Master these fundamentals, and you'll spend less time wrestling with version control and more time building great software.

GitHub
LinkedIn
X
youtube