Git Workflow Best Practices

Git Workflow Best Practices: Professional Version Control

Table of Contents

  1. Git Fundamentals
  2. Branching Strategies
  3. Commit Best Practices
  4. Collaboration Workflows
  5. Code Review Process
  6. Release Management
  7. Conflict Resolution
  8. Git Hooks and Automation
  9. Advanced Git Techniques
  10. Best Practices Summary

Git Fundamentals {#fundamentals}

Git is a distributed version control system that tracks changes in source code during software development. Understanding Git fundamentals is crucial for effective collaboration and code management.

Basic Git Configuration

# Global configuration
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
git config --global init.defaultBranch main

# Editor configuration
git config --global core.editor "code --wait"

# Line ending configuration
git config --global core.autocrlf input  # macOS/Linux
git config --global core.autocrlf true   # Windows

# Useful aliases
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual '!gitk'

Repository Initialization

# Initialize new repository
git init
git add .
git commit -m "Initial commit"

# Clone existing repository
git clone https://github.com/user/repository.git
cd repository

# Add remote to existing repository
git remote add origin https://github.com/user/repository.git
git branch -M main
git push -u origin main

Branching Strategies {#branching}

Git Flow

Git Flow is a branching model that defines specific branch types and their purposes:

# Main branches
# - main/master: Production-ready code
# - develop: Integration branch for features

# Supporting branches
# - feature/*: New features
# - release/*: Release preparation
# - hotfix/*: Critical fixes

# Initialize Git Flow
git flow init

# Feature branches
git flow feature start new-login-system
# Work on feature...
git flow feature finish new-login-system

# Release branches
git flow release start 1.2.0
# Prepare release...
git flow release finish 1.2.0

# Hotfix branches
git flow hotfix start critical-security-fix
# Fix the issue...
git flow hotfix finish critical-security-fix

GitHub Flow (Simplified)

# Create feature branch from main
git checkout main
git pull origin main
git checkout -b feature/user-authentication

# Work on feature
git add .
git commit -m "Add user authentication endpoints"
git push origin feature/user-authentication

# Create pull request on GitHub
# After review and approval, merge to main
# Delete feature branch
git checkout main
git pull origin main
git branch -d feature/user-authentication

GitLab Flow

# Feature branch workflow
git checkout -b feature/payment-integration

# Environment branches
git checkout -b production  # Production environment
git checkout -b staging     # Staging environment
git checkout -b develop     # Development environment

# Release branch with environment promotion
git checkout main
git checkout -b release/1.3.0
# Deploy to staging for testing
# After testing, merge to production

Commit Best Practices {#commits}

Conventional Commits

Follow the Conventional Commits specification for consistent commit messages:

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

# Types:
# feat: New feature
# fix: Bug fix
# docs: Documentation changes
# style: Code style changes (formatting, etc.)
# refactor: Code refactoring
# test: Adding or updating tests
# chore: Maintenance tasks

# Examples:
git commit -m "feat(auth): add OAuth2 authentication"
git commit -m "fix(api): handle null response in user endpoint"
git commit -m "docs: update API documentation for v2"
git commit -m "refactor(database): optimize user queries"
git commit -m "test(auth): add unit tests for login functionality"

# Multi-line commit with body
git commit -m "feat(payment): integrate Stripe payment processing

Add Stripe payment integration with the following features:
- Credit card processing
- Subscription management
- Webhook handling for payment events

Closes #123"

Atomic Commits

Make commits that represent single, logical changes:

# Good: Single logical change
git add src/auth/login.js
git commit -m "feat(auth): add login validation"

# Bad: Multiple unrelated changes
git add .
git commit -m "fix login, update docs, refactor database"

# Use interactive staging for partial commits
git add -p  # Stage hunks interactively
git commit -m "feat(auth): add email validation"

# Amend last commit (if not pushed)
git add forgotten-file.js
git commit --amend --no-edit

Commit Message Templates

Create a commit message template:

# Create template file
cat > ~/.gitmessage << EOF
# Title: Summary, imperative, start upper case, don't end with a period
# No more than 50 chars. #### 50 chars is here:  #

# Remember blank line between title and body.

# Body: Explain *what* and *why* (not *how*). Include task ID (Jira issue).
# Wrap at 72 chars. ################################## which is here:  #


# At the end: Include Co-authored-by for all contributors. 
# Include at least one empty line before it. Format: 
# Co-authored-by: name <user@users.noreply.github.com>
#
# How to Write a Git Commit Message:
# https://chris.beams.io/posts/git-commit/
#
# 1. Separate subject from body with a blank line
# 2. Limit the subject line to 50 characters
# 3. Capitalize the subject line
# 4. Do not end the subject line with a period
# 5. Use the imperative mood in the subject line
# 6. Wrap the body at 72 characters
# 7. Use the body to explain what and why vs. how
EOF

# Configure Git to use the template
git config --global commit.template ~/.gitmessage

Collaboration Workflows {#collaboration}

Fork and Pull Request Workflow

# Fork repository on GitHub/GitLab
# Clone your fork
git clone https://github.com/yourusername/repository.git
cd repository

# Add upstream remote
git remote add upstream https://github.com/originalowner/repository.git

# Create feature branch
git checkout -b feature/awesome-feature

# Keep your fork up to date
git fetch upstream
git checkout main
git merge upstream/main
git push origin main

# Work on your feature
git add .
git commit -m "feat: add awesome feature"
git push origin feature/awesome-feature

# Create pull request
# After merge, clean up
git checkout main
git pull upstream main
git branch -d feature/awesome-feature
git push origin --delete feature/awesome-feature

Collaborative Feature Development

# Multiple developers on same feature
git checkout -b feature/complex-feature

# Developer A pushes initial work
git push origin feature/complex-feature

# Developer B joins the feature
git fetch origin
git checkout feature/complex-feature

# Regular synchronization
git pull origin feature/complex-feature
# Work on your part
git add .
git commit -m "feat(feature): add component X"
git push origin feature/complex-feature

# Resolve conflicts when they occur
git pull origin feature/complex-feature
# Resolve conflicts in editor
git add resolved-file.js
git commit -m "resolve: merge conflicts in feature branch"
git push origin feature/complex-feature

Code Review Process {#reviews}

Preparing Code for Review

# Clean up commit history before creating PR
git rebase -i HEAD~3  # Interactive rebase for last 3 commits

# Squash related commits
pick a1b2c3d feat: add user model
squash e4f5g6h feat: add user validation
squash h7i8j9k feat: add user tests

# Update commit message
# This will become: "feat: add user model with validation and tests"

# Force push clean history (only on feature branches)
git push --force-with-lease origin feature/user-management

Review Checklist

## Code Review Checklist

### Functionality
- [ ] Code works as intended
- [ ] Edge cases are handled
- [ ] Error handling is appropriate
- [ ] Performance considerations

### Code Quality
- [ ] Code is readable and well-structured
- [ ] Functions are appropriately sized
- [ ] Variable names are descriptive
- [ ] Comments explain why, not what

### Testing
- [ ] Unit tests are included
- [ ] Tests cover edge cases
- [ ] Integration tests if needed
- [ ] All tests pass

### Security
- [ ] No sensitive data in code
- [ ] Input validation present
- [ ] Authentication/authorization checked
- [ ] SQL injection prevention

### Documentation
- [ ] README updated if needed
- [ ] API documentation updated
- [ ] Inline comments for complex logic
- [ ] CHANGELOG updated

Release Management {#releases}

Semantic Versioning

# Version format: MAJOR.MINOR.PATCH
# MAJOR: Breaking changes
# MINOR: New features (backward compatible)
# PATCH: Bug fixes (backward compatible)

# Examples:
# 1.0.0 -> 1.0.1 (bug fix)
# 1.0.1 -> 1.1.0 (new feature)
# 1.1.0 -> 2.0.0 (breaking change)

# Tag releases
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin v1.2.0

# List tags
git tag -l

# Checkout specific version
git checkout v1.2.0

Release Branch Workflow

# Create release branch
git checkout develop
git pull origin develop
git checkout -b release/1.3.0

# Prepare release
# - Update version numbers
# - Update CHANGELOG
# - Final testing

# Merge to main and tag
git checkout main
git merge --no-ff release/1.3.0
git tag -a v1.3.0 -m "Release 1.3.0"

# Merge back to develop
git checkout develop
git merge --no-ff release/1.3.0

# Push everything
git push origin main
git push origin develop
git push origin v1.3.0

# Clean up
git branch -d release/1.3.0
git push origin --delete release/1.3.0

Automated Release with GitHub Actions

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    - name: Create Release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ github.ref }}
        release_name: Release ${{ github.ref }}
        draft: false
        prerelease: false

Conflict Resolution {#conflicts}

Merge Conflicts

# When conflicts occur during merge
git merge feature-branch
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt

# View conflict status
git status

# Resolve conflicts manually
# Edit file.txt to resolve conflicts
# Remove conflict markers: <<<<<<<, =======, >>>>>>>

# Mark as resolved
git add file.txt
git commit -m "resolve: merge conflicts from feature-branch"

# Use merge tools
git config --global merge.tool vimdiff
git mergetool

Rebase Conflicts

# Interactive rebase with conflicts
git rebase -i HEAD~3

# When conflict occurs during rebase
# Edit conflicted files
git add resolved-file.txt
git rebase --continue

# Abort rebase if needed
git rebase --abort

# Skip problematic commit
git rebase --skip

Advanced Conflict Resolution

# Use different merge strategies
git merge -X ours feature-branch    # Prefer current branch
git merge -X theirs feature-branch  # Prefer incoming changes

# Cherry-pick with conflict resolution
git cherry-pick abc123
# Resolve conflicts
git add .
git cherry-pick --continue

# Three-way merge understanding
git show :1:file.txt  # Common ancestor
git show :2:file.txt  # Current branch (ours)
git show :3:file.txt  # Incoming branch (theirs)

Git Hooks and Automation {#hooks}

Pre-commit Hooks

# Install pre-commit framework
pip install pre-commit

# Create .pre-commit-config.yaml
cat > .pre-commit-config.yaml << EOF
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.1.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-json
      - id: check-merge-conflict
      - id: no-commit-to-branch
        args: ['--branch', 'main']

  - repo: https://github.com/psf/black
    rev: 22.3.0
    hooks:
      - id: black
        language_version: python3.9

  - repo: https://github.com/pycqa/flake8
    rev: 4.0.1
    hooks:
      - id: flake8
EOF

# Install hooks
pre-commit install

# Run on all files
pre-commit run --all-files

Custom Hooks

# Pre-commit hook script
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
# Run tests before commit
echo "Running tests..."
npm test
if [ $? -ne 0 ]; then
    echo "Tests failed. Commit aborted."
    exit 1
fi

# Run linting
echo "Running linter..."
npm run lint
if [ $? -ne 0 ]; then
    echo "Linting failed. Commit aborted."
    exit 1
fi

echo "All checks passed. Proceeding with commit."
EOF

chmod +x .git/hooks/pre-commit

Commit Message Hooks

# Commit message validation
cat > .git/hooks/commit-msg << 'EOF'
#!/bin/bash
# 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 login functionality"
    exit 1
fi
EOF

chmod +x .git/hooks/commit-msg

Advanced Git Techniques {#advanced}

Interactive Rebase

# Rewrite commit history
git rebase -i HEAD~5

# Options in interactive mode:
# pick = use commit
# reword = use commit, but edit message
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous
# fixup = like squash, but discard log message
# drop = remove commit

# Example rebase plan:
pick a1b2c3d Add user authentication
squash e4f5g6h Fix authentication bug
reword h7i8j9k Add user registration
drop k9l0m1n Remove debug code
edit n2o3p4q Add password validation

Advanced Log and History

# Pretty log formatting
git log --oneline --graph --decorate --all
git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short

# Search commits
git log --grep="fix"              # Search commit messages
git log -S"function_name"         # Search code changes
git log --author="John Doe"       # Filter by author
git log --since="2 weeks ago"     # Time-based filtering
git log file.txt                  # Changes to specific file

# Show file evolution
git log -p file.txt               # Show patches
git blame file.txt                # Line-by-line author info
git show HEAD:file.txt            # Show file at specific commit

Reflog and Recovery

# View reference log
git reflog

# Recover lost commits
git checkout abc123               # Detached HEAD
# Make some commits
git checkout main                 # Commits seem lost
git reflog                        # Find the lost commits
git checkout -b recover-branch abc123  # Recover them

# Undo various operations
git reset --hard HEAD~1           # Undo last commit
git reflog                        # Find the commit hash
git reset --hard abc123           # Restore to that commit

Stashing Workflows

# Basic stashing
git stash push -m "Work in progress on feature X"
git stash list
git stash apply stash@{0}
git stash drop stash@{0}
git stash pop  # Apply and drop

# Partial stashing
git stash push -p  # Interactive stashing
git stash push --keep-index  # Stash only unstaged changes

# Stash untracked files
git stash push -u -m "Include untracked files"

# Create branch from stash
git stash branch feature-branch stash@{0}

Best Practices Summary {#summary}

Repository Structure

project/
├── .gitignore          # Ignore patterns
├── .gitattributes      # Git attributes
├── README.md           # Project documentation
├── CONTRIBUTING.md     # Contribution guidelines
├── CHANGELOG.md        # Change history
├── LICENSE            # Project license
└── .github/           # GitHub-specific files
    ├── workflows/     # GitHub Actions
    ├── ISSUE_TEMPLATE/
    └── PULL_REQUEST_TEMPLATE.md

Essential .gitignore Patterns

# Dependencies
node_modules/
__pycache__/
.env

# Build outputs
dist/
build/
*.log

# IDE files
.vscode/
.idea/
*.swp
*.swo

# OS files
.DS_Store
Thumbs.db

# Temporary files
*.tmp
*.temp
.cache/

Workflow Guidelines

  1. Keep commits atomic - One logical change per commit
  2. Write meaningful commit messages - Follow conventional commits
  3. Use feature branches - Never commit directly to main
  4. Review code thoroughly - Use pull/merge requests
  5. Test before merging - Automated testing in CI/CD
  6. Keep history clean - Use rebase for feature branches
  7. Tag releases - Use semantic versioning
  8. Document changes - Maintain CHANGELOG
  9. Secure sensitive data - Never commit secrets
  10. Backup important work - Push regularly to remote

This comprehensive guide covers professional Git workflows that scale from individual projects to large team collaborations. Following these practices will lead to better code quality, easier collaboration, and more maintainable project history.