Documentation

Complete guide to version control with Git and GitHub

Module 1: Introduction to Version Control
What is Version Control?

Version control is a system that records changes to files over time so you can recall specific versions later. It allows you to track modifications, compare different versions, and collaborate with others on the same project.

Why Use Version Control?
  • Track Changes: Keep a history of every change made to your project
  • Collaboration: Multiple people can work on the same project simultaneously
  • Backup: Your code is stored in multiple locations, reducing risk of data loss
  • Experimentation: Create branches to try new ideas without affecting the main code
  • Revert Changes: Easily go back to previous versions if something goes wrong
Types of Version Control Systems
Type Description Examples
Local VCS Single-machine version control RCS
Centralized VCS Single central server containing all versions CVS, Subversion
Distributed VCS Every client has a full copy of the repository Git, Mercurial
Introduction to Git

Git is a distributed version control system created by Linus Torvalds in 2005. It is:

  • Fast and Efficient: Most operations are performed locally
  • Distributed: Every developer has a full copy of the repository
  • Secure: Uses SHA-1 hashing for integrity
  • Flexible: Supports various workflows
Basic Git Terminology
  • Repository: A project's database containing all files and history
  • Commit: A snapshot of the repository at a specific point in time
  • Branch: An independent line of development
  • Merge: Combining changes from different branches
  • Clone: Creating a copy of a remote repository
  • Push: Sending local commits to a remote repository
  • Pull: Fetching changes from a remote repository and merging them
Module 2: Git Installation and Setup
Installing Git

Git can be installed on various operating systems:

For Windows, download the installer from the official Git website:

  1. Visit https://git-scm.com/download/win
  2. Download the installer and run it
  3. Follow the installation wizard, accepting the default settings
  4. After installation, open Git Bash from the Start menu

# Verify installation
git --version

For macOS, you have several options:

  1. Download Installer: Visit https://git-scm.com/download/mac and download the installer
  2. Homebrew: If you have Homebrew installed, run:
    
    brew install git
    
  3. Xcode Command Line Tools: Install Xcode Command Line Tools which include Git:
    
    xcode-select --install
    

For Linux distributions, use the package manager:

Ubuntu/Debian:


sudo apt update
sudo apt install git

Fedora/CentOS:


sudo dnf install git
# or for older systems
sudo yum install git

Arch Linux:


sudo pacman -S git
Initial Git Configuration

After installing Git, you need to configure your name and email address. This information will be embedded in your commits.


# Set your name
git config --global user.name "Your Name"

# Set your email
git config --global user.email "your.email@example.com"

# Verify configuration
git config --list
Common Configuration Options

# Set default branch name
git config --global init.defaultBranch main

# Set default text editor
git config --global core.editor "code --wait"  # For VS Code
# git config --global core.editor "nano"     # For nano
# git config --global core.editor "vim"      # For vim

# Set line ending handling
git config --global core.autocrlf input  # For Linux/Mac
# git config --global core.autocrlf true  # For Windows

# Enable colored output
git config --global color.ui auto

# Set default push behavior
git config --global push.default simple

# Set up credential helper (cache credentials for a period)
git config --global credential.helper cache
git config --global credential.helper 'cache --timeout=3600'  # Cache for 1 hour
SSH Key Setup

SSH keys allow you to connect to GitHub without entering your password each time:


# Check if you have existing SSH keys
ls -al ~/.ssh

# Generate a new SSH key
ssh-keygen -t ed25519 -C "your.email@example.com"

# Start the ssh-agent in the background
eval "$(ssh-agent -s)"

# Add your SSH private key to the ssh-agent
ssh-add ~/.ssh/id_ed25519

# Copy your public key to clipboard
# On macOS:
pbcopy < ~/.ssh/id_ed25519.pub
# On Linux (requires xclip):
xclip -selection clipboard < ~/.ssh/id_ed25519.pub
# On Windows Git Bash:
clip < ~/.ssh/id_ed25519.pub

Then add the copied public key to your GitHub account:

  1. Go to GitHub.com and sign in
  2. Click your profile photo in the top right
  3. Click "Settings"
  4. In the left sidebar, click "SSH and GPG keys"
  5. Click "New SSH key" or "Add SSH key"
  6. Paste your key into the "Key" field
  7. Click "Add SSH key"
Verifying Your SSH Connection

# Test your SSH connection to GitHub
ssh -T git@github.com

# You should see a message like:
# Hi YourUsername! You've successfully authenticated, but GitHub does not provide shell access.
Module 3: Basic Git Commands (init, add, commit)
Creating a Git Repository

To start tracking a project with Git, you need to initialize a repository:


# Create a new directory for your project
mkdir my-project
cd my-project

# Initialize a Git repository
git init

# Initialize with a specific branch name
git init -b main
Checking Repository Status

The git status command shows the state of your working directory and staging area:


# Check the status of your repository
git status

# Get a more compact status
git status --short
# or
git status -s
Adding Files to the Staging Area

Before committing changes, you need to add them to the staging area:


# Create a new file
echo "# My Project" > README.md

# Add a specific file to the staging area
git add README.md

# Add multiple files
git add file1.txt file2.txt

# Add all files in the current directory
git add .

# Add all files, including deleted ones
git add -A

# Interactive staging
git add -i
Committing Changes

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


# Commit with a message
git commit -m "Initial commit: Add README"

# Commit with a detailed message
git commit -m "Add user authentication feature

- Implement login functionality
- Add password reset feature
- Update user model"

# Commit without staging (adds all tracked files)
git commit -a -m "Fix typos in documentation"

# Amend the last commit (use with caution)
git commit --amend -m "Updated commit message"
Viewing Commit History

# View commit history
git log

# View compact history
git log --oneline

# View history with graph
git log --oneline --graph --decorate

# View history of a specific file
git log --follow README.md

# View history with statistics
git log --stat

# View history with patch
git log -p

# Limit number of commits
git log -5
Viewing Changes

# Show differences between working directory and staging area
git diff

# Show differences between staging area and last commit
git diff --staged
# or
git diff --cached

# Show differences between two commits
git diff commit1 commit2

# Show differences in a specific file
git diff README.md

# Show changes in a more compact format
git diff --stat
Removing and Moving Files

# Remove a file from the working directory and staging area
git rm file.txt

# Remove a file from the staging area but keep it in the working directory
git rm --cached file.txt

# Move or rename a file
git mv old-name.txt new-name.txt

# This is equivalent to:
mv old-name.txt new-name.txt
git rm old-name.txt
git add new-name.txt
Ignoring Files

Create a .gitignore file to specify files that Git should ignore:


# Create a .gitignore file
touch .gitignore

# Add patterns to .gitignore
echo "*.log" >> .gitignore
echo "node_modules/" >> .gitignore
echo ".env" >> .gitignore
echo "*.tmp" >> .gitignore

# Add .gitignore to your repository
git add .gitignore
git commit -m "Add .gitignore file"
Undoing Changes

# Discard changes in the working directory
git checkout -- file.txt
# or (Git 2.23+)
git restore file.txt

# Unstage a file
git reset HEAD file.txt
# or (Git 2.23+)
git restore --staged file.txt

# Reset to a specific commit (destructive)
git reset --hard commit-hash

# Reset to a specific commit but keep changes
git reset --soft commit-hash
Module 4: Branching and Merging
Understanding Branches

In Git, a branch is a movable pointer to a commit. It allows you to develop features, fix bugs, or experiment with ideas in isolation from the main codebase.

Creating and Switching Branches

# List all branches
git branch

# List all remote branches
git branch -r

# List all local and remote branches
git branch -a

# Create a new branch
git branch feature-xyz

# Switch to a branch
git checkout feature-xyz
# or (Git 2.23+)
git switch feature-xyz

# Create and switch to a new branch
git checkout -b feature-xyz
# or (Git 2.23+)
git switch -c feature-xyz

# Switch to the previous branch
git checkout -
Making Changes on a Branch

# Make changes to files
echo "New feature code" > feature.js

# Add and commit changes
git add feature.js
git commit -m "Add new feature"

# Make more changes
echo "Update feature" >> feature.js
git add feature.js
git commit -m "Update feature implementation"
Merging Branches

# Switch to the target branch (e.g., main)
git checkout main

# Merge the feature branch into main
git merge feature-xyz

# Merge with a custom commit message
git merge feature-xyz -m "Merge feature-xyz into main"

# Merge without fast-forward (creates a merge commit)
git merge --no-ff feature-xyz

# Abort a merge in progress
git merge --abort
Resolving Merge Conflicts

