Beginner GitHub Interview Questions and Answers

๐Ÿ“‹ Table of Contents โ–พ
  1. Questions & Answers
  2. 📝 Knowledge Check

🐱‍⬛ Beginner GitHub Interview Questions

This lesson covers the fundamental Git and GitHub concepts every developer must know. Master version control basics, branching, merging, pull requests, rebasing, stashing, and GitHub workflows. These questions reflect what interviewers ask at junior and entry-level developer roles.

Questions & Answers

01 What is Git and what problem does it solve?

Core Git is a distributed version control system (DVCS) created by Linus Torvalds in 2005. It tracks changes to files over time, enabling multiple developers to collaborate on a codebase without overwriting each other’s work.

Problems Git solves:

  • History โ€” records every change ever made, who made it, when, and why
  • Collaboration โ€” multiple people work on the same files simultaneously without conflicts destroying progress
  • Branching โ€” isolate features, experiments, and bug fixes from stable code
  • Rollback โ€” revert any file or the entire project to any previous state
  • Distributed โ€” every developer has a complete copy of the repository including full history; no single point of failure
# Configure Git for the first time
git config --global user.name  "Alice Smith"
git config --global user.email "alice@example.com"
git config --global core.editor "code --wait"  # VS Code as editor

# Initialise a new repository
git init my-project
cd my-project

# Common workflow
git status             # what has changed?
git add .              # stage all changes
git commit -m "feat: add user login"
git push origin main   # push to remote

02 What is the difference between Git and GitHub?

Core

  • Git โ€” the open-source version control tool. A command-line program installed locally. Manages your repository, history, branches, and commits. Works entirely offline. Git is the technology.
  • GitHub โ€” a cloud-based hosting platform for Git repositories. Provides a web interface, collaboration tools (pull requests, issues, code review), GitHub Actions (CI/CD), security scanning, package registry, and project management. GitHub is the service built on top of Git.

Alternatives to GitHub: GitLab (self-hosted option), Bitbucket (Atlassian), Azure DevOps, Gitea (lightweight self-hosted).

# Git is local -- these commands work without internet
git init
git add .
git commit -m "local work"
git log

# GitHub is the remote -- push/pull requires network
git remote add origin https://github.com/user/repo.git
git push -u origin main   # upload local commits to GitHub
git pull                  # download changes from GitHub

# You CAN use Git without GitHub (bare server, NAS, USB drive)
# You CANNOT use GitHub without Git

03 What are the core Git commands every developer must know?

Commands

# Setup
git init                          # create a new repo in current directory
git clone <url>                   # download a repo (full history included)
git clone <url> --depth=1        # shallow clone (no full history, faster)

# Inspecting
git status                        # show staged, unstaged, untracked files
git log --oneline --graph         # compact history with branch graph
git diff                          # unstaged changes
git diff --staged                 # staged changes (what will be committed)
git show HEAD                     # show last commit details + diff

# Staging and committing
git add file.txt                  # stage a specific file
git add .                         # stage all changes in current directory
git add -p                        # interactively stage hunks (partial file staging)
git commit -m "message"           # commit with inline message
git commit --amend --no-edit      # add staged changes to last commit (keep message)

# Branches
git branch                        # list local branches
git branch feature/login          # create branch
git switch feature/login          # switch to branch (modern)
git switch -c feature/signup      # create AND switch (modern)
git checkout feature/login        # switch (older syntax, still common)
git checkout -b feature/signup    # create AND switch (older)

# Remote
git remote -v                     # list remotes
git push origin main              # push to remote
git pull                          # fetch + merge from tracked remote branch
git fetch                         # download changes without merging

04 What is a branch in Git? How do you create and work with branches?

Branching A branch is a lightweight movable pointer to a commit. Branches allow you to diverge from the main line of development, work on a feature or fix in isolation, and then merge changes back.

# Create and switch to a new branch
git switch -c feature/user-profile

# Work on it
git add .
git commit -m "feat: add user profile page"

# List all branches (local + remote)
git branch -a

# See which branch you are on
git branch --show-current

