🚀 DevOps Training

Git Fundamentals
for DevOps Engineers

Complete hands-on guide from installation to CI/CD integration — every command, every workflow, spoon-fed.

13
Sections
4
Hands-On Labs
80+
Commands
100%
Practical

What You Will Learn

Install & configure Git on any OS
Understand Git's three-zone architecture
Perform the full commit lifecycle
Work with branches, merges & rebases
Collaborate using remotes & Pull Requests
Apply Git Flow & Trunk-Based Development
Integrate Git with CI/CD pipelines
Use advanced: stash, cherry-pick, bisect, hooks
01
Introduction to Git & Version Control
Why Git is the backbone of modern DevOps

What is Version Control?

Version Control Systems (VCS) track every change made to files over time, allowing teams to collaborate, revert mistakes, and maintain a full history of a project. In DevOps, VCS is the very first stage of the SDLC.

TypeDescriptionExamples
Local VCSTracks changes on a single machine onlyRCS
Centralized VCSSingle server holds all history; clients check out filesSVN, CVS
Distributed VCSEvery clone is a full repo with complete historyGit, Mercurial

Why Git in DevOps?

📦
Everything as Code
Infrastructure, configs, and pipelines all live in Git
📋
Audit Trail
Every change is signed, timestamped, and attributed to an author
CI/CD Trigger
A git push fires build, test, and deploy pipelines automatically
🌿
Branching Model
Isolate features, hotfixes, and releases cleanly in parallel
👥
Collaboration
Pull Requests, code reviews, and approvals are Git-native
Rollback
One command reverts a bad release to any previous state

Git Architecture — The Three Zones

Understanding Git's three-zone model is the most important concept. Every Git command moves changes between these zones:

Git Three-Zone Flow
✏️
Working Directory
Edit files here
git add
📋
Staging Area
Index / pre-commit buffer
git commit
🗄️
Local Repository
.git folder
git push
☁️
Remote Repository
GitHub / GitLab
💡
Key InsightGit never directly saves "changes". It saves complete snapshots of the entire project at each commit. Delta compression happens transparently in the object store.
02
Installation & Initial Configuration
Setting up Git on your machine for the first time

Installation

Linux (Ubuntu/Debian)

bash
$ sudo apt update && sudo apt install git -y
$ git --version          # verify installation

macOS

bash
$ brew install git       # via Homebrew (recommended)
# OR install Xcode Command Line Tools:
$ xcode-select --install

Windows

cmd
# Download Git for Windows from https://git-scm.com/download/win
# Run the installer — select 'Git Bash' and 'Git from command line'
> git --version

Global Configuration (Do This First!)

bash
# Set your identity (required — used in every commit)
$ git config --global user.name  "Your Full Name"
$ git config --global user.email "[email protected]"

# Set default branch name (modern standard)
$ git config --global init.defaultBranch main

# Set your preferred editor (VS Code shown)
$ git config --global core.editor "code --wait"

# Improve diff output with color
$ git config --global color.ui auto

# Configure line endings
$ git config --global core.autocrlf input    # macOS/Linux
$ git config --global core.autocrlf true     # Windows

# View all global settings
$ git config --global --list
Config Levels--system (all users), --global (your user), --local (this repo only). Local overrides global overrides system.

SSH Key Setup (for GitHub/GitLab)

bash
# Generate an SSH key pair
$ ssh-keygen -t ed25519 -C "[email protected]"

# Start the SSH agent and add your key
$ eval "$(ssh-agent -s)"
$ ssh-add ~/.ssh/id_ed25519

# Copy your PUBLIC key — paste into GitHub > Settings > SSH Keys
$ cat ~/.ssh/id_ed25519.pub

# Test the connection
$ ssh -T [email protected]
# Expected: Hi username! You've successfully authenticated...
03
Core Git Workflow
The fundamental add → commit → push cycle

Creating Your First Repository

Option A: Initialize from Scratch

bash
$ mkdir my-devops-project && cd my-devops-project
$ git init
# Output: Initialized empty Git repository in .../my-devops-project/.git/
$ ls -la          # confirms the hidden .git folder

Option B: Clone an Existing Repository

bash
# Clone via HTTPS
$ git clone https://github.com/username/repo-name.git

# Clone via SSH (recommended — no password prompts)
$ git clone [email protected]:username/repo-name.git

# Clone into a specific folder name
$ git clone [email protected]:username/repo-name.git my-folder

# Shallow clone (only latest snapshot — faster for large repos)
$ git clone --depth=1 [email protected]:username/repo-name.git

Status, Staging & Committing

bash
# Check what zone everything is in — run this constantly!
$ git status
$ git status -s           # compact format

# Stage files
$ git add index.html      # single file
$ git add .               # all changes in current dir
$ git add -p filename     # stage hunks interactively
$ git restore --staged filename  # unstage a file