When Git can't automatically merge changes, it will stop and ask you to resolve conflicts:


# After a merge attempt with conflicts, check status
git status

# Open the conflicted file(s) and resolve conflicts
# Conflicts will be marked like this:
# <<<<<<< HEAD
# Current branch content
# =======
# Incoming branch content
# >>>>>>> feature-xyz

# After resolving conflicts, mark them as resolved
git add conflicted-file.js

# Continue the merge
git commit
# Git will open an editor with a default merge commit message
Deleting Branches

# Delete a local branch (must be merged)
git branch -d feature-xyz

# Force delete a local branch (even if not merged)
git branch -D feature-xyz

# Delete a remote branch
git push origin --delete feature-xyz
# or
git push origin :feature-xyz
Rebasing

Rebasing is an alternative to merging that rewrites commit history:


# Rebase the current branch onto main
git checkout feature-xyz
git rebase main

# Interactive rebase (for editing history)
git rebase -i HEAD~3

# Continue after resolving conflicts during rebase
git rebase --continue

# Abort a rebase in progress
git rebase --abort
Cherry-picking

Cherry-picking allows you to apply specific commits from one branch to another:


# Cherry-pick a specific commit
git cherry-pick commit-hash

# Cherry-pick without committing
git cherry-pick --no-commit commit-hash

# Cherry-pick multiple commits
git cherry-pick start-commit..end-commit
Stashing Changes

Stashing allows you to temporarily save changes without committing them:


# Stash current changes
git stash

# Stash with a message
git stash push -m "Work in progress on feature X"

# List stashes
git stash list

# Apply the most recent stash
git stash apply

# Apply and remove the most recent stash
git stash pop

# Apply a specific stash
git stash apply stash@{1}

# Drop a stash
git stash drop stash@{1}

# Clear all stashes
git stash clear
Module 5: GitHub Introduction and Account Setup
What is GitHub?

GitHub is a web-based hosting service for Git repositories. It provides:

  • Cloud storage for Git repositories
  • Collaboration tools like pull requests and code reviews
  • Issue tracking and project management
  • Continuous integration and deployment (GitHub Actions)
  • Social networking features for developers
  • Documentation hosting with GitHub Pages
Creating a GitHub Account
  1. Go to https://github.com
  2. Click "Sign up" in the top right corner
  3. Enter your username, email, and password
  4. Verify your email address
  5. Complete your profile by adding a profile picture and bio
GitHub Pricing Plans
Plan Public Repositories Private Repositories Collaborators Price
Free Unlimited Unlimited Unlimited $0
Team Unlimited Unlimited Unlimited $4/user/month
Enterprise Unlimited Unlimited Unlimited Custom
Creating a New Repository on GitHub
  1. Click the "+" icon in the top right corner and select "New repository"
  2. Enter a repository name
  3. Add a description (optional)
  4. Choose between Public or Private
  5. Optionally initialize with a README file, .gitignore, or license
  6. Click "Create repository"
GitHub Profile Customization

Make your GitHub profile stand out by:

  • Adding a professional profile picture
  • Writing a clear bio
  • Pinning your most important repositories
  • Creating a special README repository with your username
Creating a Profile README
  1. Create a new repository with your exact username as the repository name
  2. Add a README.md file with information about yourself
  3. Include badges, skills, projects, and contact information

# Hi there! 👋

I'm [Your Name], a passionate [Your Role] from [Your Location].

## 🚀 About Me

- 🔭 I'm currently working on [Project Name]
- 🌱 I'm currently learning [Technology/Concept]
- 👯 I'm looking to collaborate on [Project Type]
- 🤔 I'm looking for help with [Technology/Concept]
- 💬 Ask me about [Technology/Topic]
- 📫 How to reach me: [Your Email]
- 😄 Pronouns: [Your Pronouns]
- ⚡ Fun fact: [Interesting Fact]

## 🛠️ Skills

[Add skill badges or list your skills]

## 📊 GitHub Stats

