Chapter 10: Git Version Control¶
Source slides:
V08_Git.pdf. Exercise:E08_Git.pdf. The exercise has three tasks: setup & first commit, branching & merging, GitLab collaboration. The lecture referenceshttps://learngitbranching.js.org/for branch demos.
1. Chapter Overview¶
In any HPC/CFD project you write code (solvers, scripts, gnuplot, sbatch templates) that evolves over months. Without version control you cannot answer "what changed in commit X", "who introduced this bug", "give me yesterday's working version". Git is the de-facto standard: distributed (every developer has a full copy), fast, and free.
Why it matters in HPC/CFD: clusters require reproducibility — published results must be recoverable from a specific commit hash. CFD groups push to GitLab (often the university's, e.g. git.rz.tu-bs.de for TU Braunschweig). Branching enables parallel feature work; merging integrates it.
What the examiner asks (very common):
- "Difference between
git add,git commit,git push." - "What is the staging area?"
- "How do you create a branch and merge it?"
- "What's a remote?
origin?" - "Explain
git log,git status,git diff." - "Explain GitFlow naming convention."
- "Resolve a merge conflict."
What you must master for top grade:
- The three-zone model (working dir / staging / local repo) + remote repo.
- The 4 file states: untracked / unmodified / modified / staged.
- Top-15 commands.
- Branch workflow.
- HTTPS vs SSH remote authentication.
- Personal-access tokens for GitLab.
2. Basics from Zero¶
A Git repository is just a hidden folder .git/ inside your project that records snapshots of your files. You explicitly stage the changes you want to record (git add), then commit them (git commit). Each commit gets a unique 40-char SHA-1 hash that forever identifies that exact tree.
Three big advantages:
- History.
git logshows every change with author/date/message. - Branching. Create parallel timelines, merge them.
- Collaboration. Push your local repo to a remote (GitHub, GitLab, Bitbucket); other people pull from it.
The flow:
WORKING STAGING LOCAL REMOTE
DIR AREA REPO REPO
│ │ │ │
│ add ──▶ │ │ │
│ │ commit ──▶ │ │
│ │ │ push ──▶ │
│ │ │ ◀── pull │
বাংলায়: Git-এর মূল ছন্দ: ফাইল এডিট করো → git add দিয়ে staging area-তে তোলো → git commit দিয়ে লোকাল history-তে snapshot নাও → git push দিয়ে সার্ভারে পাঠাও। মনে রাখো, commit শুধু তোমার মেশিনে থাকে — push না করা পর্যন্ত টিমের কেউ সেটা দেখতে পায় না। এই চারটা zone আর তিনটা verb-এর ছবিটা পরীক্ষায় আঁকতে পারলে অর্ধেক নম্বর পকেটে।
Real-life analogy. Git = a time-machine + photo album for code. You take photos (commit); each photo has a label and a date. You can flip back, branch into alternate timelines, and share albums with collaborators.
Real-life HPC use. A CFD researcher tracks solver.cpp, case_template/in.dat, plot_residuals.gp. Every paper figure is reproducible because a git tag v1.0 marks the commit used to generate it.
What if you misunderstand? You forget to git add after editing a file → commit records nothing. Or you think commit already shares with team — it doesn't, you must push. Or you delete a branch before merging → work lost.
বাংলায়: তিনটা ক্লাসিক ভুল মুখস্থ রাখো: (১) এডিটের পর add ভুলে গেলে commit-এ নতুন পরিবর্তন ঢোকেই না; (২) commit করেই ভাবা "টিম পেয়ে গেছে" — আসলে push না করা পর্যন্ত সব লোকাল; (৩) merge করার আগে branch delete করলে কাজ হারানোর ঝুঁকি। এই তিনটা trap পরীক্ষার ছোট প্রশ্নে ঘুরেফিরে আসে, আর viva-তেও।
3. Hard English Made Easy¶
| Hard Term | Simple English | বাংলা | Example |
|---|---|---|---|
| Repository (repo) | Folder tracked by git | গিট-নিয়ন্ত্রিত ফোল্ডার | git init |
| Working directory | Files visible on disk | কাজের ফোল্ডার | ls |
| Staging area / index | Pre-commit zone | কমিটের আগের জায়গা | git add |
| Commit | Saved snapshot | সংরক্ষিত স্ন্যাপশট | git commit -m |
| Hash | 40-char SHA-1 ID | কমিটের স্বতন্ত্র চিহ্ন | d29882c… |
| Branch | Independent timeline | আলাদা সময়রেখা | git branch x |
| Merge | Combine two branches | শাখা একত্রিত করা | git merge x |
| Conflict | Both branches changed same lines | একই লাইনে দুই পরিবর্তন | conflict markers <<<< |
| Remote | Server-hosted copy | সার্ভারে কপি | origin |
| Origin | Default remote name | ডিফল্ট রিমোট | git push origin main |
| HEAD | Pointer to current commit | বর্তমান অবস্থান | git reset HEAD~1 |
| Pull | Fetch + merge | ফেচ ও মার্জ | git pull |
| Push | Send local commits to remote | সার্ভারে পাঠানো | git push |
| Clone | Copy a remote into a new local | রিমোটের লোকাল কপি | git clone url |
| Tag | Named commit (e.g. release) | কমিটের নামকরণ | git tag v1.0 |
| Diff | Show line-level changes | পরিবর্তন প্রদর্শন | git diff |
| Tracked / Untracked | In repo / not | ট্র্যাকড / আনট্র্যাকড | new file = untracked |
| Modified / Staged | Changed but not staged / staged | পরিবর্তিত / স্টেজড | git status |
| GitLab / GitHub | Hosting platforms | হোস্টিং প্ল্যাটফর্ম | git.rz.tu-bs.de |
| Personal Access Token (PAT) | Token in lieu of password | পাসওয়ার্ডের পরিবর্তে টোকেন | for GitLab HTTPS |
4. Deep Theory Explanation¶
4.1 Three zones + four file states¶
- Untracked — file is new, git ignores it until you
git add. - Unmodified — tracked, not touched since last commit.
- Modified — tracked, edited but not staged.
- Staged — added to the index, ready for commit.
বাংলায়: Git-এ একটা ফাইল চারটা অবস্থার যেকোনো একটায় থাকে: untracked (git এখনো চেনে না), unmodified (শেষ commit-এর পর অপরিবর্তিত), modified (বদলেছ কিন্তু stage করোনি), staged (পরের commit-এর জন্য প্রস্তুত)। git add ফাইলকে staged করে, git commit সেটাকে history-তে ঢুকিয়ে আবার unmodified বানায়। কোন ফাইল কোন অবস্থায় আছে সন্দেহ হলেই git status — এটাই তোমার কম্পাস।
4.2 Configuration¶
git --version
git config --global user.name "Debwashis"
git config --global user.email "debwa.web@gmail.com"
git config --global core.editor vim # or nano
git config --global merge.tool vimdiff
git config --global init.defaultBranch main
git config --list # show all
cat ~/.gitconfig # the file
Three scopes: --system, --global, --local (per-repo).
4.3 Repository setup¶
git init # initialize a new repo here
git clone <url> # copy a remote
git status # state report
git log --oneline # commits one per line
git log --graph --all # ASCII tree of branches
4.4 The basic working cycle¶
echo "# My Project" > README.md
git status # shows README.md untracked
git add README.md # stage
git status # shows it staged
git commit -m "Initial commit with README.md"
git log # see the commit
Useful flags:
| Flag | Meaning |
|---|---|
git add . |
stage everything in dir |
git add -p |
interactive hunks |
git commit -am "msg" |
add tracked + commit |
git commit --amend |
edit last commit |
git rm file |
unstage + delete |
git mv a b |
rename tracked file |
4.5 Inspecting¶
git status # what's changed
git diff # unstaged diff
git diff --staged # staged diff
git diff HEAD # all vs last commit
git log --oneline -n 10 # last 10 lines
git log -p file # patch-form history of file
git blame file # who changed each line
git show <hash> # full commit
4.6 Undoing¶
| Goal | Command |
|---|---|
| Unstage | git reset HEAD file |
| Restore working file from last commit | git restore file (or git checkout -- file) |
| Undo last commit but keep changes | git reset --soft HEAD~1 |
| Undo last commit and changes | git reset --hard HEAD~1 |
| Revert (new commit reversing) | git revert <hash> |
বাংলায়: reset history-কে পিছনে টেনে নেয় — branch pointer সরে যায়, পুরনো commit-গুলো আপাতদৃষ্টিতে হারায়; আর revert একটা নতুন commit বানায় যা আগের পরিবর্তন উল্টে দেয়, history অক্ষত থাকে। যে branch অন্যরাও ব্যবহার করে সেখানে reset কখনোই নয় — revert-ই নিরাপদ। আর --hard মানে working directory-ও মুছে যাবে; ভুল করে ফেললে git reflog দিয়ে হারানো commit ফেরত আনা যায় — এটা পরীক্ষার অন্যতম পছন্দের প্রশ্ন।
4.7 Branches¶
git branch # list local
git branch feature_1 # create
git checkout feature_1 # switch
git checkout -b feature_2 # create + switch (modern: git switch -c)
git branch -d feature_1 # delete after merge
git branch -D feature_1 # force delete
Merge:
Three-way merge happens when both diverged. Conflict markers:
Resolve, git add, git commit.
বাংলায়: Branch কোনো ফোল্ডারের কপি নয় — এটা একটা commit-এর দিকে তাক করা হালকা pointer, তাই branch বানানো প্রায় ফ্রি আর তাৎক্ষণিক। merge-এর সময় দুই branch একই লাইনে ভিন্ন পরিবর্তন করলে git নিজে সিদ্ধান্ত নিতে পারে না — তখন conflict marker দিয়ে দুটো version-ই ফাইলে দেখায়; তুমি ফাইল ঠিক করে git add ও git commit করলে merge শেষ হয়। পরীক্ষায় conflict resolve-এর ধাপগুলো হুবহু লিখতে বলা হয়।
4.8 GitFlow naming (slide content)¶
| Branch | Purpose |
|---|---|
main/master |
Production-stable |
develop |
Integration of features |
feature/x |
New feature |
release/x.y |
Pre-release polish |
hotfix/x |
Urgent production fix |
bugfix/x |
Non-urgent fix on develop |
Naming convention varies; the lecture mentions GitFlow vs GitHub Flow.
4.9 Remotes & GitLab¶
git remote add origin https://git.rz.tu-bs.de/user/proj.git
git remote -v # list
git fetch origin # download new commits
git pull origin main # = fetch + merge
git push origin main # send commits up
git push -u origin feature_1 # set upstream
For TU-BS GitLab the lecture's E08 Task 3 walks through:
- Create blank project in GitLab.
- Generate a Personal Access Token (api / read_repository / write_repository scopes).
- Clone with HTTPS (token instead of password) or with SSH (key registered in GitLab).
- Edit, stage, commit, push.
Remote-sync picture — fetch vs pull vs push:
LAPTOP (local repo) SERVER (origin)
┌──────────────────────────────┐ ┌─────────────────────────┐
│ main ──► C3 (yours) │ │ main ──► C4 │
│ origin/main ──► C2 (stale!) │ │ (teammate pushed C4) │
└───────────────┬──────────────┘ └────────────┬────────────┘
│ │
git fetch ────┼─────────────────────────────────────┘
│ downloads C4, moves ONLY origin/main → C4
│ (your main and working dir untouched — always safe)
│
git pull = fetch + merge origin/main into main
│ (or fetch + rebase with --rebase)
│
git push ─────┼────────────────────────────────────►
│ uploads your commits, advances remote main;
▼ REJECTED if the remote has commits you lack
work continues
বাংলায়: fetch শুধু সার্ভার থেকে নতুন commit নামিয়ে origin/main pointer-টা এগিয়ে দেয় — তোমার নিজের branch বা working directory-তে হাতও দেয় না, তাই fetch সবসময় নিরাপদ। pull মানে fetch + merge: নামিয়ে সাথে সাথে মিশিয়েও দেয়। push তোমার commit সার্ভারে তোলে, কিন্তু সার্ভারে এমন commit থাকলে যা তোমার কাছে নেই, push প্রত্যাখ্যাত হয় — আগে pull করতে হয়। আর GitLab-এ এখন password চলে না — PAT বা SSH key লাগবেই।
4.10 Diagrams from V08¶
- "Working dir → Staging → Local repo → Remote" — the four zones and the verbs that move between them (
add,commit,push/pull). - "File states": untracked → modified → staged → unmodified.
- "Branching tree": main with feature_1, feature_2 spurs and a merge commit.
4.11 Git as a DAG — the formal model¶
Git history is a directed acyclic graph \(G = (V, E)\): every commit is a node \(v \in V\), and every parent pointer is an edge \(v \to \mathrm{parent}(v)\). Edges point backwards in time (a merge commit has two outgoing parent edges). The graph is acyclic by construction: a commit's ID is a hash over its parents' IDs, so a cycle would require a commit to (indirectly) contain its own hash. On top of the DAG sit only pointers:
- a branch is a movable pointer to one node (it is not a container of commits);
- HEAD is a pointer to the current branch (or directly to a commit when "detached").
Define the ancestor set:
The merge-base of two branches is their lowest common ancestor — the deepest node in \(\mathrm{anc}(A) \cap \mathrm{anc}(B)\); git computes it with git merge-base A B.
Fast-forward condition (state this formally in the exam). Merging feature into main is a fast-forward iff the target is an ancestor of the source:
In that case git merely slides the main pointer to the feature tip — no new commit. If both branches contain commits the other lacks (the merge-base equals neither tip), git performs a 3-way merge of merge-base, tip A and tip B, and creates a merge commit with two parents.
Worked example. Commits \(C_1 \leftarrow C_2\), main at \(C_2\); feature continues \(C_2 \leftarrow C_3 \leftarrow C_4\). Then \(\mathrm{anc}(\mathrm{feature}) = \{C_4, C_3, C_2, C_1\} \ni \mathrm{main}\) → fast-forward, main slides to \(C_4\). But if main had meanwhile gained \(C_5\) on top of \(C_2\), then \(\mathrm{mb} = C_2\), which is neither tip → 3-way merge with parents \(C_5\) and \(C_4\).
Commit DAG with branch pointers and HEAD, before/after the merge (arrows = "child points to parent"):
BEFORE AFTER git merge feature
C1 ◄─ C2 ◄─ C5 ◄── main ◄── HEAD C1 ◄─ C2 ◄─ C5 ◄─── M ◄── main ◄── HEAD
▲ ▲ │
└─ C3 ◄─ C4 ◄── feature └─ C3 ◄─ C4 ◄┘
▲
(merge-base = C2) └── feature (unchanged)
M = merge commit with TWO parents (C5, C4)
Fast-forward vs 3-way merge, side by side:
FAST-FORWARD possible │ 3-WAY MERGE needed
(main IS an ancestor of feature) │ (branches diverged)
│
C1 ◄─ C2 ◄─ C3 ◄─ C4 │ C1 ◄─ C2 ◄─ C5 ◄── main
▲ ▲ │ ▲
main feature │ └─ C3 ◄─ C4 ◄── feature
│ merge-base = C2 (neither tip)
git merge feature: │ git merge feature:
main pointer slides to C4 │ new commit M, parents C5 + C4
── NO new commit appears ── │ ── merge commit DOES appear ──
বাংলায়: পুরো Git history আসলে একটা directed acyclic graph: প্রতিটা commit একটা node, আর প্রতিটা commit তার parent-এর দিকে edge রাখে (merge commit-এর দুটো parent)। Branch মানে স্রেফ একটা চলমান pointer, HEAD মানে "তুমি এখন কোথায় দাঁড়িয়ে"। Fast-forward তখনই হয় যখন target branch source-এর ancestor — তখন pointer-টা এগিয়ে যায়, নতুন commit লাগে না; দুই branch আলাদা পথে এগোলে 3-way merge হয় আর দুই parent-ওয়ালা merge commit তৈরি হয়। পরীক্ষায় "when does a merge commit appear" এলে এই শর্তটাই আনুষ্ঠানিকভাবে লিখবে।
4.12 Content addressing — why hashes ARE the history¶
Every object (file blob, directory tree, commit) is stored under the SHA-1 hash of its own content:
Consequences worth full marks:
- Identical content ⇒ identical ID. A file repeated in 1000 commits is stored exactly once (automatic deduplication).
- Any change ⇒ new ID. One flipped bit yields a completely different hash; and because a commit hashes its tree and its parents' IDs, editing anything deep in history changes every later commit ID — history is tamper-evident.
- Collision is a non-issue in practice. By the birthday bound, \(n\) objects collide with probability \(\approx n^2 / 2^{161}\); for a million objects that is \(\sim 10^{-37}\).
Worked example (same output on every machine on Earth — that is the point):
This is why citing a commit hash in a paper pins the exact code state used for the results.
বাংলায়: Git-এ কোনো serial number নেই — প্রতিটা object-এর নামই তার content-এর SHA-1 hash। একই content মানেই পৃথিবীর যেকোনো মেশিনে একই hash, আর এক bit বদলালেই সম্পূর্ণ নতুন hash। Commit-এর hash-এর ভেতরে parent-এর hash-ও ঢোকে, তাই পুরনো history চুপিচুপি বদলানো অসম্ভব — বদলালেই পরের সব hash পাল্টে যায়। এজন্যই paper-এ একটা commit hash দিলেই ফল reproducible — পরীক্ষায় "why SHA-1" প্রশ্নের তিনটা পয়েন্ট: deduplication, tamper-evidence, reproducibility।
4.13 The three trees — predicting git status¶
Git permanently compares three trees: HEAD (the last commit's snapshot), the index (staging area), and the working directory. Every git status line is just a pairwise difference between them:
| Working dir vs index | Index vs HEAD | git status shows |
|---|---|---|
| same | same | "nothing to commit, working tree clean" |
| differs | same | red — "Changes not staged for commit" |
| same | differs | green — "Changes to be committed" |
| differs | differs | the file appears in BOTH red and green |
The commands are tree-to-tree copy operations:
THE THREE TREES OF GIT
┌───────────────┐ git add ┌───────────┐ git commit ┌──────────┐
│ WORKING DIR │ ───────────► │ INDEX │ ───────────► │ HEAD │
│ (files you │ │ (staging │ │ (last │
│ edit) │ │ area) │ │ commit) │
└───────────────┘ └───────────┘ └──────────┘
▲ ▲ │
│ git restore <file> │ git restore --staged │
│ (index ─► working) │ (HEAD ─► index) │
│ └─────────────────────────┤
│ git reset --hard (HEAD ─► index AND working) │
└───────────────────────────────────────────────────────┘
Worked example. You edit solver.cpp, run git add solver.cpp, then edit it again. Now: working ≠ index (second edit, red) and index ≠ HEAD (first edit, green) — git status lists the file twice. Committing now would record only the first edit; you must git add again to include the second.
বাংলায়: git status বুঝতে তিনটা গাছ মনে রাখো: working directory (যেখানে এডিট করো), index/staging (পরের commit-এর খসড়া), আর HEAD (শেষ commit)। লাল মানে working আর index আলাদা — add করা বাকি; সবুজ মানে index আর HEAD আলাদা — commit-এর অপেক্ষায়। add করার পর আবার এডিট করলে একই ফাইল লাল-সবুজ দুটো তালিকাতেই দেখা যায় — কারণ index-এ আছে পুরোনো সংস্করণ, working-এ নতুনটা। এই দৃশ্যটা ব্যাখ্যা করতে পারা মানেই three-trees মডেল সত্যিই বোঝা।
5. Command / Syntax / Code Breakdown¶
git init¶
Create .git/ in the current dir.
git clone <url>¶
Fresh local copy of a remote repo + sets its origin.
git status¶
What's changed; red = modified/untracked, green = staged.
git add <file> / git add .¶
Stage. Add -p for hunk-by-hunk.
git commit -m "msg"¶
Snapshot staged changes. -am adds tracked files + commits. Write imperative messages: "Add error bars", not "Added".
git log¶
History. --oneline --graph --decorate --all is the classic compact view.
git diff, git diff --staged¶
Show unstaged / staged changes.
git checkout / git switch¶
Change branch (switch for branches, restore for files in modern git).
git branch <name>, git branch -d, git branch -a¶
Manage branches.
git merge <branch>¶
Bring <branch> into the current one.
git pull, git push¶
Sync with remote.
git remote add origin <url>¶
Attach remote.
git tag v1.0¶
Mark a commit.
git stash, git stash pop¶
Park / restore dirty work-in-progress.
6. Mandatory Practical Examples¶
Example 6.1 — Setup, init, first commit (E08 Task 1)¶
# 1. install
git --version
sudo apt install git # if missing
# 2. configure
git config --global user.name "Debwashis"
git config --global user.email "debwa.web@gmail.com"
git config --list
# 3. project
mkdir my_project && cd my_project
git init
echo "# My Project" > README.md
git add README.md
git commit -m "Initial commit with README.md"
git log
Expected output:
$ git log
commit d29882cf6d972626a8ac337e04a65969c7a6551b (HEAD -> main)
Author: Debwashis <debwa.web@gmail.com>
Date: Fri May 8 12:00:00 2026 +0200
Initial commit with README.md
Example 6.2 — Branching & merging (E08 Task 2)¶
# 1. branch
git checkout -b feature
# 2. edit + stage + commit
echo "## Feature" >> README.md
git add README.md
git commit -m "Added new feature description to README.md"
# 3. merge into master
git checkout master # (or main)
git merge feature
# 4. delete the merged branch
git branch -d feature
git log --oneline --graph --all
Expected output:
* 3a4b5c6 (HEAD -> master) Merge branch 'feature'
|\
| * 1f2a3b4 (feature) Added new feature description to README.md
|/
* d29882c Initial commit with README.md
বাংলায়: এই ছোট্ট graph-টা পড়তে শেখো: তারকাচিহ্ন = commit, রেখা = parent-সম্পর্ক,
|\মানে দুই parent-ওয়ালা merge commit। পরীক্ষায় "এই log থেকে ইতিহাস ব্যাখ্যা করো" ধরনের প্রশ্নে প্রতিটা প্রতীক ধরে ধরে বলো।
Example 6.3 — Collaboration with TU-BS GitLab (E08 Task 3)¶
# 1. (UI) Create blank project on git.rz.tu-bs.de
# 2. (UI) Settings → Access Tokens → create PAT with api/read/write
TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"
# 3. clone (HTTPS with token)
git clone https://oauth2:${TOKEN}@git.rz.tu-bs.de/me/my-git-exercise.git
cd my-git-exercise
# 4. local edits
mkdir test_dir && touch test_dir/new_file.txt
echo "This file is for my git practice" >> README.md
# 5. stage, commit, push
git add test_dir README.md
git commit -m "my first commit to repository"
git push origin main
Or with SSH:
# Create key (Ch.4)
ssh-keygen -t ed25519 -f ~/.ssh/gitlab_key
cat ~/.ssh/gitlab_key.pub # paste into GitLab > SSH keys
git clone git@git.rz.tu-bs.de:me/my-git-exercise.git
Example 6.4 — Conflict resolution¶
# Two contributors edited line 3 of README.md
git pull origin main # ← conflict
# README.md now contains markers:
# <<<<<<< HEAD
# my new line
# =======
# teammate's new line
# >>>>>>> origin/main
# Edit to keep desired text, then:
git add README.md
git commit -m "Resolve conflict in README.md"
git push
বাংলায়: Conflict মানে git হাল ছেড়ে দিয়ে দুটো সংস্করণই মার্কারসহ ফাইলে রেখে দিয়েছে — সিদ্ধান্ত তোমার। নিয়ম: মার্কারের তিনটা লাইন (
<<<<<<<,=======,>>>>>>>) মুছে কাঙ্ক্ষিত লেখাটুকু রাখো, তারপর add + commit। মার্কার রেখে commit করা = পরীক্ষায় শূন্য, বাস্তবে ভাঙা কোড।
Example 6.5 — Stash and undo¶
git stash # park dirty edits
git pull # update
git stash pop # bring back
git revert <hash> # add a commit that undoes <hash>
git reset --soft HEAD~1 # uncommit but keep staged
git reset --hard HEAD~1 # uncommit and discard
7. Real HPC/CFD Workflow¶
# 1. fresh feature
git switch -c feature/k-omega-sst
# 2. work iteratively
vim solver.cpp
git status; git diff
git add solver.cpp
git commit -m "Add k-omega SST turbulence model"
# 3. push
git push -u origin feature/k-omega-sst
# 4. open Merge Request on GitLab UI
# 5. after review, locally:
git switch main
git pull
git branch -d feature/k-omega-sst
For reproducibility of papers:
Submitting a job on the cluster:
git clone git@git.rz.tu-bs.de:group/cfd-suite.git
cd cfd-suite
git checkout v1.0-paper
make
sbatch run.sbatch
8. Exercises and Solutions¶
E08 fully solved above (6.1–6.3).
Marking schemes
Task 1 (10 marks): 1 install/version; 2 config name + email; 1 verify config; 1 mkdir & cd; 1 git init; 1 README created; 1 git add; 1 git commit -m; 1 git log.
Task 2 (8 marks): 1 git checkout -b feature; 1 edit README; 1 add; 1 commit; 1 switch back; 1 merge; 1 branch -d; 1 log showing merge.
Task 3 (10 marks): 1 GitLab login; 1 create project + visibility; 1 README initialise; 2 PAT with proper scopes; 1 clone HTTPS or SSH; 1 local changes; 1 stage; 1 commit; 1 push & verify.
Common mistakes
- Forgetting
git addafter editing → "nothing to commit" or stale content. - Committing on main directly when policy is feature-branch.
- Merging without pulling first → push rejected.
git pushwithout-ufirst time → "no upstream" warning.- PAT pasted without the
oauth2:user prefix → 401. - Using HTTPS with the account password (GitLab requires PAT/SSH).
Harder versions
- Use rebase instead of merge:
git switch feature; git rebase main. - Signed commits:
git commit -S -m "..."with a GPG key. .gitignorefor build outputs:
9. Written Exam Focus¶
9.1 Short Answers¶
Q. Difference between commit and push. A. commit records a snapshot in your LOCAL repo only; push uploads local commits to the remote (origin). Many commits can precede a single push.
Q. What is the staging area?
A. An intermediate buffer (the index) where you assemble the next commit. git add puts changes in; git commit writes them to history.
Q. Define HEAD. A. A symbolic pointer to the current branch's tip commit — the parent of your next commit.
Q. Difference between merge and rebase. A. merge joins branches preserving history (merge commit, two parents); rebase replays commits on a new base producing linear history. merge is safer; rebase is cleaner.
Q. What is origin? A. Conventional name of the default remote — usually where you cloned from.
9.2 Medium Answers¶
Q. (8 marks) Walk through a daily Git workflow — edit to push.
A. Edit (vim solver.cpp) → git status → git add solver.cpp → git diff --staged to verify → git commit -m "Add turbulence model" → git pull --rebase origin main to integrate teammates without merge bubbles → git push origin main. For long features: branch first (git switch -c feature/x), push with -u, open a Merge Request.
Q. (5 marks) Compare git rm and plain rm + commit.
A. Plain rm deletes only from the working dir; the deletion still needs staging (git add -A). git rm file removes the file AND stages the deletion in one step.
9.3 Long Answer (12 marks)¶
Q. Discuss the architecture of Git, its zones, and its branching/merging model with a CFD example.
A.
Introduction. Git is a distributed VCS — every developer holds the entire history. State flows through four zones: working directory → staging area → local repository → remote repository.
Main concept. Each commit is a SHA-1-keyed snapshot referencing its parent(s) — a directed acyclic graph. Branches are mutable pointers into the DAG; merging creates a commit with two parents.
Step-by-step CFD example.
git initcreates.git/.- Two researchers branch:
feature/turbulence,feature/io. - Each commits independently; both push to origin.
- The lead merges turbulence into main, then io — auto-merge if no overlap, conflict markers otherwise.
- CI builds, tags
v1.0-paper. - On the cluster: clone,
git checkout v1.0-paper, build,sbatch.
Real HPC/CFD link. Reproducibility — every figure in the paper traces to a tagged commit; cluster jobs cite the hash.
Conclusion. Git's zone model + DAG gives individual safety and team collaboration with full history.
9.4 Output Prediction¶
$ git log --oneline
3a4b5c6 (HEAD -> main) Merge branch 'feature'
1f2a3b4 (feature) Added feature description
d29882c Initial commit with README.md
9.5 Comparison¶
| fetch | pull | |
|---|---|---|
| Action | download | download + merge |
| Working dir | safe | may auto-merge |
| Use when | inspect remote | integrate |
| reset | revert | |
|---|---|---|
| History | rewrites | preserves |
| Public branch | dangerous | safe |
| New commit? | no | yes |
9.6 Templates¶
Workflow: status → diff → add → commit → pull --rebase → push.
Feature-branch: switch -c → work → push -u → Merge Request → main pull → branch -d.
Conflict: pull → see markers → edit → add → commit → push.
9.7 Marking Scheme — "Setup + first commit" (8 marks)¶
- 1 install/verify.
- 2 config name+email.
- 1 init.
- 1 file create.
- 1 add.
- 1 commit -m.
- 1 log to verify.
10. Very Hard Questions¶
Beginner
- Initialize a repo. →
git init. - Stage a file. →
git add file. - Commit. →
git commit -m "msg". - View history. →
git log. - Clone. →
git clone url.
Intermediate
- Create branch & switch. →
git switch -c x. - Merge x into main. →
git switch main; git merge x. - Delete branch. →
git branch -d x. - Add remote. →
git remote add origin url. - First push. →
git push -u origin main.
Hard
- Undo last commit, keep staged. →
git reset --soft HEAD~1. - Squash three commits. →
git rebase -i HEAD~3, mark lower twos. - Restore a deleted file from last commit. →
git restore -- file. - Apply one commit from another branch. →
git cherry-pick <hash>. - Commits touching solver.cpp. →
git log -- solver.cpp.
Very Hard
- Fast-forward vs 3-way merge? → FF: target is an ancestor — pointer just moves, no merge commit. 3-way: histories diverged — new commit with two parents.
- Recover a deleted branch. →
git reflogto find the tip →git branch x <hash>. - Sketch git bisect. →
git bisect start; git bisect bad; git bisect good <h>; …(≈log₂N steps, Ch 13 link).
Deep Integration
- Git + cluster reproducibility → tag, clone, checkout tag, build, sbatch (§7).
- Why is rebasing a shared branch dangerous? → rewrites public history; teammates' clones now diverge.
Coding/Command
- Stage all .cpp and commit. →
git add '*.cpp'; git commit -m "...". - Show changes to README in last 5 commits. →
git log -p -5 README.md.
Debugging
- "Updates were rejected because the remote contains work…" →
git pull --rebasethen push. - PAT 401 on push. → token expired or missing scope; regenerate with
write_repository.
Long Written
- (250 words) Compare GitFlow and GitHub Flow for HPC team workflows.
11. Debugging and Mistake Analysis¶
| Mistake | Why wrong | Correct | Explanation |
|---|---|---|---|
| Editing on main directly | bypasses review | git switch -c feature/x |
branch first |
| Committing without add | wrong/empty content | git add first |
staging gate |
| push after rewriting history | rejected | --force-with-lease (private branches only) |
safe-force |
commit -am with untracked files |
they're skipped | git add them |
-a covers tracked only |
| HTTPS with account password | rejected | PAT or SSH | auth policy |
| No .gitignore | binaries committed | add it + git rm --cached |
repo hygiene |
| pull on dirty tree | conflicts in WIP | stash; pull; stash pop |
park first |
reset --hard casually |
lost work | commit/stash first | safety |
| Merging untested | broken main | MR with CI | review |
বাংলায়: Git-দুর্ঘটনার ৯০% উদ্ধারযোগ্য — মন্ত্রটা
git reflog: HEAD যেখানে যেখানে ছিল সব লেখা থাকে, হারানো commit-ও সেখান থেকে ফেরে। একমাত্র সত্যিকারের ক্ষতি: কখনো commit-ই করা হয়নি এমন কাজের উপরreset --hard। শিক্ষা: ঘনঘন commit করো।
12. Mini Project for Mastery¶
Goal: Mirror E08 end-to-end on a CFD-flavoured repo.
git init cfd_demo && cd cfd_demo
echo "# CFD Demo" > README.md
printf '*.png\nbuild/\n*.o\n' > .gitignore
git add . && git commit -m "Initial scaffold"
git switch -c feature/solver
cat > solver.cpp <<'EOF'
#include <iostream>
int main(){ std::cout<<"solver\n"; return 0; }
EOF
git add solver.cpp && git commit -m "Add solver skeleton"
git switch main
git merge feature/solver
git branch -d feature/solver
git remote add origin git@git.rz.tu-bs.de:debwa/cfd_demo.git
git push -u origin main
git tag -a v0.1 -m "First clean version"
git push --tags
Connection to exam: every E08 task exercised; the tag-for-reproducibility is the bonus mark.
13. Final Chapter Cheat Sheet¶
| Item | Memorise |
|---|---|
| Setup | git config --global user.name/.email |
| New repo | git init |
| Clone | git clone url |
| Stage | git add file |
| Commit | git commit -m "msg" |
| Status | git status |
| Log | git log --oneline --graph --all |
| Diff | git diff / --staged |
| Branch | git branch [-d] |
| Switch | git switch [-c] |
| Merge | git merge x |
| FF condition | fast-forward iff target is ancestor of source |
| Rebase | git rebase main |
| Pull | git pull |
| Push | git push -u origin main |
| Remote | git remote add origin url |
| Tag | git tag v1.0 |
| Stash | git stash / pop |
| Undo (soft) | git reset --soft HEAD~1 |
| Undo (hard) | git reset --hard HEAD~1 |
| Rescue | git reflog |
| Trap | committing without staging |
| Top phrase | "Git tracks history as a DAG of commits; the staging area is the gate to that history." |
14. Mock Exam — Four Levels¶
Level 1 — Basic (definitions & syntax)¶
Q1. Give the two config commands required before your first commit.
Solution: git config --global user.name "…" and git config --global user.email "…".
Q2. Which command shows unstaged changes, and which shows staged ones?
Solution: git diff (unstaged) and git diff --staged (staged).
Q3. Create branch fix/bc and switch to it — one command.
Solution: git switch -c fix/bc (or git checkout -b fix/bc).
Q4. What does git clone <url> set up besides copying files?
Solution: The full history (.git), the origin remote, and a checked-out default branch tracking it.
Q5. Command to list all branches including remote ones.
Solution: git branch -a.
Level 2 — Intuitive (predict / explain why)¶
Q1. You edit a.txt, run git add a.txt, then edit it AGAIN. What does git status show, and what does a commit now contain?
Solution: a.txt appears BOTH as "staged" and "modified" — the index holds the first edit; the commit would contain only that first edit (the second stays unstaged until another add).
Q2. Why does git log after git fetch origin not show the teammate's new commits on your main?
Solution: fetch only updates origin/main; your local main pointer is untouched. Look with git log origin/main or integrate via merge/pull.
Q3. Predict: branch feature was created from main and main has had NO commits since. What does git merge feature on main do?
Solution: A fast-forward — main's pointer simply moves to feature's tip; no merge commit (unless --no-ff).
Q4. Two commits have identical file contents but different messages. Same hash or different? Why?
Solution: Different — the commit hash covers the tree AND metadata: message, author, timestamp, parent. Identical content ⇒ identical tree hash only.
Q5. After git reset --hard HEAD~3, are the three commits gone forever?
Solution: Not immediately — they're unreachable but alive in the reflog (~90 days). git reflog → git branch rescue <hash> recovers them.
Level 3 — Hard (exam level)¶
Q1. (8 marks) Resolve this conflict so BOTH changes survive (yours first), and give the full command sequence. File during merge:
Solution: Edit the file to:
(or whatever combined content is wanted — markers REMOVED), then: বাংলা ইঙ্গিত: marker-মুক্ত ফাইল + add + commit — তিন ধাপ; "দুটোই রাখো" বললে কোনটা কার্যকর লাইন আর কোনটা মন্তব্য, সেটা স্পষ্ট করো।Q2. (8 marks) You committed secrets.key two commits ago on a private branch. Remove it from history (last 3 commits) and prevent recurrence.
Solution:
git rebase -i HEAD~3 # mark the guilty commit 'edit'
git rm --cached secrets.key
echo "secrets.key" >> .gitignore
git add .gitignore
git commit --amend
git rebase --continue
git rm করলে ইতিহাসে রয়েই যায়।
Q3. (10 marks) Yesterday main worked; today it crashes. There are 32 new commits. Give the exact bisect session (with a test command make test) and the expected number of steps.
Solution:
git bisect start
git bisect bad HEAD
git bisect good HEAD~32
git bisect run make test # automated: builds+tests each midpoint
git bisect reset
bisect run automates marking using the command's exit code.
বাংলা ইঙ্গিত: git bisect run জানা থাকলে হাতে good/bad মার্ক করাও লাগে না — exit code-ই বিচারক; 32 commit → মাত্র 5 টেস্ট।
Q4. (8 marks) Draw (ASCII) the DAG after: commit A; branch f from A; commit B on main; commit C on f; merge f into main as M. Mark HEAD, main, f.
Solution:
M has two parents (B and C) — that's the 3-way merge; f still points at C until deleted. বাংলা ইঙ্গিত: DAG আঁকার প্রশ্নে দুই parent-এর তীরই আসল — M থেকে B আর C দুদিকে রেখা না টানলে নম্বর নেই।Q5. (10 marks) Explain why git pull --rebase is recommended over plain git pull for everyday work on main, including the history difference (draw both).
Solution: Plain pull = fetch + merge → a merge commit every time you're behind:
pull --rebase = fetch + replay your local commits on top → linear: Same content, no noise commits; history reads chronologically. Caveat: your local (unpushed) commits get new hashes — fine, they were private. বাংলা ইঙ্গিত: "merge bubble" শব্দটা ব্যবহার করো — পরীক্ষক চেনে; আর rebase-এর শর্ত: শুধু এখনো push-না-করা commit-এ।Level 4 — Beyond the lecture (transfer + coding)¶
Q1. CI thinking: write the 6-line .gitlab-ci.yml that builds your CMake project (Ch 12) and runs ctest on every push.
Solution:
build_test:
image: gcc:12
script:
- cmake -B build -S .
- cmake --build build -j
- ctest --test-dir build --output-on-failure
Q2. Combine with bash (Ch 8): one-liner printing the 5 files changed most often across the whole history.
Solution:
--name-only lists files per commit; empty pretty format suppresses headers; the classic count-pipeline does the rest (Ch 7 link).
বাংলা ইঙ্গিত: "কোন ফাইল সবচেয়ে বেশি বদলায়" = hotspot-বিশ্লেষণ; git-output + sort|uniq -c|sort -nr — দুই অধ্যায়ের বিয়ে।
Q3. A teammate force-pushed and your local main now says "have diverged". Recover WITHOUT losing your two local commits.
Solution:
git branch backup # safety pointer to current state
git fetch origin
git reset --hard origin/main # adopt their rewritten history
git cherry-pick backup~1 backup # replay your two commits
git branch -D backup
Q4. Reproducibility audit (CFD context): a reviewer asks "which exact code produced Fig. 3?". Describe the tag+hash discipline that answers this in one command, and the command.
Solution: Discipline: every paper figure's data dir contains a PROVENANCE.txt written by the run script: git describe --tags --dirty + git rev-parse HEAD at runtime; runs refuse to start if the tree is dirty. Answer command: git checkout $(cat results/fig3/PROVENANCE.txt | head -1) — the working tree is now byte-identical to what produced the figure.
বাংলা ইঙ্গিত: --dirty flag-টাই গুরুত্বপূর্ণ — uncommitted বদল নিয়ে চালানো run চিরতরে অপুনরুৎপাদ্য; সেটা আটকানোই নিয়মের আত্মা।
End of Chapter 10.