# Commit staged changes
$ git commit -m "feat: add user authentication module"
$ git commit -am "fix: correct null pointer"  # stage tracked + commit
$ git commit --amend -m "corrected message"   # fix last commit (pre-push only)
📝
Conventional Commits FormatUse: type(scope): description — Types: feat, fix, docs, style, refactor, test, chore, ci, perf

Viewing History & Diffs

bash
$ git log                              # full log
$ git log --oneline                    # compact one-line
$ git log --oneline --graph --all --decorate  # visual graph
$ git log -5                           # last 5 commits
$ git log --author="John"             # by author
$ git log --since="2024-01-01"        # since date
$ git blame filename.py               # who changed each line

# Diffs
$ git diff                             # unstaged changes
$ git diff --staged                    # staged vs last commit
$ git diff main..feature-branch        # between branches

.gitignore — Excluding Files

.gitignore
# Dependencies
node_modules/
vendor/

# Build outputs
dist/
build/
*.jar

# Environment / Secrets — NEVER commit these!
.env
.env.local
*.pem
*.key

# OS files
.DS_Store
Thumbs.db

# Check if a file is ignored
$ git check-ignore -v filename
⚠️
Warninggit add . stages ALL files including secrets. Always set up a .gitignore before your first commit.
04
Branching & Merging
Isolate work, collaborate in parallel, merge safely

A branch is a lightweight, movable pointer to a commit. Creating a branch is instant and costs almost nothing in Git.

Branch & Merge Diagram
main
C1
C2
C3
C6 ✓
HEAD
feature
C4
C5

Branch Commands

bash
$ git branch                         # list local branches
$ git branch -a                      # list all (local + remote)
$ git checkout -b feature/user-login # create AND switch
$ git switch -c feature/user-login   # modern equivalent
$ git switch main                    # switch to existing branch
$ git branch -m old-name new-name    # rename a branch
$ git branch -d feature/user-login  # delete merged branch
$ git branch -D feature/user-login  # force delete
$ git branch --merged                # show merged branches

Merging & Conflict Resolution

bash
# Merge feature into main
$ git checkout main
$ git merge --no-ff feature/user-login   # always creates a merge commit

# === Resolving Merge Conflicts ===
# Step 1: See which files conflict
$ git status

# Step 2: Open the file — Git marks conflicts like this:
# <<<<<<< HEAD
# Your version
# =======
# Their version
# >>>>>>> feature/user-login

# Step 3: Edit the file to the desired final state
# Step 4: Stage the resolved file
$ git add app.js

# Step 5: Complete the merge
$ git commit

# Abort a merge entirely
$ git merge --abort

Rebase (Linear History)

bash
$ git checkout feature/my-feature
$ git rebase main               # rebase onto main tip

# Interactive rebase — squash/edit last 3 commits
$ git rebase -i HEAD~3
# Commands: pick, squash (s), fixup (f), reword (r), drop (d)

$ git rebase --continue          # after resolving conflict
$ git rebase --abort             # cancel rebase
🚫
Never Rebase Shared BranchesNEVER rebase commits already pushed to a shared remote branch. This rewrites history and breaks everyone else's copies.
05
Working with Remotes
Push, pull, fetch — collaborating via GitHub/GitLab
bash
# Remote management
$ git remote -v                               # list remotes
$ git remote add origin [email protected]:u/r.git # add remote
$ git remote set-url origin [email protected]:u/r.git # change URL

# Pushing
$ git push -u origin main      # first push — sets tracking
$ git push                     # subsequent pushes
$ git push -u origin feature/user-login  # push new branch
$ git push origin --delete feature/old   # delete remote branch

# Fetching & Pulling
$ git fetch origin             # download WITHOUT merging
$ git fetch --all              # fetch from all remotes
$ git pull                     # fetch + merge
$ git pull --rebase            # fetch + rebase (cleaner)
$ git config --global pull.rebase true  # set rebase as default

Pull Request Workflow

1
Create a feature branch from main
2
Make commits on the feature branch
3
Push: git push -u origin feature/my-feature
4
Open a Pull Request on GitHub/GitLab via the web UI
5
Assign reviewers — code review happens here
6
CI/CD pipeline runs automatically on the PR
7
After approval, merge the PR (squash, rebase, or merge commit)
8
Delete the feature branch on remote after merge
9
Update local: git checkout main && git pull
06
Tags & Releases
Marking versions in your history
bash
$ git tag                                       # list all tags
$ git tag -a v1.0.0 -m "Release version 1.0.0"  # annotated tag
$ git tag -a v0.9.0 abc1234 -m "Beta"          # tag a past commit
$ git push origin v1.0.0                        # push single tag
$ git push --tags                               # push all tags
$ git tag -d v1.0.0                             # delete local tag
$ git push origin --delete v1.0.0               # delete remote tag
$ git checkout v1.0.0                           # detached HEAD at tag
07
Undoing Changes & Recovery
Safely fix mistakes at every stage