![Your GitHub stats](https://github-readme-stats.vercel.app/api?username=yourusername&show_icons=true&theme=radical)

## 📫 Get in Touch

- [LinkedIn](https://linkedin.com/in/yourprofile)
- [Twitter](https://twitter.com/yourhandle)
- [Email](mailto:your.email@example.com)
GitHub Security Settings

Secure your GitHub account by:

  • Enabling two-factor authentication (2FA)
  • Using a strong, unique password
  • Reviewing authorized applications and OAuth apps
  • Setting up SSH keys instead of HTTPS
Enabling Two-Factor Authentication
  1. Go to your account settings
  2. Click "Security" in the left sidebar
  3. Click "Enable two-factor authentication"
  4. Choose between using an authenticator app or SMS
  5. Follow the setup instructions
  6. Save your recovery codes in a secure location
Module 6: Remote Repositories (clone, push, pull)
Understanding Remote Repositories

A remote repository is a version of your project that is hosted on the internet or network. It allows you to collaborate with others and have a backup of your work.

Cloning a Repository

Cloning creates a local copy of a remote repository:


# Clone a repository using HTTPS
git clone https://github.com/username/repository.git

# Clone a repository using SSH
git clone git@github.com:username/repository.git

# Clone into a specific directory
git clone https://github.com/username/repository.git my-project

# Clone a specific branch
git clone -b branch-name https://github.com/username/repository.git

# Clone with depth (shallow clone - gets only recent history)
git clone --depth=1 https://github.com/username/repository.git
Adding Remote Repositories

# Add a remote repository
git remote add origin https://github.com/username/repository.git

# Add a remote with a different name
git remote add upstream https://github.com/original-owner/repository.git

# List all remote repositories
git remote

# List remote repositories with URLs
git remote -v

# Show information about a remote
git remote show origin
Fetching from Remote Repositories

# Fetch all changes from the remote
git fetch

# Fetch from a specific remote
git fetch origin

# Fetch a specific branch
git fetch origin branch-name

# Fetch all remotes
git fetch --all

# Fetch and prune (remove deleted remote branches)
git fetch --prune
Pulling Changes from Remote

# Pull changes from the remote (fetch + merge)
git pull

# Pull from a specific remote and branch
git pull origin main

# Pull with rebase instead of merge
git pull --rebase

# Pull without committing automatically
git pull --no-commit
Pushing Changes to Remote

# Push changes to the remote
git push

# Push to a specific remote and branch
git push origin main

# Push a new branch to the remote
git push -u origin feature-branch

# Push all branches
git push --all

# Push tags
git push --tags

# Force push (use with caution - rewrites history)
git push --force

# Force push with lease (safer alternative)
git push --force-with-lease
Tracking Branches

# Set up tracking for an existing branch
git branch --set-upstream-to=origin/main main

# Create a new branch that tracks a remote branch
git checkout -b feature-branch origin/feature-branch

# Show tracking information
git branch -vv
Managing Remote Branches

# List all remote branches
git branch -r

# List all local and remote branches
git branch -a

# Create a local branch from a remote branch
git checkout -b local-branch origin/remote-branch

# Delete a remote branch
git push origin --delete remote-branch
# or
git push origin :remote-branch
Renaming and Removing Remotes

# Rename a remote
git remote rename old-name new-name

# Remove a remote
git remote remove remote-name
# or
git remote rm remote-name
Working with Forks

When you fork a repository, you create a personal copy that you can modify:


# Clone your fork
git clone https://github.com/yourusername/repository.git

# Add the original repository as a remote (upstream)
git remote add upstream https://github.com/original-owner/repository.git

# Fetch changes from the original repository
git fetch upstream

# Merge changes from the original repository
git merge upstream/main

# Push changes to your fork
git push origin main
Module 7: Pull Requests and Code Reviews
What is a Pull Request?

A pull request (PR) is a mechanism for a developer to notify team members that they have completed a feature. It allows others to review the code before it's merged into the main branch.

Creating a Pull Request
  1. Push your feature branch to GitHub
  2. Navigate to the repository on GitHub
  3. Click the "Pull requests" tab
  4. Click "New pull request"
  5. Select the base and compare branches
  6. Add a title and description for your PR
  7. Click "Create pull request"
Pull Request Template

Create a .github/pull_request_template.md file in your repository:


## Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.

## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update

## How Has This Been Tested?
Please describe the tests that you ran to verify your changes.

## Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
Reviewing Pull Requests
  • Overall Review: Check if the PR achieves its stated goal
  • Code Quality: Look for clean, readable code
  • Functionality: Ensure the code works as expected
  • Performance: Check for potential performance issues
  • Security: Look for security vulnerabilities
  • Tests: Verify that tests are included and passing
Reviewing and Commenting
  1. Navigate to the "Files changed" tab in the PR
  2. Click on a line to add a general comment
  3. Highlight code to add a specific comment
  4. Use the suggestion feature to propose code changes
  5. Leave a general review comment at the bottom
  6. Approve, request changes, or comment on the PR
Making Changes to a Pull Request

After receiving feedback:

  1. Make the necessary changes in your local branch
  2. Commit and push the changes to the same branch
  3. The PR will automatically update with the new changes
Merging a Pull Request

There are several merge options:

  • Create a merge commit: Merges the branch with a merge commit
  • Squash and merge: Combines all commits into one
  • Rebase and merge: Replays commits on top of the base branch
Code Review Best Practices
  • Be constructive and respectful in your feedback
  • Focus on the code, not the person
  • Explain why a change is needed, not just what to change
  • Ask questions to understand the developer's intent
  • Recognize good work and positive contributions
  • Respond to comments in a timely manner
Protected Branches

Protect important branches by:

  1. Going to repository settings
  2. Clicking "Branches" in the left sidebar
  3. Adding branch protection rules
  4. Configuring requirements like:
    • Require pull request reviews before merging
    • Require status checks to pass before merging
    • Require branches to be up to date before merging
    • Restrict who can push to the branch
Using GitHub's Review Features
  • Suggested Changes: Propose code changes directly in the review
  • Request Changes: Block merging until changes are made
  • Approve: Indicate that the PR is ready to merge
  • Assign Reviewers: Specify who should review the PR
  • Assignees: Specify who is working on the PR
Module 8: Git Workflows and Best Practices
Common Git Workflows

There are several established workflows for using Git in a team environment:

Git Flow is a strict branching model designed for projects with scheduled releases:

  • main: Contains production-ready code
  • develop: Integration branch for features
  • feature: Branches for new features
  • release: Branches for preparing releases
  • hotfix: Branches for urgent fixes

# Initialize Git Flow
git flow init

# Start a new feature
git flow feature start feature-name

# Finish a feature
git flow feature finish feature-name

# Start a release
git flow release start v1.0.0

# Finish a release
git flow release finish v1.0.0

# Start a hotfix
git flow hotfix start hotfix-name

# Finish a hotfix
git flow hotfix finish hotfix-name

GitHub Flow is a simpler workflow that works well for continuous deployment:

  1. Anything in the main branch is deployable
  2. Create descriptive branches for new features
  3. Push to the named branch and open a pull request
  4. Discuss and review the code with teammates
  5. Merge to main after approval
  6. Deploy immediately

# Create a new feature branch
git checkout -b feature-user-authentication

# Make changes and commit
git add .
git commit -m "Add user authentication"

# Push to GitHub
git push origin feature-user-authentication

# Create a pull request on GitHub
# After review and approval, merge to main
# Pull the latest changes
git pull origin main

# Deploy

GitLab Flow combines features of Git Flow and GitHub Flow:

  • Primary branch (main) is always deployable
  • Environment branches (staging, production)
  • Feature branches for new work
  • Merge requests for code review

# Create a feature branch
git checkout -b feature-new-dashboard

# Make changes and commit
git add .
git commit -m "Add new dashboard UI"

# Push to GitLab
git push origin feature-new-dashboard

# Create a merge request on GitLab
# After review, merge to main

# Deploy to staging
git checkout -b staging origin/staging
git merge main
git push origin staging

# After testing, deploy to production
git checkout production
git merge staging
git push origin production
Commit Message Best Practices

Write clear, consistent commit messages:

  • Use the present tense ("Add feature" not "Added feature")
  • Keep the first line under 50 characters
  • Separate subject from body with a blank line
  • Wrap the body at 72 characters
  • Use the body to explain what and why, not how

# Good commit message format
feat: Add user authentication

Implement login and registration functionality with JWT tokens.
This allows users to create accounts and securely access the application.

- Add login form with validation
- Implement JWT token generation
- Create registration endpoint
- Add password reset functionality

Closes #123
Conventional Commits

Follow the Conventional Commits specification:


# Format: type(scope): description

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

# Examples
feat(auth): add JWT token refresh mechanism
fix(api): handle null response in user endpoint
docs(readme): update installation instructions
style(components): fix linting errors
refactor(utils): simplify date formatting function
test(auth): add unit tests for login service
chore(deps): update react to v18.2.0
Branch Naming Conventions

# Feature branches
feature/user-authentication
feat/add-payment-gateway

# Bugfix branches
bugfix/login-validation-error
fix/responsive-layout-issue

# Release branches
release/v1.2.0
release/2023.10.15

# Hotfix branches
hotfix/security-vulnerability
hotfix/critical-bug-fix

# Task branches
task/update-dependencies
task/code-cleanup
Git Best Practices
  • Commit often with small, logical changes
  • Write clear, descriptive commit messages
  • Use branches for features and bug fixes
  • Keep the main branch stable and deployable
  • Use pull requests for code review
  • Resolve conflicts as soon as possible
  • Use .gitignore to exclude unnecessary files
  • Regularly pull changes from the main branch
  • Use semantic versioning for releases
  • Document your workflow for the team
Git Hooks

Git hooks allow you to run custom scripts at certain points in the Git workflow:


# List available hooks
ls .git/hooks

# Enable a hook (remove .sample extension)
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit

# Example pre-commit hook to run tests
#!/bin/sh
npm test
RESULT=$?
if [ $RESULT -ne 0 ]; then
  echo "Tests failed. Commit aborted."
  exit 1
fi
Module 9: GitHub Actions and CI/CD Basics
What is GitHub Actions?

GitHub Actions is a CI/CD (Continuous Integration/Continuous Deployment) platform that allows you to automate your build, test, and deployment pipeline directly in your GitHub repository.

Key Concepts
  • Workflow: A configurable automated process
  • Event: An activity that triggers a workflow
  • Job: A set of steps in a workflow
  • Step: A single task that can run commands
  • Action: A custom application for the GitHub Actions platform
  • Runner: A server that runs your workflows
Creating a Simple Workflow

Create a .github/workflows/main.yml file:


name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs
jobs:
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3

      # Runs a single command using the runners shell
      - name: Run a one-line script
        run: echo Hello, world!

      # Runs a set of commands using the runners shell
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
Node.js CI/CD Workflow

name: Node.js CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [14.x, 16.x, 18.x]

    steps:
    - uses: actions/checkout@v3
    
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test
    
    - name: Upload coverage reports
      uses: codecov/codecov-action@v3
      with:
        file: ./coverage/lcov.info
Python CI/CD Workflow

name: Python CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [3.8, 3.9, "3.10", "3.11"]

    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}
    
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install pytest pytest-cov
    
    - name: Run tests
      run: |
        pytest --cov=./ --cov-report=xml
    
    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v3
Deploying to GitHub Pages

name: Deploy to GitHub Pages

on:
  push:
    branches: [ main ]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v3
    
    - name: Setup Pages
      uses: actions/configure-pages@v3
    
    - name: Build with Jekyll
      uses: actions/jekyll-build-pages@v1
      with:
        source: ./
        destination: ./_site
    
    - name: Upload artifact
      uses: actions/upload-pages-artifact@v2

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
    - name: Deploy to GitHub Pages
      id: deployment
      uses: actions/deploy-pages@v2
Docker Build and Push

name: Docker Build and Push

on:
  push:
    branches: [ main ]
    tags: [ 'v*.*.*' ]
  pull_request:
    branches: [ main ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push-image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Log in to the Container registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
Using Secrets in Workflows

Store sensitive information in repository secrets:

  1. Go to your repository settings
  2. Click "Secrets" in the left sidebar
  3. Click "New repository secret"
  4. Add your secret (e.g., API_KEY, PASSWORD)

name: Use Secrets

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Use secret
      env:
        API_KEY: ${{ secrets.API_KEY }}
      run: |
        echo "Using API key (but not showing it)"
        # Use the API key in your commands
Scheduling Workflows

name: Scheduled Tasks

on:
  schedule:
    # Run at 00:00 UTC every day
    - cron: '0 0 * * *'
  workflow_dispatch:

jobs:
  run-scheduled-task:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Run scheduled task
      run: |
        echo "Running scheduled task"
        # Add your task here
Using Marketplace Actions

Find pre-built actions in the GitHub Marketplace:


name: Use Marketplace Actions

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    # Send a Slack notification
    - name: Send Slack notification
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        channel: '#deployments'
        webhook_url: ${{ secrets.SLACK_WEBHOOK }}
    
    # Create a release
    - 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
Module 10: Advanced Git Techniques and Troubleshooting
Advanced Git Techniques
Interactive Rebase

Interactive rebase allows you to rewrite commit history:


# Start an interactive rebase for the last 3 commits
git rebase -i HEAD~3

# Commands available in interactive rebase:
# pick: use the commit
# reword: use the commit, but edit the commit message
# edit: use the commit, but stop for amending
# squash: use the commit, but meld into previous commit
# fixup: like squash, but discard this commit's log message
# exec: run command (the rest of the line) using shell
# drop: remove commit
Bisecting

Use binary search to find the commit that introduced a bug:


# Start bisecting
git bisect start

# Mark the current commit as bad
git bisect bad

# Mark a known good commit
git bisect good v1.0.0

# Git will checkout a commit in the middle
# Test the code and mark as good or bad
git bisect good  # or git bisect bad

# Continue until the bad commit is found
# Once found, you can examine the commit or fix it

# End bisecting and return to original state
git bisect reset
Reflog

Reference log (reflog) tracks all movements of HEAD and branch references:


# Show the reflog
git reflog

# Show the reflog for a specific branch
git reflog main

# Restore a lost commit using reflog
git checkout HEAD@{2}

# Reset to a previous state using reflog
git reset --hard HEAD@{5}
Submodules

Submodules allow you to keep a Git repository as a subdirectory of another Git repository:


# Add a submodule
git submodule add https://github.com/user/repo.git path/to/submodule

# Clone a repository with submodules
git clone --recursive https://github.com/user/main-repo.git

# Initialize and update submodules in an existing repository
git submodule update --init --recursive

# Update all submodules to their latest commits
git submodule update --remote

# Remove a submodule
git submodule deinit path/to/submodule
git rm path/to/submodule
rm -rf .git/modules/path/to/submodule
Worktrees

Worktrees allow you to check out multiple branches into different directories:


# Create a new worktree for a branch
git worktree add ../feature-branch feature-branch

# List all worktrees
git worktree list

# Remove a worktree
git worktree remove ../feature-branch

# Prune stale worktree information
git worktree prune
Troubleshooting Common Issues
Undoing a Pushed Commit

# If the commit is the most recent:
git reset --hard HEAD~1
git push --force-with-lease

# If the commit is not the most recent:
git rebase -i HEAD~n  # where n is the number of commits back
# Mark the commit as 'drop' in the editor
git push --force-with-lease
Recovering a Deleted Branch

# Find the commit hash of the deleted branch
git reflog

# Recreate the branch
git branch branch-name commit-hash
Resolving Merge Conflicts

# When you encounter a merge conflict:

# 1. Check which files have conflicts
git status

# 2. Open the conflicted files and resolve conflicts
# Look for <<<<<<<, =======, and >>>>>>> markers

# 3. After resolving conflicts, mark them as resolved
git add path/to/resolved/file.js

# 4. Continue the merge
git commit

# 5. If you want to abort the merge
git merge --abort
Fixing a Broken Repository

# Check repository integrity
git fsck

# Fix dangling objects
git fsck --lost-found

# If you have a corrupted object, try to recover it
# First, identify the corrupted object
git fsck --full

# Then try to restore it from a backup or remote
git fetch origin
git reset --hard origin/main
Dealing with Large Files

# Use Git LFS (Large File Storage) for large files
# Install Git LFS first
git lfs install

# Track specific file types
git lfs track "*.psd"
git lfs track "*.zip"

# Add .gitattributes to repository
git add .gitattributes
git commit -m "Configure Git LFS"

# Add and commit large files as normal
git add large-file.zip
git commit -m "Add large file"
git push
Performance Optimization

# Speed up Git operations
git config --global core.preloadindex true
git config --global core.fscache true
git config --global gc.auto 256

# Clean up unnecessary files and optimize the repository
git gc --aggressive --prune=now

# Check for large files that might be slowing down operations
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sed -n 's/^blob //p' | sort --numeric-sort --key=2 | tail -10
Advanced Git Configuration

# Configure diff and merge tools
git config --global diff.tool meld
git config --global merge.tool meld
git config --global difftool.prompt false

# Configure aliases for common commands
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.cm commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.visual '!gitk'

# Configure rebase behavior
git config --global pull.rebase true
git config --global rebase.autosquash true