Introduction to Version Control Concepts

Python Full Stack Web Developer Course - Week 1: Tuesday

Understanding Version Control

Version control is to code what save points are to video games - a safety net that allows you to explore freely knowing you can always return to a previous state. It's the technological equivalent of a time machine for your projects.

At its core, version control is a system that records changes to files over time, allowing you to recall specific versions later. Imagine you're writing a novel and want to try a different ending - version control lets you create that alternate ending while preserving your original work.

In the world of software development, version control is not a luxury but a necessity, much like how a pilot needs instruments to fly safely through clouds.

Why Use Version Control?

Consider this scenario: You're working on a web application, and it's functioning perfectly. You decide to add a new feature, but after making numerous changes across multiple files, the application crashes. Without version control, you'd need to remember every change you made and manually revert them - like trying to un-bake a cake.

Version control systems provide:

Types of Version Control Systems

Local Version Control Systems

The simplest form of version control is manual - copying your project folder and renaming it (project_v1, project_v2, etc.). This is like taking photographs of your whiteboard after each meeting. It's better than nothing, but it's error-prone and inefficient.

Early automated systems like RCS (Revision Control System) store patch sets (differences between files) in a special format on disk. Think of it as saving only the edits to a document rather than full copies, similar to how a teacher might mark up a student's paper rather than rewriting it entirely.

Centralized Version Control Systems (CVCS)

Systems like SVN (Subversion) and CVS (Concurrent Versions System) use a central server that contains all versioned files. This is like a library where books (code) must be checked out before modifications and returned afterward.

The advantages include:

The downsides include:

Distributed Version Control Systems (DVCS)

Git, Mercurial, and Bazaar are distributed systems where clients fully mirror the repository, including its history. This is like everyone having their own complete library rather than a single central one.

The advantages include:

Today, Git has become the de facto standard for version control due to its speed, distributed nature, and the popularity of hosting services like GitHub.

Git Fundamentals

The Three States of Git

In Git, your files exist in three main states, similar to the states of matter (solid, liquid, gas):

Basic Git Terminology

Essential Git Commands

Setting Up a Repository

git init

Creates a new Git repository. This is like establishing a new timeline for your project. It adds a hidden .git folder that stores all the version history data.

Checking Status

git status

Shows the current state of your working directory and staging area. It tells you which changes are tracked, untracked, modified, or staged. This is like checking a dashboard to see where everything stands.

Adding Files to Staging

git add filename.py

Adds a specific file to the staging area, preparing it for commit.

git add .

Adds all changed files in the current directory to staging. Use with caution - you might include files you didn't mean to commit!

Committing Changes

git commit -m "Add login functionality"

Creates a new commit with all staged changes. The message should clearly describe what changed and why. Think of each commit as signing your name to a specific set of changes.

Viewing History

git log

Shows the commit history, like reading a project diary with entries for each significant change.

git log --oneline

Shows a condensed history with one line per commit - useful for getting a quick overview.

A Practical Git Workflow

Let's walk through a real-world example of using Git in a Python web project:

Scenario: Adding a New User Registration Feature

  1. Start by creating a repository for your project:
    mkdir my_flask_app cd my_flask_app git init
  2. Create your initial project files and make your first commit:
    touch app.py requirements.txt # Edit these files with your code editor git add . git commit -m "Initial project setup"
  3. Add some basic Flask application code to app.py:
    from flask import Flask, render_template app = Flask(__name__) @app.route('/') def home(): return render_template('home.html') if __name__ == '__main__': app.run(debug=True)
  4. Create a templates directory and add a home.html file:
    mkdir templates touch templates/home.html

    Add some HTML to the home.html file:

    <!DOCTYPE html> <html> <head> <title>My Flask App</title> </head> <body> <h1>Welcome to My Flask App</h1> </body> </html>
  5. Stage and commit these changes:
    git add . git commit -m "Add basic Flask application structure"
  6. Check your commit history:
    git log --oneline

    You should see something like:

    a1b2c3d Add basic Flask application structure e5f6g7h Initial project setup
  7. Now, let's add the user registration functionality:
    # Modify app.py to add registration route

    Updated app.py:

    from flask import Flask, render_template, request, redirect, url_for app = Flask(__name__) # Simple in-memory user storage (would use a database in production) users = [] @app.route('/') def home(): return render_template('home.html') @app.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] # Would hash this in production users.append({'username': username, 'password': password}) return redirect(url_for('home')) return render_template('register.html') if __name__ == '__main__': app.run(debug=True)
  8. Create a register.html template:
    touch templates/register.html

    Add form HTML:

    <!DOCTYPE html> <html> <head> <title>Register - My Flask App</title> </head> <body> <h1>Register New Account</h1> <form method="POST"> <div> <label>Username:</label> <input type="text" name="username" required> </div> <div> <label>Password:</label> <input type="password" name="password" required> </div> <button type="submit">Register</button> </form> <a href="/">Back to Home</a> </body> </html>
  9. Update home.html to include a link to the registration page:
    <!DOCTYPE html> <html> <head> <title>My Flask App</title> </head> <body> <h1>Welcome to My Flask App</h1> <a href="/register">Register New Account</a> </body> </html>
  10. Check what files have changed:
    git status
  11. Commit the new feature:
    git add . git commit -m "Add user registration functionality"