# Push branch to remote (creates it remotely if it doesn't exist)
git push -u origin feature/user-profile
# -u sets the upstream so future 'git push' needs no arguments

# Merge branch into main (after PR or locally)
git switch main
git merge feature/user-profile
git push origin main

# Delete branch after merging
git branch -d feature/user-profile          # safe delete (checks merged)
git branch -D feature/user-profile          # force delete
git push origin --delete feature/user-profile  # delete on remote

# Rename a branch
git branch -m old-name new-name             # rename local branch
git push origin :old-name new-name          # delete old, push new on remote

# Typical branching strategy (GitHub Flow):
# main -- always deployable
# feature/xxx -- short-lived, merged via PR
# No long-lived develop branch needed for simple projects

05 What is the difference between git merge and git rebase?

Branching

  • git merge โ€” creates a new merge commit that joins two branch histories. Preserves the complete, true history. Non-destructive. Safe to use on shared/public branches.
  • git rebase โ€” replays commits from one branch on top of another. Creates new commits with new SHAs. Results in a linear, clean history. Rewrites history. Only safe on private/local branches (never rebase pushed public branches).
# --- MERGE ---
# Before: main A-B-C, feature A-B-D-E
git switch main
git merge feature/login
# After: main A-B-C-M (M = merge commit combining C and E)
# History: non-linear, shows exactly when branches diverged and merged

# --- REBASE ---
# Before: main A-B-C, feature A-B-D-E
git switch feature/login
git rebase main
# After: feature A-B-C-D'-E' (D and E replayed on top of C, new SHAs!)
# Then fast-forward merge:
git switch main
git merge feature/login  # fast-forward, no merge commit needed
# History: linear A-B-C-D'-E'

# When to use which:
# Merge:   integrating a completed feature branch (preserves context)
#          merging a public/shared branch (never rebase these)
# Rebase:  cleaning up local commits before a PR
#          keeping a feature branch up-to-date with main
#          "squashing" commits for a clean PR history

# GOLDEN RULE: Never rebase commits that exist outside your local repo
# Rebasing changes commit SHAs -- teammates who pulled the old commits get confused

06 What makes a good commit? What is Conventional Commits?

Workflow

# A commit should represent ONE logical change
# Good commit message format:
# <type>(<scope>): <short description>
#
# [optional body: WHY, not what (the diff shows what)]
#
# [optional footer: BREAKING CHANGE:, Closes #123]

# Conventional Commits spec (widely used)
git commit -m "feat(auth): add JWT token refresh endpoint"
git commit -m "fix(cart): prevent negative quantities on order"
git commit -m "docs(readme): add deployment instructions"
git commit -m "refactor(api): extract validation to middleware"
git commit -m "test(orders): add unit tests for discount logic"
git commit -m "chore(deps): upgrade Express to 5.0"
git commit -m "perf(db): add index on orders.customer_id"
git commit -m "ci(github-actions): add SAST security scan"

# Breaking change
git commit -m "feat(api)!: rename /users to /accounts
BREAKING CHANGE: All /users endpoints now use /accounts prefix"

# Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert

# Why conventional commits matter:
# - Auto-generate CHANGELOG.md
# - Trigger semantic version bumps (feat = minor, fix = patch, BREAKING = major)
# - Searchable history
# - Clear communication in PR review

# Tools: commitlint, commitizen, semantic-release, git-cliff

07 What is the difference between git fetch and git pull?

Commands

  • git fetch โ€” downloads commits, branches, and tags from the remote into your local remote-tracking branches (e.g., origin/main) but does NOT change your working directory or local branches. Safe, non-destructive โ€” lets you inspect changes before integrating.
  • git pull โ€” runs git fetch followed by git merge (or rebase if configured). Downloads AND integrates changes into your current branch immediately.
# git fetch -- download without merging
git fetch origin
# Now origin/main is updated but local main is unchanged
git log origin/main --oneline  # inspect what was fetched
git diff main origin/main      # see what's different
git merge origin/main          # integrate when ready

# git pull -- fetch + merge in one step
git pull                       # merges origin/<current branch> into current branch
git pull origin main           # explicit remote and branch

