Article 1: Version Control with Git

Introduction

Version control is the foundation of modern software engineering. Through my experience working on both solo projects and large team codebases, I've seen how proper Git practices can mean the difference between smooth collaboration and merge conflict nightmares.

This article covers Git fundamentals from a practical perspectiveβ€”not just the commands, but the workflows and habits that make version control work effectively in real projects.

Why Version Control Matters

spinner

Version control provides:

  • History tracking: Every change is recorded with who, when, and why

  • Collaboration: Multiple developers can work simultaneously

  • Experimentation: Try ideas in branches without risking stable code

  • Recovery: Revert to any previous state when things go wrong

  • Code review: Review changes before they're merged

Git Fundamentals

The Three States

Understanding Git's three states is essential for working effectively:

spinner
State
Description
Command to Move

Working Directory

Files you're actively editing

-

Staging Area

Changes ready to be committed

git add

Repository

Committed history

git commit

Essential Commands

Understanding Commits

A commit is a snapshot of your project at a point in time:

Commit Best Practices

Writing Good Commit Messages

The conventional commit format I use in my projects:

Types:

  • feat: New feature

  • fix: Bug fix

  • docs: Documentation changes

  • style: Formatting, no code change

  • refactor: Code restructuring

  • test: Adding tests

  • chore: Maintenance tasks

Examples:

Commit Frequency

spinner

Guidelines from my experience:

  1. Commit often, but meaningfully - Each commit should represent one logical change

  2. Don't commit broken code to main branches

  3. Use staging selectively - git add -p lets you commit related changes separately

Branching Strategies

Git Flow

The branching model I use for most projects:

spinner

Branch Types:

Branch
Purpose
Naming

main

Production-ready code

main

develop

Integration branch

develop

feature

New features

feature/description

bugfix

Bug fixes

bugfix/description

hotfix

Urgent production fixes

hotfix/description

release

Release preparation

release/v1.0.0

GitHub Flow (Simplified)

For smaller projects, I often use the simpler GitHub Flow:

spinner

Steps:

  1. Create branch from main

  2. Make changes and commit

  3. Open Pull Request

  4. Review and discuss

  5. Merge to main

  6. Deploy

Branch Commands

Merging and Rebasing

Merge vs Rebase

spinner

When to use each:

Scenario
Strategy
Reason

Merging feature to main

Merge

Preserves feature history

Updating feature with main

Rebase

Keeps history clean

Public/shared branches

Merge

Don't rewrite shared history

Local cleanup

Rebase

Clean up before sharing

Merge Commands

Resolving Merge Conflicts

When conflicts occur:

Resolution steps:

Collaborative Workflows

Pull Request Workflow

spinner

Keeping Branches Updated

Working with Remotes

Undoing Changes

Common Scenarios

spinner

Commands for Undoing

Git Configuration

Essential Settings

Useful Aliases

Add these to your .gitconfig:

.gitignore Patterns

Advanced Git Techniques

Stashing Changes

Cherry-picking

Bisect for Bug Finding

Practical Exercise

Exercise 1: Repository Setup

Exercise 2: Feature Branch Workflow

Exercise 3: Handling Conflicts

Common Mistakes and How to Avoid Them

Mistake
Prevention
Recovery

Committing to wrong branch

Always check git status first

git stash, switch branch, git stash pop

Committing sensitive data

Use .gitignore, review before commit

git filter-branch or BFG Repo Cleaner

Force pushing to shared branch

Use --force-with-lease

Coordinate with team, restore from backup

Large binary files

Use Git LFS for binaries

Remove with git filter-branch

Vague commit messages

Use templates, review before pushing

git rebase -i to reword

Key Takeaways

  1. Commit messages matter - They're documentation for your future self and teammates

  2. Branch strategically - Use branches for features, but don't let them live too long

  3. Pull/rebase regularly - Keep your branch updated to minimize conflicts

  4. Never rewrite shared history - Use revert for pushed commits

  5. Configure Git properly - Good defaults save time and prevent mistakes

What's Next?

With version control mastered, you're ready to set up a professional development environment. In Article 2: Development Environment Setup, we'll configure Python tooling, virtual environments, and IDE settings for productive development.


This article is part of the Software Engineering 101 series.

Last updated