01 What is Git?
Git is a distributed version control system — it tracks every change you make to files over time. Think of it as an intelligent, unlimited undo history for your entire project, shared across as many machines or collaborators as you like.
Repository (repo)
A folder that Git tracks. Contains all your project files plus a hidden .git/ folder storing the full history.
Commit
A snapshot of your files at a moment in time. Each commit has a unique ID (SHA hash) and a message you write.
Branch
An independent line of development. You can have dozens of branches, each with its own history.
Merge
Combining changes from one branch into another. Git is usually smart enough to do this automatically.
Remote
A copy of your repository hosted elsewhere — GitHub, GitLab, your own server. Used to collaborate and back up.
Staging Area
A holding area where you decide exactly which changes go into your next commit. Like a shopping basket before checkout.
The Three States
Every file in a Git project lives in one of three states:
files you edit
changes queued
history saved
shared online
02 Installing Git on Linux
Git is available in every major Linux distribution's package manager. Pick your distro below:
Ubuntu / Debian / Linux Mint
$ sudo apt update $ sudo apt install git Reading package lists... Done Building dependency tree... Done git is already the newest version (1:2.43.0-1ubuntu7).
Fedora / RHEL / Rocky Linux
$ sudo dnf install git
Arch / Manjaro
$ sudo pacman -S git
Verify Installation
$ git --version git version 2.43.0
03 First-Time Configuration
Before making any commits, tell Git who you are. This information is attached to every commit you create.
# Set your name and email (use same email as your GitHub account) $ git config --global user.name "Your Name" $ git config --global user.email "you@example.com" # Set your preferred editor (nano is beginner-friendly) $ git config --global core.editor nano # Name the default branch "main" (modern standard) $ git config --global init.defaultBranch main # View all your settings $ git config --list user.name=Your Name user.email=you@example.com core.editor=nano init.defaultBranch=main
--global flag saves settings to ~/.gitconfig, applying them to all your repos. You can override per-project by omitting --global inside a repo folder.
04 Core Workflow — The Basics
Starting a New Repository
# Create a new project folder and initialise Git $ mkdir my-project $ cd my-project $ git init Initialized empty Git repository in /home/user/my-project/.git/
Checking Status & Adding Files
# Check what Git sees $ git status On branch main Untracked files: index.html style.css # Stage a specific file $ git add index.html # Stage all changes at once $ git add . # See exactly what's staged vs unstaged $ git diff --staged
Making Commits
# Commit with a message (keep it short and descriptive) $ git commit -m "Add homepage and base stylesheet" [main (root-commit) a3f1d7e] Add homepage and base stylesheet 2 files changed, 47 insertions(+) # Stage ALL tracked files and commit in one step $ git commit -am "Fix typo in header"
Viewing History
# Full log $ git log # Compact one-liner view $ git log --oneline a3f1d7e Add homepage and base stylesheet d92c1b5 Initial commit # Beautiful graph view $ git log --oneline --graph --all
Undoing Things
# Unstage a file (keeps your changes) $ git restore --staged index.html # Discard changes in a file (PERMANENT — use with care) $ git restore index.html # Fix the last commit message (before pushing) $ git commit --amend -m "Corrected commit message" # Undo last commit but KEEP the changes in staging $ git reset --soft HEAD~1
Ignoring Files — .gitignore
Create a .gitignore file in your project root to tell Git which files to never track:
# Compiled outputs *.o *.pyc __pycache__/ dist/ # Environment & secrets — NEVER commit these! .env *.key *.pem # Editor / OS clutter .DS_Store .vscode/ Thumbs.db # Node / PHP dependencies node_modules/ vendor/
05 Branching & Merging
Branches let you work on features or fixes in isolation without disturbing the main codebase. They are cheap and fast in Git — use them liberally.
Creating & Switching Branches
# List all branches (* = current) $ git branch * main # Create and switch to a new branch $ git switch -c feature/contact-form Switched to a new branch 'feature/contact-form' # Switch back to main $ git switch main # Delete a branch (after it's merged) $ git branch -d feature/contact-form
Merging
# Make sure you're on the target branch (e.g. main) $ git switch main # Merge your feature branch into main $ git merge feature/contact-form Merge made by the 'ort' strategy. contact.html | 45 +++++++++++++++++++++ 1 file changed, 45 insertions(+)
Resolving Merge Conflicts
If Git can't automatically combine changes, it marks the file with conflict markers you resolve manually:
<<<<<<< HEAD <h1>Welcome to my site</h1> ======= <h1>Hello, world!</h1> >>>>>>> feature/contact-form # Edit the file to keep what you want, remove the markers, then: $ git add index.html $ git commit -m "Merge feature/contact-form — resolve heading conflict"
Stashing Work in Progress
# Quickly save dirty work to switch context $ git stash push -m "half-finished nav menu" # List stashes $ git stash list stash@{0}: On main: half-finished nav menu # Restore the most recent stash $ git stash pop
06 Connecting to GitHub
GitHub is the most popular remote Git host. Setting it up on Linux involves creating an SSH key so your computer can authenticate securely without needing a password every time.
Step 1 — Create a GitHub Account
Visit github.com and sign up. Use the same email address you configured in Git.
Step 2 — Generate an SSH Key
# Generate an ED25519 SSH key (modern, secure) $ ssh-keygen -t ed25519 -C "you@example.com" Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519): [press Enter] Enter passphrase (empty for no passphrase): [type a passphrase] # Start the SSH agent $ eval "$(ssh-agent -s)" Agent pid 12345 # Add your key to the agent $ ssh-add ~/.ssh/id_ed25519
Step 3 — Add the Key to GitHub
# Copy your PUBLIC key to clipboard (never share the private key!) $ cat ~/.ssh/id_ed25519.pub ssh-ed25519 AAAAC3Nza... you@example.com # If xclip is installed, pipe it to clipboard directly $ cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
Then in GitHub: Settings → SSH and GPG keys → New SSH key. Paste the contents of your .pub file and give it a descriptive name like "My Linux Laptop".
Step 4 — Test the Connection
$ ssh -T git@github.com Hi username! You've successfully authenticated, but GitHub does not provide shell access.
Persistent SSH Agent (optional but handy)
Add this to your ~/.bashrc or ~/.zshrc so the agent starts automatically:
# Auto-start SSH agent if [ -z "$SSH_AUTH_SOCK" ]; then eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 fi
07 Working with Remotes
Pushing a Local Repo to GitHub
First, create an empty repository on GitHub (no README, no .gitignore). Then back in your terminal:
# Add the GitHub repo as the "origin" remote $ git remote add origin git@github.com:username/my-project.git # Verify the remote was added $ git remote -v origin git@github.com:username/my-project.git (fetch) origin git@github.com:username/my-project.git (push) # Push and set main as the upstream tracking branch $ git push -u origin main Enumerating objects: 5, done. Branch 'main' set up to track remote branch 'main' from 'origin'. * [new branch] main -> main
Cloning an Existing Repository
# Clone via SSH (recommended — uses your SSH key) $ git clone git@github.com:username/repo-name.git # Clone to a specific folder name $ git clone git@github.com:username/repo-name.git my-local-name
Fetch, Pull & Push
# Download remote changes WITHOUT merging $ git fetch origin # Download AND merge remote changes into current branch $ git pull # Push current branch to origin $ git push # Push a new branch for the first time $ git push -u origin feature/my-feature
git pull before starting work for the day and before pushing. It avoids conflicts and keeps your history clean.
08 A Real-World Workflow
Here's the full cycle you'll use day-to-day when collaborating on a project:
# 1. Make sure main is up to date $ git switch main $ git pull # 2. Create a feature branch $ git switch -c feature/add-dark-mode # 3. Make your changes, then stage and commit $ nano style.css $ git add style.css $ git commit -m "Add dark mode colour variables" # 4. Push the feature branch to GitHub $ git push -u origin feature/add-dark-mode # 5. On GitHub: open a Pull Request → review → merge # 6. Back locally, clean up after merge $ git switch main $ git pull $ git branch -d feature/add-dark-mode $ git push origin --delete feature/add-dark-mode
Useful Aliases — Work Faster
Add these shortcuts to your git config:
$ git config --global alias.st status $ git config --global alias.co switch $ git config --global alias.lg "log --oneline --graph --all --decorate" $ git config --global alias.unstage "restore --staged" # Now you can use them $ git st $ git lg
09 Quick Reference Cheatsheet
Setup
| Command | What it does |
|---|---|
| git init | Initialise a new repository in the current folder |
| git clone <url> | Clone a remote repository locally |
| git config --global user.name "X" | Set your name globally |
| git config --global user.email "X" | Set your email globally |
Staging & Committing
| Command | What it does |
|---|---|
| git status | Show working tree and staging status |
| git add <file> | Stage a specific file |
| git add . | Stage all changes |
| git commit -m "msg" | Commit with a message |
| git commit -am "msg" | Stage tracked files and commit in one step |
| git diff --staged | Show what's staged vs last commit |
Branches
| Command | What it does |
|---|---|
| git branch | List all local branches |
| git switch -c <name> | Create and switch to a new branch |
| git switch <name> | Switch to an existing branch |
| git merge <branch> | Merge a branch into current |
| git branch -d <name> | Delete a merged branch |
Remote
| Command | What it does |
|---|---|
| git remote add origin <url> | Add a remote called "origin" |
| git push -u origin main | Push and set upstream tracking |
| git push | Push current branch to remote |
| git pull | Fetch + merge remote changes |
| git fetch | Download remote changes without merging |
| git remote -v | Show configured remotes |
Undoing
| Command | What it does |
|---|---|
| git restore <file> | Discard working directory changes |
| git restore --staged <file> | Unstage a file |
| git reset --soft HEAD~1 | Undo last commit, keep changes staged |
| git revert <hash> | Create a new commit that undoes a specific one (safe for shared history) |
| git stash | Stash uncommitted changes |
| git stash pop | Re-apply stashed changes |