Skip to content

Git & GitHub — Workflows, Branching, CI & Advanced Git

DodaTech Updated 2026-06-22 7 min read

In this tutorial, you'll learn about Git & GitHub. We cover key concepts, practical examples, and best practices.

Git workflows define how teams collaborate on code. Choosing the right branching strategy prevents merge conflicts, enables continuous integration, and keeps your history clean.

What You'll Learn

In this tutorial, you'll learn Git branching strategies including Git Flow, GitHub Flow, trunk-based development, rebase vs merge, CI/CD integration, submodules, Git hooks, and advanced commands for rewriting history and debugging.

Why It Matters

A team without a consistent Git workflow wastes hours resolving merge conflicts, loses commits in noisy histories, and struggles to release hotfixes quickly. The right workflow scales from solo developers to enterprise teams of hundreds.

Real-World Use

Durga Antivirus Pro uses a variant of GitHub Flow: feature branches off main, automatic CI checks on every push, squash-merge to main, and tag-based releases. This enables 20+ developers to ship daily without merge conflicts.

flowchart LR
  A[main] --> B[feature/scan-engine]
  A --> C[feature/ui-refactor]
  B --> D[PR + CI Checks]
  C --> E[PR + CI Checks]
  D --> F[Main (squash-merge)]
  E --> F
  F --> G[Release Tag v2.1.0]
  G --> H[Production Deploy]

Git Workflow Comparison

Workflow Branch Structure Merge Strategy Best For
GitHub Flow feature branches off main Squash-merge Continuous delivery teams
Git Flow develop, feature, release, hotfix Merge commit Release-cycle projects
Trunk-Based Short-lived feature branches off main Rebase or squash CI/CD with fast feedback
GitLab Flow feature, environment, release branches Merge commit with rebase Teams with staging environments
Forking Workflow Fork + feature branches Merge commit or rebase Open-source contributions

Git Branching Strategies

GitHub Flow

The simplest workflow: create a branch, commit changes, open a pull request, merge to main after CI passes.

# Create a feature branch
git checkout -b feat/real-time-scanning
# Make changes and commit
git add . && git commit -m "Add real-time file scanning module"
# Push and open PR
git push -u origin feat/real-time-scanning

Expected behavior: GitHub prompts you to create a pull request. CI runs tests automatically. After approval, squash-merge to main.

Git Flow

More structured — uses develop as the integration branch and main for production releases.

# Start a feature
git flow feature start scan-scheduler
# After completion, finish the feature
git flow feature finish scan-scheduler
# Start a release
git flow release start v2.1.0
# Finish and tag
git flow release finish v2.1.0

Expected behavior: The feature branch merges into develop, and when you finish a release, it merges into both main and develop with a version tag.

Trunk-Based Development

Short-lived branches (less than a day) merged directly to main. Feature flags hide incomplete work.

# Short-lived branch
git checkout -b fix/scan-timeout
# CI runs immediately
git push origin fix/scan-timeout
# Quick review, merge, delete
git checkout main && git merge --squash fix/scan-timeout
git branch -D fix/scan-timeout

Expected behavior: Branches live hours, not days. Main is always deployable. Feature flags gate incomplete features in production.

Merge vs Rebase

Merge Commits

Preserves the exact history of when branches diverged and merged.

git checkout main && git merge feature/real-time-scanning

Expected output: A merge commit appears with two parents, showing the branch was merged. Useful for audit trails.

Rebase

Rewrites history to create a linear sequence of commits.

git checkout feature/real-time-scanning
git rebase main
# Now the feature commits appear after the latest main commit

Expected behavior: git log --oneline shows a straight line. No merge commits. Safer for private branches; dangerous for shared branches.

Interactive Rebase

Squash, reword, reorder, or split commits.

git rebase -i HEAD~5
# Editor opens with:
# pick abc123 Add scanner module
# squash def456 Fix scanner bug
# reword 789ghi Update README
# Save and close

Expected behavior: Five commits become three (or however many you choose). The commit messages are combined or rewritten.

Advanced Git Commands

Bisect — Find the Commit That Introduced a Bug

# Start bisect with known bad and good commits
git bisect start
git bisect bad v2.0.0        # Current version is broken
git bisect good v1.9.0       # Last known good version
# Git checks out the midpoint commit
# Test it, then mark:
git bisect good              # or git bisect bad
# Repeat until the first bad commit is identified
git bisect reset

Expected output: abc123def is the first bad commit — the exact commit that introduced the bug.

Git Hooks

# pre-commit hook: run linter before every commit
# File: .git/hooks/pre-commit (make executable)
#!/bin/sh
npm run lint
if [ $? -ne 0 ]; then
  echo "Lint failed. Commit rejected."
  exit 1
fi

Expected behavior: Every git commit runs the linter first. If it fails, the commit is aborted.

Submodules — Managing External Dependencies

# Add a submodule
git submodule add https://github.com/example/scan-engine.git lib/scan-engine
# Clone a repo with submodules
git clone --recursive https://github.com/team/project.git
# Update submodules
git submodule update --remote

Expected behavior: The submodule is pinned to a specific commit in the parent repo. git submodule update --remote pulls the latest from the submodule's default branch.

CI/CD Integration

GitHub Actions with Branch Protection

# .github/workflows/ci.yml
name: CI
on:
  pull_request:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm test
      - run: npm run build

Expected behavior: Every PR triggers this workflow. If tests or build fail, the PR cannot be merged (assuming branch protection rules are enabled).

Common Errors

  1. Merging main into a long-lived feature branch repeatedly — Each merge creates noise. Instead, rebase the feature branch onto main weekly.
  2. Rebasing a shared branch — If others have pushed to the branch, rebase creates divergent history. Use merge instead.
  3. Force-pushing to maingit push --force rewrites history others may have pulled. Use --force-with-lease as a safety check.
  4. Large files in Git — Binaries, dependencies, and build artifacts bloat the repo. Use .gitignore and consider Git LFS for large assets.
  5. Committing sensitive data — API keys, passwords, and secrets in git history are permanent even if removed later. Use pre-commit hooks to scan for secrets.

Practice Questions

  1. What is the difference between git merge and git rebase? Merge creates a merge commit preserving branch history; rebase rewrites commit history to appear linear. Use merge for shared branches, rebase for private branches.

  2. When should you use Git Flow vs GitHub Flow? Git Flow is suited for projects with scheduled releases and hotfixes. GitHub Flow is better for continuous deployment where every commit to main can go to production.

  3. How do you remove the last commit without losing changes? git reset --soft HEAD~1 removes the commit but keeps changes staged. git reset --hard HEAD~1 removes both commit and changes permanently.

  4. What does git bisect do? It performs a binary search through commit history to find the exact commit that introduced a bug. You mark commits as good or bad until Git pinpoints the offender.

Challenge

Write a bash script that automates the Git Flow release process: creates a release branch from develop, bumps the version in package.json, creates a changelog entry from commit messages since the last tag, opens a PR, and tags the merge commit on main.

Mini Project: Git Workflow for a Security Tool

Build a simulated Git workflow for a multi-team antivirus project:

  1. Create a repo with main and develop branches
  2. Feature branch feat/heuristic-engine — add a heuristic analysis module, commit with conventional commits (feat:, fix:, chore:)
  3. Open a PR, add a simulated review approval, merge with squash
  4. Create a hotfix/critical-cve branch from main, fix, and merge to both main and develop
  5. Tag the release as v3.0.0
  6. Generate a changelog from commit messages

This mirrors Durga Antivirus Pro's release process and builds muscle memory for real team workflows.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro