Saturday, September 19, 2026

PROFESSIONAL GIT AND GITHUB IN A NUTSHELL

 




INTRODUCTION

Even if you are using Git and GitHub daily in your job, it is hard to remember all git commands and best practices. I have collected a set of best practices in this small document, so that I do not have to remember all Git commands or look them up in one of those multi hundred pages books. Maybe, this Nutshell is also helpful for your work.


Welcome to the complete guide for mastering Git and GitHub in professional software development. This curriculum assumes no prior knowledge and will take you from absolute beginner to advanced practitioner through carefully structured modules. Each section builds upon previous knowledge with real-world examples and production-ready code.


Git is a distributed version control system that tracks changes in source code during software development. GitHub is a web-based platform that hosts Git repositories and provides collaboration tools. Together, they form the backbone of modern software development workflows.


MODULE 1: FUNDAMENTAL CONCEPTS


What is Version Control?

Version control is a system that records changes to files over time so that you can recall specific versions later. Imagine writing a novel where you want to keep every draft, see what changed between drafts, and potentially revert to an earlier version if needed. Git does this for code.


The Three States of Git

Git has three main states that your files can reside in: modified, staged, and committed. Modified means you have changed the file but not committed it to your database yet. Staged means you have marked a modified file in its current version to go into your next commit snapshot. Committed means the data is safely stored in your local database.


Your First Git Repository

Let us start by creating a new project directory and initializing it as a Git repository. This is the foundation of every Git project.



# Create a new directory for our project

mkdir professional-web-app

cd professional-web-app


# Initialize a new Git repository

git init


# Check the status of our repository

git status



The output will show that we are on the master branch (or main branch in newer Git versions) with no commits yet. This is our starting point.


Configuring Git Identity

Before making any commits, we need to configure Git with our identity. This information will be attached to every commit we make.



# Set your name and email globally
git config --global user.name "Your Full Name"
git config --global user.email "your.email@company.com"
# Verify the configuration
git config --global user.name
git config --global user.email



MODULE 2: BASIC WORKFLOW MASTERY


Creating Meaningful Files

Let us create a simple web application structure to work with. This represents a real project that you might encounter in professional development.



# Create project structure

mkdir src

mkdir tests

mkdir docs


# Create a main application file

cat > src/app.js << 'EOF'

/**

 * Professional Web Application

 * Main application entry point

 * 

 * @author Your Name

 * @version 1.0.0

 */


const express = require('express');

const app = express();

const PORT = process.env.PORT || 3000;


// Middleware setup

app.use(express.json());

app.use(express.static('public'));


// Health check endpoint

app.get('/health', (req, res) => {

    res.json({ 

        status: 'healthy', 

        timestamp: new Date().toISOString(),

        uptime: process.uptime()

    });

});


// Main route

app.get('/', (req, res) => {

    res.json({ 

        message: 'Welcome to Professional Web App',

        version: '1.0.0'

    });

});


// Error handling middleware

app.use((err, req, res, next) => {

    console.error(err.stack);

    res.status(500).json({ error: 'Something went wrong!' });

});


// Start server

if (require.main === module) {

    app.listen(PORT, () => {

        console.log(`Server running on port ${PORT}`);

    });

}


module.exports = app;

EOF


# Create package.json

cat > package.json << 'EOF'

{

  "name": "professional-web-app",

  "version": "1.0.0",

  "description": "A production-ready web application demonstrating Git best practices",

  "main": "src/app.js",

  "scripts": {

    "start": "node src/app.js",

    "dev": "nodemon src/app.js",

    "test": "jest",

    "lint": "eslint src/**/*.js"

  },

  "keywords": ["web", "express", "nodejs"],

  "author": "Your Name",

  "license": "MIT",

  "dependencies": {

    "express": "^4.18.2"

  },

  "devDependencies": {

    "nodemon": "^3.0.1",

    "jest": "^29.7.0",

    "eslint": "^8.50.0"

  }

}