# git pull --rebase -- fetch + rebase (linear history)
git pull --rebase
# Set as default:
git config --global pull.rebase true

# Why prefer fetch + merge/rebase over bare pull?
# - More control: inspect changes before integrating
# - Avoid surprise merge conflicts breaking your working state
# - Understand exactly what changed on the remote

# Fetch all remotes and prune deleted remote branches
git fetch --all --prune

08 What is .gitignore and how does it work?

Configuration .gitignore tells Git which files and directories to ignore โ€” they won’t be staged, committed, or tracked. Useful for build artifacts, secrets, editor config, and OS files.

# .gitignore file in project root

# Node.js
node_modules/
dist/
build/
*.log
npm-debug.log*
.env                  # NEVER commit secrets!
.env.local
.env.*.local

# Python
__pycache__/
*.py[cod]
*.egg-info/
.venv/
venv/
*.pyc

# OS files
.DS_Store             # macOS
Thumbs.db             # Windows
*.swp                 # Vim swap files

# IDE
.vscode/
.idea/
*.suo

# Wildcards
*.tmp                 # all .tmp files anywhere
temp/                 # the temp directory anywhere
/temp/                # temp only at repo root (leading /)
!important.tmp        # negation: DO track this despite *.tmp rule

# Already tracked files -- .gitignore won't help!
# Must untrack first:
git rm --cached .env              # untrack (keep file locally)
git rm --cached -r node_modules/  # untrack directory
git commit -m "chore: untrack .env"

# Global ignore (for your machine, all repos)
git config --global core.excludesfile ~/.gitignore_global

# Check why a file is ignored
git check-ignore -v .env

09 What is the staging area (index) in Git?

Core The staging area (also called the index) is a preparation zone between your working directory and the repository. You explicitly choose which changes to include in the next commit by staging them with git add.

# Three-tree architecture
# Working Directory  -- where you edit files
# Staging Area (Index) -- what will go into the next commit
# Repository (.git/) -- committed history

# Check what's where
git status                     # shows staged vs unstaged vs untracked

# Stage selectively
git add src/auth.js            # stage one file
git add src/                   # stage an entire directory
git add -p                     # interactive: stage individual hunks within a file

# Unstage (move back from index to working dir)
git restore --staged file.txt  # modern (Git 2.23+)
git reset HEAD file.txt        # older syntax (same effect)

# Compare the three areas
git diff                       # working dir vs index (unstaged changes)
git diff --staged              # index vs last commit (what will be committed)
git diff HEAD                  # working dir vs last commit (everything)

# Why staging matters:
# - Commit only part of your changes (keep unrelated WIP out of commit)
# - Review exactly what goes into the commit before committing
# - Stage partial file changes with git add -p for atomic, focused commits

# Example: changed 5 files, want 2 separate commits
git add feature-A.js
git commit -m "feat: implement feature A"
git add feature-B.js
git commit -m "feat: implement feature B"

10 What is git stash and when do you use it?

Commands git stash temporarily saves uncommitted changes (both staged and unstaged) so you can switch context without committing incomplete work.

# Stash your current changes
git stash                          # save WIP with auto-message
git stash push -m "WIP: login form validation"  # named stash

# List stashes
git stash list
# stash@{0}: WIP on feature/auth: a1b2c3d WIP: login form validation
# stash@{1}: On main: 9e8f7a6 quick test

# Apply the most recent stash
git stash pop                      # apply + delete from stash list
git stash apply                    # apply but KEEP in stash list

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

# Show what's in a stash
git stash show -p stash@{0}        # -p for full diff

# Drop / clear stashes
git stash drop stash@{0}           # delete one stash
git stash clear                    # delete ALL stashes

# Stash including untracked files
git stash push -u                  # also stash untracked files
git stash push -u -m "include new files"

# Create a branch from a stash
git stash branch hotfix/nav stash@{0}  # branch + apply + drop stash

# Common scenario:
# Working on feature, urgent bug report comes in
git stash push -m "WIP: user settings page"
git switch main
git switch -c hotfix/broken-login
# ... fix the bug, commit, merge ...
git switch feature/settings
git stash pop

