Git line
Git basics
Git is a photo album for your files that remembers every version, so you can undo mistakes and work with others.
Stops explain each step. The film plays the whole ride.
- Your work moving on
- Something to notice
- News arriving
- A clash
You change a file and pick it
This is your messy desk, where you edit files. You change one file, then move it onto the arranging tray. Nothing is saved yet.
Next stop: You save a page
All stops
The everyday version
Think of building a photo album you share with family. Every Git place has a twin there.
- Your messy deskis the Working directory
Photos, scissors and scribbles lie everywhere. Nothing here is in the album yet.
- The arranging trayis the Staging area
You place only the photos you want in the next page, ready to be shot.
- The photo albumis the Local repository
Each photo has a caption and points to the one before it. A sticky note marks where you are.
- Your cloud noteis the origin/main
It says what the cloud album looked like when you last checked. It can be out of date.
- The shared cloud albumis the GitHub (origin)
The family album everyone adds to. Teammates see only what is uploaded here.
- Two people glued different photos on one pageis a merge conflict
Nobody can tell which photo belongs there, so a human has to look at the page and pick.
Interview questions
Say the short answer first. Go deeper only if they ask.
What does HEAD actually point to?
Usually to a branch name, which points to a commit.
.git/HEAD contains ref: refs/heads/main, a symbolic ref. The branch file holds a commit SHA. Checking out a commit or tag leaves HEAD holding a raw SHA (detached). Committing moves the branch HEAD refers to, not HEAD itself.
“HEAD is the latest commit on the remote” or “HEAD is a copy of the code”.
What is the difference between fetch and pull?
Fetch downloads. Pull downloads and then integrates.
Fetch updates remote-tracking refs like origin/main only, so it is always safe. Pull is fetch plus merge (or rebase with --rebase), which can change your branch and working tree and cause conflicts. Many people fetch, inspect with git log main..origin/main, then integrate.
“They are the same” or “fetch deletes local changes”.
What is a branch?
A movable pointer to a commit.
It is a tiny file under .git/refs/heads/ holding one commit SHA, which is why branching is cheap. History is a graph of immutable commits, and a branch just names one of them.
“A branch is a copy of all the files”.
Why does the staging area exist?
It lets you build a commit from only part of your changes.
The index is the proposed next snapshot. git add -p stages hunks, so unrelated edits can become separate commits. git diff compares working files to the index, and git diff --staged compares the index to HEAD.
“It is just a temporary backup”.
Merge or rebase: what is the difference?
Merge keeps history and adds a merge commit. Rebase rewrites it into a straight line.
Rebase creates new commits with new parents and SHAs, so never rebase commits that others have based work on. Merge is non-destructive, while rebase gives a cleaner log. A squash merge collapses a branch into one commit.
“Rebase is just a faster merge” or “rebase is always safe”.
How do you undo a bad commit that is already pushed?
Use git revert.
Revert adds a new commit that inverts the change, so it is safe on shared branches. Reset plus force-push rewrites shared history and breaks teammates’ copies.
“reset --hard and force push to main”.
Cheat-sheet
Commands you will actually type.
git status -sbShort status, with the branch and how far it is ahead or behind.
git add -pStage changes hunk by hunk, so one commit holds one idea.
git switch -c feature/xCreate a new branch and switch to it.
git fetch --pruneUpdate remote refs and drop the ones deleted on the remote.
git pull --rebaseFetch, then replay your local commits on top of the remote ones.
git log --oneline --graph --decorate --allDraw the whole history as a graph with branch names.
git revert <sha>Undo a commit by adding a new one. Safe on shared branches.
git push --force-with-leaseForce-push after a rebase. Safer than `--force`: it refuses if the remote moved since you last fetched.