EOF



Understanding the Staging Area

The staging area is like a preparation zone where you compose your next commit. Think of it as a shopping cart where you collect items before checking out.



# Check what files are untracked

git status


# Add specific files to staging area

git add src/app.js

git add package.json


# Or add all files at once

git add .


# See what is staged

git diff --staged



Making Your First Commit

A commit is like taking a snapshot of your project at a specific point in time. Each commit has a unique identifier and contains the changes you have staged.



# Create a meaningful commit

git commit -m "Initial project setup with Express.js web application


- Added main application file with health check endpoint

- Configured package.json with production dependencies

- Set up basic project structure with src, tests, and docs directories

- Included error handling and proper server startup logic"


# View commit history

git log --oneline



MODULE 3: BRANCHING STRATEGIES


Understanding Branches

Branches in Git allow you to diverge from the main line of development and work on features or fixes in isolation. Think of branches as parallel universes where you can experiment without affecting the stable version of your code.


Creating and Switching Branches

Let us create a feature branch for adding user authentication to our application.


# Create and switch to a new branch

git checkout -b feature/user-authentication


# Verify current branch

git branch


# Create authentication module

cat > src/auth.js << 'EOF'

/**

 * Authentication Module

 * Handles user authentication and authorization

 * 

 * @module auth

 */


const bcrypt = require('bcrypt');

const jwt = require('jsonwebtoken');


class AuthService {

    constructor() {

        this.users = new Map();

        this.secretKey = process.env.JWT_SECRET || 'your-secret-key-change-in-production';

    }


    /**

     * Register a new user

     * @param {string} username - The username

     * @param {string} password - The plain text password

     * @returns {Object} User object without password

     */

    async register(username, password) {

        if (this.users.has(username)) {

            throw new Error('Username already exists');

        }


        const hashedPassword = await bcrypt.hash(password, 10);

        const user = {

            id: Date.now().toString(),

            username,

            password: hashedPassword,

            createdAt: new Date().toISOString()

        };


        this.users.set(username, user);

        

        // Return user without password

        const { password: _, ...userWithoutPassword } = user;

        return userWithoutPassword;

    }


    /**

     * Authenticate a user

     * @param {string} username - The username

     * @param {string} password - The plain text password

     * @returns {string} JWT token

     */

    async login(username, password) {

        const user = this.users.get(username);

        if (!user) {

            throw new Error('User not found');

        }


        const isValidPassword = await bcrypt.compare(password, user.password);

        if (!isValidPassword) {

            throw new Error('Invalid password');

        }


        return jwt.sign(

            { userId: user.id, username: user.username },

            this.secretKey,

            { expiresIn: '24h' }

        );

    }


    /**

     * Verify a JWT token

     * @param {string} token - The JWT token

     * @returns {Object} Decoded token payload

     */

    verifyToken(token) {

        try {

            return jwt.verify(token, this.secretKey);

        } catch (error) {

            throw new Error('Invalid token');

        }

    }

}


module.exports = AuthService;

EOF


# Update package.json to include new dependencies

# First, let's see the current state

git status


# Stage and commit the authentication feature

git add src/auth.js

git commit -m "Add user authentication service


- Implemented AuthService class with register, login, and verifyToken methods

- Added bcrypt for password hashing with salt rounds of 10

- Integrated JWT token generation with 24-hour expiration

- Included comprehensive JSDoc documentation

- Prepared for environment variable configuration"



Merging Branches

After completing work on a feature branch, we merge it back into the main branch. This integrates our changes into the stable codebase.



# Switch back to main branch

git checkout main


# Merge the feature branch

git merge feature/user-authentication


# Delete the feature branch (optional)

git branch -d feature/user-authentication



MODULE 4: COLLABORATIVE WORKFLOWS


Setting Up GitHub

GitHub extends Git with collaboration features. First, create a GitHub account and set up SSH keys for secure communication.