11 What is a pull request (PR)? What makes a good PR?

GitHub A Pull Request (PR) is a GitHub feature that proposes merging one branch into another. It provides a review interface, discussion thread, automated checks (CI), and merge history. PRs are the primary unit of code collaboration on GitHub.

# Typical PR workflow
git switch -c feature/payment-webhooks
# ... develop and commit ...
git push -u origin feature/payment-webhooks
# Then open a PR on GitHub: feature/payment-webhooks โ†’ main

# What makes a good PR:
# 1. SMALL and FOCUSED -- one feature/fix per PR (easier to review)
# 2. Clear title using conventional commits: "feat(billing): add Stripe webhook handler"
# 3. Description template:
#    ## What does this PR do?
#    Adds a /webhooks/stripe endpoint that verifies signatures and processes payment events
#
#    ## Why?
#    Required for Stripe to confirm payment status after 3D Secure authentication
#
#    ## How to test
#    1. Configure STRIPE_WEBHOOK_SECRET in .env
#    2. Use Stripe CLI: stripe listen --forward-to localhost:3000/webhooks/stripe
#    3. Trigger test event: stripe trigger payment_intent.succeeded
#
#    ## Screenshots / recordings
#    [attach if UI change]
#
#    Closes #142

# PR checklist items (enforce via .github/pull_request_template.md)
# - [ ] Tests added/updated
# - [ ] Documentation updated
# - [ ] No secrets in code
# - [ ] Breaking changes documented

12 What is the difference between git reset and git revert?

Commands

  • git reset โ€” moves the branch pointer backward, effectively “uncommitting” commits. Rewrites history. Safe for local, private commits only.
  • git revert โ€” creates a new commit that undoes the changes from a previous commit. Does NOT rewrite history. Safe for public/shared branches.
# git reset -- moves HEAD backward (rewrites history)
git reset --soft  HEAD~1    # undo last commit, keep changes STAGED
git reset --mixed HEAD~1    # undo last commit, keep changes UNSTAGED (default)
git reset --hard  HEAD~1    # undo last commit, DISCARD changes (irreversible!)

# Example: undo last 3 commits and squash into one
git reset --soft HEAD~3     # uncommit 3 commits, keep all changes staged
git commit -m "feat: complete checkout flow"  # single clean commit

# git revert -- creates an undo commit (safe for shared branches)
git revert HEAD             # revert the last commit
git revert abc1234          # revert a specific commit by SHA
git revert HEAD~3..HEAD     # revert a range (multiple revert commits)
git revert HEAD~3..HEAD --no-commit  # stage all reverts, commit once

# When to use which:
# reset: cleaning up local/private history before pushing
# revert: undoing changes on main/shared branches (safe, auditable)

# Reset the working directory to match HEAD (discard all local changes)
git restore .               # modern syntax (Git 2.23+)
git checkout -- .           # older syntax

# Recover from a bad --hard reset (commits still in reflog!)
git reflog                  # find the SHA you need
git reset --hard abc1234    # restore to that state

13 What is the difference between –soft, –mixed, and –hard git reset?

Commands

# Starting state: HEAD points to C, index has C, working dir has C
# git reset HEAD~1 moves HEAD back to B

# --soft: move HEAD only
# Repository: HEAD = B (undone commit)
# Index (staged): still has C's changes (ready to re-commit)
# Working dir: still has C's changes
git reset --soft HEAD~1
# Use: "I want to redo my commit message" or combine multiple commits

# --mixed (DEFAULT): move HEAD + reset index
# Repository: HEAD = B
# Index: reset to B (changes are unstaged)
# Working dir: still has C's changes
git reset --mixed HEAD~1  # or just: git reset HEAD~1
# Use: "I committed too early, want to re-stage selectively"

# --hard: move HEAD + reset index + reset working directory
# Repository: HEAD = B
# Index: reset to B
# Working dir: reset to B (C's changes are GONE)
git reset --hard HEAD~1
# Use: "I want to completely undo this commit and its changes"
# WARNING: hard reset discards uncommitted changes permanently