Now, if something goes wrong with your registration feature, you can always go back to the previous working state using git commands.

Version Control Best Practices

Commit Messages

Good commit messages are like well-written chapter titles in a book - they help readers understand what's inside without having to read the whole thing.

Follow these guidelines:

Bad: git commit -m "changes"

Good: git commit -m "Add password reset functionality"

Commit Frequency

Commit frequency is like deciding when to save your progress in a video game:

Ignoring Files

Not all files should be tracked in version control. Create a .gitignore file to exclude:

A basic .gitignore for Python projects:

# Python __pycache__/ *.py[cod] *$py.class *.so .Python env/ venv/ ENV/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # Environment variables .env .env.local # IDE specific files .idea/ .vscode/ *.swp *.swo # OS specific files .DS_Store Thumbs.db

Common Version Control Scenarios

Scenario 1: Undoing Changes

You've made changes to a file but realize they're incorrect and want to revert to the last committed version:

git checkout -- filename.py

Think of this as using a time machine to restore a file to its previous state.

Scenario 2: Viewing Differences

You want to see what's changed since your last commit:

git diff

This is like using a "spot the difference" tool between two versions of your code.

Scenario 3: Fixing the Last Commit

You made a commit but forgot to include a file or made a typo in the commit message:

git add forgotten_file.py git commit --amend -m "Correct commit message"

This is like going back to edit the last entry in your journal.

Scenario 4: Creating a Branch for a New Feature

You want to develop a new feature without affecting the main codebase:

git branch new-feature git checkout new-feature # Or in one command: git checkout -b new-feature

This is like creating a parallel universe where you can experiment safely.

Version Control in Real-World Development

Open Source Collaboration

Version control enables thousands of developers worldwide to contribute to projects like Python, Django, and Flask. Without Git, projects like the Linux kernel (with thousands of contributors) would be nearly impossible to manage.

Continuous Integration/Continuous Deployment (CI/CD)

Modern development workflows use version control as the foundation for automated testing and deployment pipelines. Each commit can trigger tests, and successful builds on specific branches can automatically deploy to staging or production environments.

Software Archaeology

When bugs appear in production, developers can use version control history to identify when the issue was introduced and why, making troubleshooting much more efficient.

Code Reviews

Version control platforms like GitHub facilitate code reviews through pull requests, where changes can be discussed, improved, and approved before being merged into the main codebase.

Hands-on Exercise: Git Basics

Follow these steps to practice basic Git operations:

  1. Create a new directory for a sample project:
    mkdir git_practice cd git_practice
  2. Initialize a Git repository:
    git init
  3. Create a Python file with a simple function:
    # calculator.py def add(a, b): return a + b
  4. Stage and commit the file:
    git add calculator.py git commit -m "Add calculator with addition function"
  5. Modify the file to add a new function:
    # calculator.py def add(a, b): return a + b def subtract(a, b): return a - b
  6. Check the status and differences:
    git status git diff
  7. Commit the changes:
    git add calculator.py git commit -m "Add subtraction function"
  8. View the commit history:
    git log

Topics for Further Exploration

Remember, version control is like learning to drive - the basics are simple, but mastery comes with practice and experience. The investment you make in learning Git will pay dividends throughout your career as a developer.

Key Takeaways

As you progress in your development journey, your understanding and usage of Git will naturally evolve. Start with these fundamentals, and you'll be well-prepared to collaborate on projects of any size.

Assignment: Create Your First GitHub Repository

Create a repository on GitHub with a README.md file describing your goals for the course.

  1. Create a GitHub account if you don't already have one (github.com)
  2. Create a new repository on GitHub named "python_fullstack_course"
  3. Initialize it with a README.md file
  4. Clone the repository to your local machine:
    git clone https://github.com/yourusername/python_fullstack_course.git
  5. Edit the README.md file to include:
    • Your name and background
    • Why you're taking this course
    • Your goals for the next 14 weeks
    • Any previous experience with Python or web development
  6. Commit and push your changes:
    git add README.md git commit -m "Update README with course goals" git push origin main
  7. Submit the URL to your GitHub repository