Undo Decision Matrix

SituationCommand
Working dir — discard editsgit restore <file>
Staging — unstage a filegit restore --staged <file>
Last commit — amend itgit commit --amend (before pushing only)
Revert a commit (safe)git revert <hash> — creates new undo commit
Reset — move HEAD backgit reset (see below — use carefully)
Recover deleted commitsgit reflog + git cherry-pick <hash>

git reset — Three Modes

bash
# --soft: move HEAD back, keep staged changes
$ git reset --soft HEAD~1
# Use: "I want to redo my last commit message"

# --mixed (default): move HEAD back, unstage, keep files
$ git reset HEAD~1
# Use: "Re-organise what went into the last commit"

# --hard: move HEAD back, DISCARD ALL CHANGES (dangerous!)
$ git reset --hard HEAD~1
# Use: "Throw away the last commit entirely"
🚫
Warning: --hard is irreversiblegit reset --hard permanently discards uncommitted changes. Use git stash or git commit first if in doubt.

git reflog — Your Safety Net

bash
# Show the full history of every HEAD movement
$ git reflog
# abc1234 HEAD@{0}: commit: feat: add login
# def5678 HEAD@{1}: reset: moving to HEAD~1

# Recover a 'lost' commit after a bad reset
$ git checkout -b recovery-branch abc1234
Tipgit reflog is the ultimate undo. Almost nothing is permanently lost in Git within 90 days. Check reflog before panicking.
08
Advanced Git Commands
Power tools for professional workflows

git stash — Temporary Shelving

bash
$ git stash                              # stash all uncommitted work
$ git stash push -m "WIP: auth feature"  # stash with description
$ git stash list                         # view all stashes
$ git stash apply                        # apply latest, keep in list
$ git stash pop                          # apply AND remove from list
$ git stash apply stash@{2}              # apply specific stash
$ git stash drop stash@{0}               # delete a stash
$ git stash branch feature/new stash@{0} # create branch from stash

git cherry-pick — Port Specific Commits

bash
$ git cherry-pick abc1234           # apply a single commit
$ git cherry-pick abc1234^..def5678 # cherry-pick a range
$ git cherry-pick -n abc1234        # stage only, don't commit

# Use case: backport a hotfix to a release branch
$ git checkout release/1.5
$ git cherry-pick hotfix-commit-hash

git bisect — Binary Search for Bugs

bash
$ git bisect start            # start session
$ git bisect bad              # current HEAD has the bug
$ git bisect good v1.0.0      # this version was good
# Git checks out midpoint — test it, then:
$ git bisect good             # bug NOT here
$ git bisect bad              # bug IS here
# Git finds the exact first bad commit...
$ git bisect reset            # end session

Useful Aliases

bash
$ git config --global alias.st    status
$ git config --global alias.co    checkout
$ git config --global alias.br    branch
$ git config --global alias.lg    "log --oneline --graph --all --decorate"
$ git config --global alias.last  "log -1 HEAD"
$ git config --global alias.unstage "restore --staged"
09
Branching Strategies for DevOps
Git Flow, GitHub Flow, Trunk-Based Development
Git Flow
Release-Based
  • main — production only, tagged
  • develop — integration branch
  • feature/xxx — one per feature
  • release/x.y.z — only bug fixes
  • hotfix/xxx — emergency from main
GitHub Flow
CI/CD Friendly
  • Always branch from main
  • Descriptive branch names
  • Open PR early for discussion
  • CI runs on every PR
  • Merge to main = deploy
Trunk-Based Dev
High Velocity
  • Commit to main multiple times/day
  • Branches live < 2 days
  • Feature flags hide WIP
  • Requires solid CI/CD
  • Used by Google, Facebook

Git Flow in Practice

bash
# Start a feature
$ git checkout develop
$ git checkout -b feature/user-auth
# ... work, commit ...
$ git checkout develop && git merge --no-ff feature/user-auth
$ git branch -d feature/user-auth

# Create a release
$ git checkout -b release/2.0.0 develop
# ... only bug fixes ...
$ git checkout main && git merge --no-ff release/2.0.0
$ git tag -a v2.0.0 -m "Version 2.0.0"
$ git checkout develop && git merge --no-ff release/2.0.0