# Generate SSH key pair

ssh-keygen -t ed25519 -C "your.email@company.com"


# Start SSH agent and add key

eval "$(ssh-agent -s)"

ssh-add ~/.ssh/id_ed25519


# Copy public key to clipboard

cat ~/.ssh/id_ed25519.pub



Add the public key to your GitHub account under Settings > SSH and GPG keys.


Connecting Local Repository to GitHub

Create a new repository on GitHub named "professional-web-app" (without README), then connect your local repository.



# Add remote repository

git remote add origin git@github.com:yourusername/professional-web-app.git


# Push code to GitHub

git push -u origin main


Pull Requests and Code Reviews

In professional development, we use pull requests to propose changes and conduct code reviews before merging.



# Create a new feature branch

git checkout -b feature/add-database


# Add database configuration

cat > src/database.js << 'EOF'

/**

 * Database Configuration Module

 * Handles database connections and operations

 * 

 * @module database

 */


const sqlite3 = require('sqlite3').verbose();

const path = require('path');


class DatabaseService {

    constructor() {

        this.db = null;

        this.dbPath = process.env.DB_PATH || path.join(__dirname, '../data/app.db');

    }


    /**

     * Initialize database connection

     * @returns {Promise} Database connection promise

     */

    async connect() {

        return new Promise((resolve, reject) => {

            this.db = new sqlite3.Database(this.dbPath, (err) => {

                if (err) {

                    reject(err);

                } else {

                    console.log('Connected to SQLite database');

                    this.initializeTables();

                    resolve(this.db);

                }

            });

        });

    }


    /**

     * Initialize database tables

     */

    initializeTables() {

        const createUsersTable = `

            CREATE TABLE IF NOT EXISTS users (

                id TEXT PRIMARY KEY,

                username TEXT UNIQUE NOT NULL,

                password TEXT NOT NULL,

                created_at DATETIME DEFAULT CURRENT_TIMESTAMP

            )

        `;


        this.db.run(createUsersTable, (err) => {

            if (err) {

                console.error('Error creating users table:', err);

            } else {

                console.log('Users table ready');

            }

        });

    }


    /**

     * Close database connection

     */

    close() {

        if (this.db) {

            this.db.close((err) => {

                if (err) {

                    console.error('Error closing database:', err);

                } else {

                    console.log('Database connection closed');

                }

            });

        }

    }

}


module.exports = DatabaseService;

EOF


# Create data directory

mkdir data


# Update .gitignore to exclude sensitive files

cat > .gitignore << 'EOF'

# Dependencies

node_modules/


# Environment variables

.env


# Database files

data/*.db


# Logs

*.log

logs/


# Runtime data

pids/

*.pid

*.seed


# Coverage directory used by tools like istanbul

coverage/


# IDE

.vscode/

.idea/


# OS

.DS_Store

Thumbs.db

EOF


# Stage and commit changes

git add .

git commit -m "Add SQLite database service with user table


- Implemented DatabaseService class for SQLite operations

- Added automatic table initialization for users

- Configured .gitignore to exclude sensitive files

- Prepared for environment-based configuration

- Added proper error handling and connection management"



MODULE 5: ADVANCED GIT FEATURES


Interactive Rebase

Interactive rebase allows you to rewrite commit history for a cleaner project history. This is useful before merging feature branches.



# Start interactive rebase for last 3 commits

git rebase -i HEAD~3


# The editor will open with options like:

# pick, reword, edit, squash, fixup, drop

# Save and close to apply changes


Cherry-Picking

Cherry-picking allows you to apply specific commits from one branch to another without merging entire branches.


# Find the commit hash you want to cherry-pick

git log --oneline


# Cherry-pick a specific commit

git cherry-pick abc123def456


Stashing Changes

Stashing temporarily shelves changes so you can work on something else, then return to them later.


# Stash current changes

git stash save "Work in progress on user profile feature"


# List stashes

git stash list


# Apply most recent stash

git stash pop


# Apply specific stash

git stash apply stash@{2}



MODULE 6: COLLABORATION BEST PRACTICES


Fork and Clone Workflow

When contributing to open-source projects or working with restricted repositories, you use the fork and clone workflow.



# Fork repository on GitHub web interface

# Then clone your fork

git clone git@github.com:yourusername/some-open-source-project.git


# Add upstream remote

git remote add upstream git@github.com:originalauthor/some-open-source-project.git


# Keep fork updated

git fetch upstream

git checkout main

git merge upstream/main



Issue Tracking Integration

Link commits to GitHub issues for better project management.



# Commit that fixes an issue

git commit -m "Fix user authentication bypass vulnerability


- Added input validation for all authentication endpoints

- Implemented rate limiting to prevent brute force attacks

- Added comprehensive security tests

- Fixes #42"



MODULE 7: CONTINUOUS INTEGRATION


GitHub Actions Setup

GitHub Actions automate testing and deployment workflows. Create a workflow file:


# Create GitHub Actions directory

mkdir -p .github/workflows


# Create CI/CD workflow

cat > .github/workflows/ci.yml << 'EOF'

name: CI/CD Pipeline


on:

  push:

    branches: [ main, develop ]

  pull_request:

    branches: [ main ]


jobs:

  test:

    runs-on: ubuntu-latest

    

    strategy:

      matrix:

        node-version: [16.x, 18.x, 20.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'

    

    - name: Install dependencies

      run: npm ci

    

    - name: Run linter

      run: npm run lint

    

    - name: Run tests

      run: npm test

    

    - name: Build application

      run: npm run build

    

    - name: Upload coverage reports

      uses: codecov/codecov-action@v3

      if: matrix.node-version == '18.x'

EOF


# Commit the workflow

git add .github/workflows/ci.yml

git commit -m "Add GitHub Actions CI/CD pipeline


- Configured automated testing for Node.js 16, 18, and 20

- Added linting and build steps

- Integrated Codecov for coverage reporting

- Runs on push to main/develop and all pull requests"



MODULE 8: RELEASE MANAGEMENT


Semantic Versioning

Use semantic versioning (SemVer) for releases: MAJOR.MINOR.PATCH.



# Create a release branch

git checkout -b release/v1.1.0


# Update version in package.json

# Then commit

git commit -am "Bump version to 1.1.0"


# Create annotated tag

git tag -a v1.1.0 -m "Release version 1.1.0


- Added user authentication system

- Implemented SQLite database support

- Enhanced security features

- Improved error handling"


# Push tag to GitHub

git push origin v1.1.0



MODULE 9: ADVANCED COLLABORATION



Code Review Guidelines

When reviewing pull requests, focus on:


1. Code quality and maintainability

2. Security considerations

3. Performance implications

4. Test coverage

5. Documentation completeness


Example review comment:


This authentication implementation looks solid! However, I recommend:

- Adding rate limiting middleware to prevent brute force attacks

- Using environment variables for JWT secret configuration

- Adding unit tests for edge cases (empty passwords, SQL injection attempts)

- Consider using async/await consistently throughout the codebase



Branch Protection Rules

Set up branch protection on GitHub to enforce quality standards:


1. Require pull request reviews before merging

2. Require status checks to pass

3. Require branches to be up to date before merging

4. Restrict pushes that create files larger than 100MB


MODULE 10: TROUBLESHOOTING COMMON ISSUES


Recovering from Mistakes

If you accidentally committed sensitive data:


# Remove sensitive file from history

git filter-branch --force --index-filter \

"git rm --cached --ignore-unmatch path/to/sensitive/file" \

--prune-empty --tag-name-filter cat -- --all


# Force push to update remote

git push origin --force --all


Resolving Merge Conflicts

When Git cannot automatically merge changes:



# During merge, conflicts will be marked

# Edit files to resolve conflicts

# Then stage resolved files

git add path/to/resolved/file.js


# Complete the merge

git commit -m "Resolve merge conflicts in authentication module"



MODULE 11: PERFORMANCE OPTIMIZATION


Repository Size Management

Keep repositories lean for better performance:


# Check repository size

git count-objects -vH


# Remove large files from history

git filter-branch --tree-filter 'rm -f path/to/large/file.zip' HEAD


# Use Git LFS for large files

git lfs track "*.zip"

git lfs track "*.mp4"

git add .gitattributes


Submodule Management

For projects with dependencies:


# Add a submodule

git submodule add https://github.com/company/shared-library.git lib/shared


# Initialize submodules after clone

git submodule update --init --recursive


# Update submodule to latest commit

cd lib/shared

git pull origin main

cd ../..

git add lib/shared

git commit -m "Update shared library to latest version"


MODULE 12: SECURITY BEST PRACTICES



Secret Management

Never commit secrets to Git:


# Create .env.example for documentation

cat > .env.example << 'EOF'

# Database Configuration

DB_PATH=./data/app.db


# JWT Configuration

JWT_SECRET=your-jwt-secret-here


# Server Configuration

PORT=3000

NODE_ENV=development

EOF


# Add .env to .gitignore (already done)

# Use environment variables in code

const jwtSecret = process.env.JWT_SECRET || 'fallback-for-dev-only';


Signed Commits

Use GPG signing for verified commits:


# Generate GPG key

gpg --full-generate-key


# Configure Git to use GPG key

git config --global user.signingkey YOUR_GPG_KEY_ID

git config --global commit.gpgsign true


# Make signed commit

git commit -S -m "Add secure payment processing module"



MODULE 13: WORKFLOW OPTIMIZATION


Git Aliases

Create shortcuts for common commands:



# Set up useful aliases

git config --global alias.co checkout

git config --global alias.br branch

git config --global alias.ci commit

git config --global alias.st status

git config --global alias.unstage 'reset HEAD --'

git config --global alias.last 'log -1 HEAD'

git config --global alias.visual '!gitk'

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"


# Use aliases

git st

git lg



Pre-commit Hooks

Automate quality checks:


# Install pre-commit framework

npm install --save-dev husky lint-staged


# Set up husky

npx husky install


# Create pre-commit hook

cat > .husky/pre-commit << 'EOF'

#!/usr/bin/env sh

. "$(dirname -- "$0")/_/husky.sh"


npx lint-staged

EOF


# Configure lint-staged in package.json

# Add to package.json:

# "lint-staged": {

#   "*.js": ["eslint --fix", "git add"]

# }



MODULE 14: MONOREPO MANAGEMENT


Managing Large Projects

For projects with multiple packages:


# Create monorepo structure

mkdir -p packages/{web,api,shared}

git add packages/

git commit -m "Set up monorepo structure"


# Use workspaces in package.json

cat > package.json << 'EOF'

{

  "name": "professional-web-app",

  "version": "1.0.0",

  "private": true,

  "workspaces": [

    "packages/*"

  ],

  "scripts": {

    "dev": "concurrently \"npm run dev --workspace=packages/web\" \"npm run dev --workspace=packages/api\"",

    "test": "npm test --workspaces"

  }

}

EOF



MODULE 15: DEPLOYMENT STRATEGIES


GitHub Pages Deployment

For static sites:


# Create gh-pages branch

git checkout --orphan gh-pages

git rm -rf .


# Add deployment workflow

cat > .github/workflows/deploy.yml << 'EOF'

name: Deploy to GitHub Pages


on:

  push:

    branches: [ main ]


jobs:

  deploy:

    runs-on: ubuntu-latest

    steps:

    - uses: actions/checkout@v3

    

    - name: Setup Node.js

      uses: actions/setup-node@v3

      with:

        node-version: '18'

    

    - name: Install dependencies

      run: npm ci

    

    - name: Build

      run: npm run build

    

    - name: Deploy to GitHub Pages

      uses: peaceiris/actions-gh-pages@v3

      with:

        github_token: ${{ secrets.GITHUB_TOKEN }}

        publish_dir: ./dist

EOF


git add .github/workflows/deploy.yml

git commit -m "Add GitHub Pages deployment workflow"

git push -u origin gh-pages



Heroku Deployment

For Node.js applications:


# Create Procfile for Heroku

echo "web: node src/app.js" > Procfile


# Add Heroku remote

heroku create professional-web-app-demo

git remote add heroku https://git.heroku.com/professional-web-app-demo.git


# Deploy to Heroku

git push heroku main



MODULE 16: MAINTENANCE AND HOUSEKEEPING


Regular Repository Maintenance

Keep your repository healthy:


# Prune remote-tracking branches

git remote prune origin


# Garbage collect to optimize repository

git gc --aggressive


# Verify repository integrity

git fsck --full


# Clean untracked files (use carefully)

git clean -fd

# Preview what would be deleted

git clean -fdn



Documentation Standards

Maintain comprehensive documentation:


# Create comprehensive README

cat > README.md << 'EOF'

# Professional Web Application


A production-ready web application demonstrating Git and GitHub best practices.


## Getting Started


### Prerequisites

- Node.js 16 or higher

- npm or yarn


### Installation

1. Clone the repository

   git clone git@github.com:yourusername/professional-web-app.git

2. Install dependencies

   npm install

3. Set up environment variables

   cp .env.example .env

4. Start development server

   npm run dev


### Testing

npm test


### Deployment

This project uses GitHub Actions for CI/CD. Pushes to main branch automatically deploy to production.


## Architecture

- Express.js backend

- SQLite database

- JWT authentication

- RESTful API design

EOF


git add README.md

git commit -m "Add comprehensive project documentation"



MODULE 17: TEAM COLLABORATION-----


Scenario 1: Hotfix Production Issue

When critical bugs need immediate attention:



# Create hotfix branch from main

git checkout main

git pull origin main

git checkout -b hotfix/security-patch


# Make urgent fix

# ... fix the security vulnerability ...


# Test thoroughly

npm test


# Merge quickly

git checkout main

git merge hotfix/security-patch

git tag v1.0.1

git push origin main --tags



Scenario 2: Feature Development with Multiple Developers

Coordinating work on large features:


# Developer A starts feature

git checkout -b feature/payment-system

# ... works on payment processing ...


# Developer B joins the feature

git checkout feature/payment-system

git pull origin feature/payment-system

# ... works on payment UI ...


# Regular integration

git checkout feature/payment-system

git merge main

# Resolve any conflicts

git push origin feature/payment-system



Scenario 3: Release Management

Managing stable releases:


# Create release candidate

git checkout -b release/v2.0.0-rc1

# Final testing and bug fixes

# Update version numbers

git commit -am "Prepare release candidate 2.0.0-rc1"

git tag v2.0.0-rc1

git push origin v2.0.0-rc1


# After testing, create final release

git checkout main

git merge release/v2.0.0-rc1

git tag v2.0.0

git push origin main --tags



CONCLUSION AND NEXT STEPS

You have now completed a comprehensive curriculum covering professional Git and GitHub usage. The concepts and practices covered here form the foundation for effective software development in team environments.


Key takeaways for continued learning:

- Practice these workflows regularly in real projects

- Explore advanced Git features like bisect, reflog, and worktrees

- Contribute to open-source projects to gain collaborative experience

- Stay updated with Git and GitHub's evolving features

- Consider learning Git internals for deeper understanding


Remember that mastering Git is a journey. Start with the basics, gradually incorporate advanced features, and always prioritize clear communication with your team through meaningful commit messages and well-structured branches.


Your professional development workflow is now equipped with industry-standard practices that will serve you throughout your career in software development.