# Summary table:
# Mode    | HEAD | Index | Working Dir | Data loss?
# --soft  |  YES |  NO   |    NO       | None
# --mixed |  YES |  YES  |    NO       | None (unstaged)
# --hard  |  YES |  YES  |    YES      | Committed changes gone!

14 What is a merge conflict and how do you resolve it?

Branching A merge conflict occurs when two branches both modify the same lines in a file and Git cannot automatically determine which version to keep. You must manually choose the correct version.

# Conflict markers in a file
<<<<<<< HEAD
function login(user) {
  return validateUser(user);  // YOUR version
=======
function login(user, options = {}) {
  return validateUser(user, options);  // THEIR version (incoming)
>>>>>>> feature/auth-options

# Resolve the conflict manually
function login(user, options = {}) {
  return validateUser(user, options);  // resolved: merge both changes
}

# Then mark as resolved and commit
git add src/auth.js
git commit   # Git auto-generates a merge commit message

# Conflict resolution workflow
git merge feature/auth-options   # conflict!
git status                       # see conflicting files
# Edit each conflicted file
code .                           # VS Code has a great merge editor
git add <resolved files>
git commit

# Abort a merge mid-conflict
git merge --abort               # go back to pre-merge state

# Useful conflict tools
git mergetool                   # open configured merge tool
# Configure: git config --global merge.tool vimdiff

# Prevent conflicts proactively:
# - Keep branches short-lived (less divergence)
# - Regularly sync feature branch with main: git pull --rebase
# - Use atomic commits (smaller, focused changes)
# - Communicate with teammates about shared files

15 What are Git tags and how do you use them?

Commands Tags are permanent named references to specific commits โ€” used to mark release points. Unlike branches, tags don’t move as new commits are added.

# Lightweight tag -- just a name for a commit
git tag v1.0.0

# Annotated tag -- includes tagger, date, message (recommended for releases)
git tag -a v1.2.0 -m "Release 1.2.0: add payment system"
git tag -a v1.2.0 abc1234 -m "Tag a past commit"  # tag specific commit

# List tags
git tag                          # all tags
git tag -l "v1.*"                # pattern match
git tag --sort=-version:refname  # sort by version number descending

# Show tag details
git show v1.2.0

# Push tags to remote
git push origin v1.2.0           # push one tag
git push origin --tags           # push all tags
git push origin --follow-tags    # push annotated tags that belong to pushed commits

# Delete tags
git tag -d v1.0.0                # delete local tag
git push origin --delete v1.0.0  # delete remote tag

# Checkout a tagged commit (detached HEAD state)
git checkout v1.1.0
# Create a branch from a tag for hotfixes
git switch -c hotfix/1.1.x v1.1.0

# SemVer tagging convention
# v1.0.0   -- major.minor.patch
# v1.0.0-beta.1  -- pre-release
# v1.0.0-rc.1    -- release candidate

16 What is git log and how do you inspect history?

Commands

# Basic log
git log                          # full details
git log --oneline                # one line per commit
git log --oneline --graph        # with branch graph
git log --oneline --graph --all  # all branches

# Filter commits
git log --author="Alice"         # by author
git log --since="2026-01-01"     # since a date
git log --until="2026-04-01"
git log --grep="fix"             # by commit message
git log -10                      # last 10 commits
git log --no-merges              # exclude merge commits

# Show what changed
git log -p                       # include diff (patch) for each commit
git log --stat                   # show files changed + line stats
git log --shortstat              # summary: X files changed, Y insertions, Z deletions

# Filter by file
git log -- src/auth.js           # commits that touched this file
git log -p -- src/auth.js        # with diffs for that file

# Pretty formats
git log --format="%h %an %ar: %s"  # hash, author, relative time, subject
git log --pretty=format:"%C(yellow)%h%Creset %s (%Cgreen%ar%Creset)"  # coloured

# Aliases (save in ~/.gitconfig)
git config --global alias.lg "log --oneline --graph --all --decorate"
git lg                           # now a short command

# Search commit contents (pickaxe -- find when a string was added/removed)
git log -S "function login"      # commits that added or removed this string
git log -G "regex_pattern"       # commits where diff matches regex

17 What is GitHub Actions and why is it used?

GitHub Actions GitHub Actions is a CI/CD platform built into GitHub. Workflows are defined in YAML files in .github/workflows/ and are triggered by events like push, pull request, schedule, or manual dispatch.

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

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

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4        # checkout the repo

      - uses: actions/setup-node@v4      # set up Node.js
        with:
          node-version: '22'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run tests
        run: npm test -- --coverage

      - name: Upload coverage
        uses: codecov/codecov-action@v4

# Key concepts:
# Workflow    -- the entire YAML file (triggered by events)
# Job         -- a set of steps that run on one runner
# Step        -- a single task (run: command, uses: action)
# Runner      -- the machine that executes the job (ubuntu/windows/macos)
# Action      -- reusable step (from GitHub Marketplace or your own)
# Event       -- what triggers the workflow (push, pull_request, schedule, workflow_dispatch)

18 What is forking in GitHub and how does it differ from cloning?

GitHub

  • Fork โ€” creates a server-side copy of a repository under your GitHub account. Used for contributing to open-source projects where you don’t have write access to the original. Changes are proposed back via a pull request from your fork to the original (upstream).
  • Clone โ€” creates a local copy of a repository on your machine. You clone whatever repo you have access to (your own, a team repo, or your fork).
# Fork workflow (open-source contribution)
# 1. Fork on GitHub.com (click Fork button) โ†’ creates github.com/YOU/project

# 2. Clone YOUR fork locally
git clone https://github.com/YOU/project.git
cd project

# 3. Add the original as "upstream"
git remote add upstream https://github.com/ORIGINAL-OWNER/project.git
git remote -v
# origin    https://github.com/YOU/project.git        (your fork)
# upstream  https://github.com/ORIGINAL-OWNER/project.git (original)

# 4. Create a feature branch
git switch -c fix/typo-in-readme

# 5. Make changes, commit, push to YOUR fork
git push origin fix/typo-in-readme

# 6. Open a Pull Request: YOUR fork โ†’ upstream original

# Keep fork up to date with upstream
git fetch upstream
git switch main
git merge upstream/main        # integrate upstream changes
git push origin main           # update your fork's main

19 What is git blame and when do you use it?

Commands git blame shows which commit (and which author) last modified each line of a file. Useful for understanding why a particular line of code exists.

# Show blame for a file
git blame src/auth.js

# Output format:
# abc1234 (Alice Smith  2026-03-15 14:22:10 +0000 42) function login(user) {
# commit   author        date                       line  code

# Blame a specific range of lines
git blame -L 40,60 src/auth.js    # lines 40-60 only

# Ignore whitespace changes
git blame -w src/auth.js

# Show blame for a specific commit
git blame v1.2.0 -- src/auth.js   # at a historical version

# Follow renames (-M) and copies (-C)
git blame -M -C src/auth.js       # detect if lines were moved from another file

# Show commit info for a blamed commit
git show abc1234                  # see the full commit that touched the line

# GitHub: click any file โ†’ click a line number โ†’ hover "Blame" view
# VS Code: GitLens extension shows inline blame without running the command

# Note: blame shows the LAST person to touch a line
# For deeper history: git log -p -S "function login" src/auth.js
# "git blame" is often called "git context" -- it's for understanding, not finger-pointing

20 What is git cherry-pick?

Commands git cherry-pick applies the changes from one or more specific commits to the current branch โ€” without merging the entire branch. Creates new commits with new SHAs.

# Apply a single commit from another branch
git switch main
git cherry-pick abc1234            # apply commit abc1234 to current branch

# Apply multiple commits
git cherry-pick abc1234 def5678    # apply both in order
git cherry-pick abc1234..ghi9012  # apply a range (exclusive of abc1234)
git cherry-pick abc1234^..ghi9012 # apply a range (inclusive of abc1234)

# Cherry-pick with editing (change the commit message)
git cherry-pick abc1234 --edit

# Cherry-pick without committing (stage changes only)
git cherry-pick abc1234 --no-commit  # apply changes, don't commit
# Useful for: picking only some changes, combining with other edits

# Abort a cherry-pick (on conflict)
git cherry-pick --abort
git cherry-pick --continue         # after resolving conflict

# Common scenarios:
# 1. Bug fix on a feature branch that also needs to go to main
#    git switch main; git cherry-pick fix-commit-sha

# 2. Hotfix: pick a specific commit from main into a release branch
#    git switch release/1.2; git cherry-pick security-patch-sha

# 3. Salvage work from a branch you're going to abandon
#    git cherry-pick good-commit-from-abandoned-branch

# Caution: cherry-picking duplicates commits (different SHAs)
# If the original branch is later merged, you get duplicate changes
# Prefer merge/rebase when possible; use cherry-pick surgically

21 What is HEAD in Git? What is a detached HEAD?

Core HEAD is a special reference that points to the current commit โ€” usually it points to the current branch, which in turn points to its latest commit. A detached HEAD occurs when HEAD points directly to a commit SHA rather than a branch.

# HEAD normally points to a branch
cat .git/HEAD
# ref: refs/heads/main   <-- HEAD points to main branch

# Detached HEAD -- HEAD points to a commit directly
git checkout abc1234       # old syntax, causes detached HEAD
git switch --detach abc1234 # explicit modern syntax

cat .git/HEAD
# abc1234def...            <-- HEAD points directly to commit

# In detached HEAD state:
# - You can look around, run code, make experimental commits
# - Any commits you make are NOT on any branch
# - Switching back to a branch will "lose" those commits (GC may remove them)

# Save work from detached HEAD: create a branch
git switch -c experiment/new-idea   # creates branch at current HEAD

# Common causes of accidental detached HEAD:
git checkout v1.0.0          # checking out a tag
git checkout origin/main     # checking out a remote tracking branch

# Relative references
HEAD^                        # parent of HEAD (one commit back)
HEAD^^  or HEAD~2            # grandparent
HEAD~5                       # 5 commits back
HEAD^2                       # second parent (merge commit)

# Use HEAD in commands
git diff HEAD~1              # diff with one commit ago
git reset --soft HEAD~1      # undo last commit
git log HEAD..feature/auth   # commits in feature/auth not in HEAD

22 What is a remote in Git? How do you manage remotes?

Commands A remote is a named reference to another Git repository โ€” typically hosted on GitHub, GitLab, or another server. origin is the conventional name for the repository you cloned from.

# List remotes
git remote -v
# origin  https://github.com/user/repo.git (fetch)
# origin  https://github.com/user/repo.git (push)

# Add a remote
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git

# Change a remote URL (e.g., switch from HTTPS to SSH)
git remote set-url origin git@github.com:user/repo.git

# Rename a remote
git remote rename origin old-origin

# Remove a remote
git remote remove old-origin

# Inspect a remote
git remote show origin
# shows: tracked branches, fetch/push URLs, remote HEAD

# Remote tracking branches
# When you clone, Git creates remote tracking branches: origin/main, origin/dev
# These are read-only -- updated only by fetch/pull

# Push tracking setup
git push -u origin main         # -u sets origin/main as tracking branch
# After -u, plain 'git push' and 'git pull' know where to go

# Prune deleted remote branches from local tracking
git fetch --prune               # delete origin/feature/old if deleted on remote
git remote prune origin         # manual prune

# SSH key setup (more secure than HTTPS)
ssh-keygen -t ed25519 -C "alice@example.com"
# Add ~/.ssh/id_ed25519.pub to GitHub โ†’ Settings โ†’ SSH keys

📝 Knowledge Check

🧠 Quiz Question 1 of 5

What is the key difference between git merge and git rebase?





🧠 Quiz Question 2 of 5

What is the difference between git reset –soft, –mixed, and –hard?





🧠 Quiz Question 3 of 5

When should you use git revert instead of git reset to undo a commit?





🧠 Quiz Question 4 of 5

What is the purpose of the staging area (index) in Git?





🧠 Quiz Question 5 of 5

What is the difference between git fetch and git pull?