# Emergency hotfix
$ git checkout -b hotfix/critical-bug main
# ... fix ...
$ git checkout main && git merge --no-ff hotfix/critical-bug
$ git tag -a v2.0.1 -m "Hotfix 2.0.1"
$ git checkout develop && git merge --no-ff hotfix/critical-bug
10
Git in CI/CD Pipelines
How Git triggers and drives your DevOps automation
Git EventTypical Pipeline Action
git push to mainTriggers production deployment pipeline
git push to developTriggers integration test + staging deploy
Pull Request openedTriggers lint, unit tests, security scan
git tag v*.*.*Triggers release build + artifact packaging
Scheduled (cron)Nightly full regression test suites

GitHub Actions Example

.github/workflows/ci.yml
name: CI Pipeline

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

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build
        run: npm run build
11
Hands-On Labs
Step-by-step exercises to practice every concept
LAB 01
Your First Repository
bash
# 1. Create a folder and init git
$ mkdir git-lab && cd git-lab
$ git init

# 2. Create your first file
$ echo '# My Git Lab' > README.md

# 3. Check status
$ git status

# 4. Stage and commit
$ git add README.md
$ git commit -m "docs: initial commit with README"

# 5. View history
$ git log --oneline

# 6. Link to GitHub and push
$ git remote add origin [email protected]:YOUR_USERNAME/git-lab.git
$ git push -u origin main
LAB 02
Feature Branch Workflow
bash
# 1. Create a feature branch
$ git checkout -b feature/add-index

# 2. Create and commit files
$ echo '<html><body>Hello Git!</body></html>' > index.html
$ git add index.html && git commit -m "feat: add landing page"
$ echo 'body { font-family: sans-serif; }' > style.css
$ git add style.css && git commit -m "style: add base CSS"

# 3. View visual graph
$ git log --oneline --graph --all

# 4. Merge back to main
$ git checkout main
$ git merge --no-ff feature/add-index -m "merge: add-index feature"

# 5. Clean up and push
$ git branch -d feature/add-index && git push
LAB 03
Conflict Resolution
bash
# 1. On main, edit README.md
$ echo 'Version from main' > README.md
$ git add README.md && git commit -m 'main: update README'

# 2. Create a branch and edit the same line
$ git checkout -b conflict-branch HEAD~1
$ echo 'Version from branch' > README.md
$ git add README.md && git commit -m 'branch: update README'

# 3. Merge and observe conflict
$ git checkout main && git merge conflict-branch
# CONFLICT (content): Merge conflict in README.md

# 4. Open README.md, choose the final version, then:
$ git add README.md && git commit
LAB 04
Stash & Cherry-Pick
bash
# 1. Start work — don't commit yet
$ echo 'WIP code' > wip.js && git add wip.js

# 2. Urgent bug comes in — stash WIP
$ git stash push -m "WIP: in-progress JS module"

# 3. Fix the bug on main
$ git checkout main
$ echo 'bugfix' > bugfix.txt
$ git add bugfix.txt && git commit -m "fix: critical bug"

# 4. Cherry-pick that fix onto release branch
$ git checkout -b release/1.0.1
$ git cherry-pick <hash-from-step-3>

# 5. Restore WIP
$ git checkout feature/wip-branch && git stash pop
12
Best Practices for DevOps
Professional habits that separate great teams
✏️
Commit Hygiene
Small atomic commits. One logical change per commit. Use Conventional Commits format always.
🌿
Branch Discipline
Short-lived branches. Clear naming: feature/, fix/, hotfix/. Always branch from latest main.
🔒
Protect main
Require PR reviews, status checks, no force push. Branch protection rules on GitHub/GitLab.
🚫
No Secrets in Git
Never commit .env files or API keys. Use git-secrets or GitGuardian in CI to scan automatically.
🏷️
Tag Every Release
Tag every production release with a semantic version. Generate CHANGELOG from Conventional Commits.
📥
Pull with Rebase
Use git pull --rebase to keep history linear. Set pull.rebase=true globally for the team.
13
Common Issues & Troubleshooting
Diagnose and fix the most frequent Git problems
ProblemFix
Accidental commit to maingit reset --soft HEAD~1, then git checkout -b correct-branch
Committed a secret/passwordImmediately rotate the credential. Use BFG Repo Cleaner to purge history.
Wrong author on commitsgit commit --amend --author='Name <email>' (before push only)
Detached HEAD stategit checkout main to re-attach, or: git checkout -b new-branch to save work
Cannot push — rejectedgit pull --rebase origin main, resolve conflicts, then push
Accidentally deleted a branchgit reflog to find hash, git checkout -b recovered <hash>
Large file blocked by GitHubgit rm --cached largefile, add to .gitignore, use Git LFS
.gitignore not workingFile already tracked: git rm --cached filename first
Merge conflict in binary filegit checkout --ours file OR git checkout --theirs file
Pushed wrong code to maingit revert HEAD (safe) or coordinate with team before force pushing
You Are Now a Git Practitioner! 🎉
Refer to the Git Cheat Sheet for a quick-reference of all commands