Git Study Guide
Study Guide
📖 Core Concepts
Distributed VCS – Every clone contains the complete repository (full history, objects, refs) and can work offline.
Snapshot model – Git stores a full snapshot of the directory tree for each commit, not per‑file deltas.
Objects – Immutable data identified by a SHA‑1 hash:
Blob – raw file contents.
Tree – directory listing; trees form a Merkle tree so the root hash uniquely identifies the whole snapshot.
Commit – points to a tree, has parent(s), author info, timestamp, and message.
Tag – human‑readable reference (often GPG‑signed) to another object.
Index (staging area) – mutable cache of what will be written in the next commit.
References – pointers to commits:
Heads = local branches (move automatically).
HEAD – special ref that points to the current branch tip.
Tags – fixed refs for releases.
Merging strategies – three built‑in algorithms: resolve, recursive (default for two heads), octopus (default for > 2 heads).
Common workflow commands – git init, git clone, git add, git commit, .gitignore, remote name origin.
---
📌 Must Remember
Full local copy → no network needed for most operations.
Objects are identified by SHA‑1 (40‑hex hash) → guarantees content integrity.
Branch = movable reference; creating a branch is just a new ref entry.
HEAD points to the current branch, not directly to a commit.
Default branch on git init is master (many services now use main).
Merge commit = commit with multiple parents.
git add → stages file changes in the index; .gitignore tells Git to never track matching paths.
git commit -m records the staged snapshot as a new commit.
Octopus merge works only when merging more than two heads; otherwise recursive is used.
Git LFS stores large files outside the repo; the repo keeps lightweight pointers.
---
🔄 Key Processes
Initialize repository
bash
git init # creates .git with empty object DB, index, and a master (or main) branch
Clone remote
bash
git clone <URL> # copies entire repo + all refs; creates remote “origin”
Stage changes
bash
git add <file> # updates index entry for <file>
Commit
bash
git commit -m "msg" # writes index snapshot → new blob/tree/commit objects; moves HEAD’s branch ref
Create/rename branch
bash
git branch <name> # creates new ref pointing to current commit
git branch -m master main # rename default branch
Merge (two‑head case)
Resolve → three‑way merge using common ancestor.
Recursive → finds best merge base (may create temporary “virtual” merge of multiple ancestors) → reduces conflicts.
Octopus merge (≥ 3 heads)
bash
git merge <head1> <head2> <head3> # creates a single merge commit with all parents
Push / Pull (not detailed in outline but implied by remote naming).
Revert a commit
bash
git revert <commit> # adds a new commit that undoes <commit> without rewriting history
Set up a bare server repo (SSH)
Create bare repo on server (git init --bare).
Grant SSH access; users clone via git@server:path.git.
---
🔍 Key Comparisons
resolve vs recursive vs octopus
resolve: simple three‑way merge, single common ancestor.
recursive: default for two heads; handles multiple common ancestors by creating a virtual merge tree.
octopus: default for > 2 heads; merges many branches in one commit, no conflict resolution (fails if conflicts).
Branch vs Tag
Branch: mutable ref that moves with each new commit; used for ongoing development.
Tag: immutable (or rarely moved) ref, often signed, used to mark releases.
Local repo vs Centralized VCS
Git: full history locally, offline commits, cheap branching.
Centralized: only latest snapshot on server; requires network for most ops.
git add vs .gitignore
git add: stages a file now (adds to index).
.gitignore: tells Git to never consider matching paths unless explicitly added with -f.
SHA‑1 vs “stronger hash”
SHA‑1: used for object IDs; good for integrity, but collision‑prone (not for security).
Stronger hash: recommended for future Git versions, but not yet standard.
---
⚠️ Common Misunderstandings
Branches are copies of files – they are merely pointers to commits; the underlying objects are shared.
Rewriting pushed commits is safe – shared history should be reverted (new commit), not rewritten.
HEAD is a branch name – HEAD points to a branch ref; the branch name itself moves.
SHA‑1 guarantees security – it prevents accidental corruption; it is not cryptographically secure against intentional attacks.
.gitignore removes tracked files – it only prevents untracked files from being added; tracked files stay under version control.
---
🧠 Mental Models / Intuition
Merkle tree – picture the repository as a tree where each node’s hash depends on its children; change any file → a different root hash → a new commit ID.
Commit DAG – think of commits as nodes in a directed acyclic graph; merges create nodes with multiple parents.
Index as a “snapshot preview” – the index holds exactly what the next commit will look like; git status compares working tree ↔ index ↔ HEAD.
HEAD = “bookmark” – it tells Git which branch you’re currently reading/writing.
---
🚩 Exceptions & Edge Cases
Octopus merge fails if any of the heads produce a conflict; fallback to recursive merges per pair.
Renaming default branch (master → main) does not alter object storage; only ref names and remote configs change.
Signed tags are optional; a tag can exist without a GPG signature.
Git LFS stores only pointers in the repo; actual large files live on a separate LFS server.
Packfile compression – objects are stored uncompressed in loose form, but git gc packs them for efficiency; packfiles are read‑only once created.
---
📍 When to Use Which
Merge strategy:
Use recursive for normal two‑branch merges (default).
Use octopus only when merging many feature branches that you know do not conflict.
Branching model:
Choose Gitflow (git‑flow) for long‑lived release cycles and strict separation (feature, develop, release, hotfix).
Use a simple feature‑branch workflow for lightweight projects.
Git LFS: store files > 100 MB (or as defined by service limits) with LFS; keep source code in normal repo.
Revert vs Reset:
Revert when the commit is already pushed/shared.
Reset (hard/soft) only on local, unpublished history.
.gitignore vs git rm --cached:
Add patterns to .gitignore before files are tracked.
Use git rm --cached <file> to stop tracking a file already committed.
---
👀 Patterns to Recognize
“git add → git commit” always appears together; missing add ⇒ empty commit or only staged changes.
Fast‑forward merge when the current branch tip is an ancestor of the branch being merged → no merge commit created.
Multiple parents in a commit = a merge commit (look for more than one parent hash).
Large packfiles after many pushes/pulls → git gc likely ran to compress.
Remote name “origin” appears in most clone/fetch commands; custom names are rare on exams.
---
🗂️ Exam Traps
Assuming a tag can move – tags are intended to be immutable; moving a tag is a manual, discouraged operation.
Thinking HEAD is a branch name – HEAD is a pointer; the branch name is stored separately (e.g., refs/heads/master).
Choosing “resolve” for a three‑way merge – recursive is the default and handles complex histories; resolve is only a fallback.
Believing git init always creates “master” – many services now default to “main”; exam may ask which name is default by the command itself.
Confusing remote “origin” with upstream branch – origin is the default remote; the upstream branch is the remote‑tracking branch (e.g., origin/main).
Assuming SHA‑1 provides cryptographic security – it's used for integrity, not for protecting against malicious collisions.
Treating .gitignore as a way to delete tracked files – it only prevents new files from being added; tracked files stay in history.
---
or
Or, immediately create your own study flashcards:
Upload a PDF.
Master Study Materials.
Master Study Materials.
Start learning in seconds
Drop your PDFs here or
or