Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Pull Request Template

## Goal
<!-- What does this PR accomplish? 1 sentence. -->

## Changes

-

## Testing
<!-- How did you verify it? -->

## Checklist

- [ ] Title is a clear sentence (≤ 70 chars)
- [ ] Commits are signed (`git log --show-signature`)
- [ ] `submissions/labN.md` updated
262 changes: 262 additions & 0 deletions submissions/lab2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# Lab 2 submission

## Task 1

### 1.1: Exploring the repo

```console
$ git rev-parse HEAD
6f636654d85046b446f487b0632c3dfcbc9fd499
```

```console
$ git cat-file -t HEAD
commit
```

```console
$ git cat-file -p HEAD
tree 08a2d32d81ec697cc3f043680300e3be173028da
parent bfa345b2244ccfe8ae4d92caa24ed90f13fa6282
author danielpancake <45727078+danielpancake@users.noreply.github.com> 1781518457 +0500
committer danielpancake <45727078+danielpancake@users.noreply.github.com> 1781518457 +0500
gpgsig -----BEGIN SSH SIGNATURE-----
U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgNWBFYt8AE/NlEc5E0+8cXvq0AY
LMkrAp8TxeqwGXPHcAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
AAAAQB6IT5OFRk1kW9KCelcyeqpKGXpR3F0O1ZbKBcLtV2EWP2EYGSEK31lW3MLv7S+ZuG
uaXU6JByiwJfhz131H2gg=
-----END SSH SIGNATURE-----

docs: add PR template

Signed-off-by: danielpancake <45727078+danielpancake@users.noreply.github.com>
```

```console
$ git cat-file -p 08a2d32d81ec697cc3f043680300e3be173028da
040000 tree 78d51eb792c558b6b1da9ee23b3b3bc40992e60a .github
100644 blob 1c0a1e94b7bbdd951f456cda51af6b8484cc3cee .gitignore
100644 blob d10c04c6e7e0014f4fe883599c11747c15012d4e README.md
040000 tree 7d0898a908e274ea809722844cdbd836f3b1c05a app
040000 tree 89bc50bc368eff78a23dcf65c83a925674de2e66 labs
040000 tree 3f11973a71be5915539cb53313149aa319d69cb5 lectures
```

Reading the `.gitignore` blob.

```gitignore
# ⚠️ KEEP THIS FILE MINIMAL.
#
# This .gitignore is inherited by every student fork. Anything listed here
# is something a student CANNOT `git add` without `-f`. So this file must
# ONLY contain:
# (a) instructor-only paths (refs/), and
# (b) machine-generated junk that NOBODY should ever commit.
#
# Do NOT add lab DELIVERABLES here (scan reports, SBOMs, go.sum, k8s
# manifests, CI workflows, Dockerfiles, playbooks, dashboards, …). Students
# are told to commit those in their submission PRs — ignoring them upstream
# silently breaks the lab. When in doubt, leave it OUT of this file.

# ── Instructor-only ─────────────────────────────────────────────
# Reference submissions (dry-run worked examples). Never pushed upstream;
# students never see these. This is the one path that is intentionally hidden.
refs/

# ── Machine-generated junk (no one commits these) ───────────────
# Compiled binaries / local runtime state
app/quicknotes
app/data/
/quicknotes
*.exe

# Vagrant runtime state (Lab 5) — the Vagrantfile IS committed; .vagrant/ is not
.vagrant/

# Nix build symlinks (Lab 11) — flake.nix + flake.lock ARE committed; result is not
result
result-*

# Terraform state — MUST never be committed (can contain secrets)
*.tfstate
*.tfstate.backup
.terraform/

# Python virtualenvs / caches
.venv/
__pycache__/
*.pyc

# Editor / IDE
.vscode/
.idea/
*.swp

# OS noise
.DS_Store
Thumbs.db

# Local agent config (not part of the course)
.claude/

# NOTE: deliberately NOT ignored, because students commit them as lab evidence:
# submissions/labN.md (lab reports)
# .github/workflows/*.yml (Lab 3 CI)
# Dockerfile, compose.yaml (Lab 6)
# ansible/ (Lab 7)
# monitoring/ (Lab 8)
# *.sbom.cdx.json, zap-*.html/json, trivy-*.txt (Lab 9 scan evidence)
# flake.nix, flake.lock (Lab 11)
# wasm/main.go, spin.toml, go.sum (Lab 12)
```

### 1.2: Looking inside `.git/`

```console
$ ls .git/
COMMIT_EDITMSG FETCH_HEAD HEAD config description index packed-refs
hooks/ info/ logs/ objects/ refs/
```

```console
$ cat .git/HEAD
ref: refs/heads/feature/lab2
```

```console
$ ls .git/refs/heads/
feature main
```

```console
$ ls .git/objects/ | head
08 0a 0c 0e 0f 13 14 1a 27 29
```

```console
$ find .git/objects -type f | wc -l
45
```

**Interpretation:** `HEAD` is a symbolic ref pointing at the current branch (`refs/heads/feature/lab2`); `refs/heads/` holds the branch tips (here a `feature/` namespace dir plus `main`). Under `objects/`, each two-char subdirectory is the first byte of an object's SHA-1. `config`, `index`, `hooks/`, `logs/`, and `packed-refs` hold repo settings, the staging area, hook scripts, the reflog, and packed ref tips respectively.

### 1.3: Simulating disaster + recovery

Two WIP commits, then `git reset --hard HEAD~2`:

```console
$ git commit -S -s -m "wip(lab2): start"
[feature/lab2 4b156ac] wip(lab2): start
$ git commit -S -s -am "wip(lab2): more progress"
[feature/lab2 24be0e1] wip(lab2): more progress
$ git reset --hard HEAD~2
HEAD is now at 6f63665 docs: add PR template
```

After the reset, the two commits appear gone:

```console
$ git log --oneline -3
6f63665 docs: add PR template
bfa345b docs(lab3): matrix renames required checks — warn + ci-ok gate pattern; set honest cache expectations
356420b docs(lab1,lab2): clarify GitHub auth vs signing SSH key roles; add publickey-denied pitfalls
```

The reflog still has the "lost" commits:

```console
$ git reflog
6f63665 (HEAD -> feature/lab2, origin/main, origin/HEAD, main) HEAD@{0}: reset: moving to HEAD~2
24be0e1 HEAD@{1}: commit: wip(lab2): more progress
4b156ac HEAD@{2}: commit: wip(lab2): start
6f63665 (HEAD -> feature/lab2, origin/main, origin/HEAD, main) HEAD@{3}: checkout: moving from main to feature/lab2
```

Recover to the most recent commit (`24be0e1`):

```console
$ git reset --hard 24be0e1
HEAD is now at 24be0e1 wip(lab2): more progress
$ git log --oneline -3
24be0e1 wip(lab2): more progress
4b156ac wip(lab2): start
6f63665 docs: add PR template
```

**`git gc` risk:** The commits survived only because the reflog still referenced them, and `git gc` will not prune reflog-reachable objects, so a routine `gc` between the reset and recovery would have been harmless (reflog entries default to 90 days reachable / 30 days unreachable). The danger is `git gc --prune=now` or an expired reflog: once those entries are gone, `4b156ac` and `24be0e1` become unreferenced and get collected, and `git reset --hard 24be0e1` then fails with `unknown revision`.

## Task 2

### 2.1: Annotated, signed release tag

List the tags (`tag` objecttype confirms they are annotated):

```console
$ git tag -l --format='%(refname:short) %(objecttype) %(*objecttype)'
v0.0.1 tag commit
v0.1.0-lab2-danielpancake tag commit
```

Verify the signature:

```console
$ git tag -v "v0.1.0-lab2-danielpancake"
object 6f636654d85046b446f487b0632c3dfcbc9fd499
type commit
tag v0.1.0-lab2-danielpancake
tagger danielpancake <45727078+danielpancake@users.noreply.github.com> 1781522885 +0500

Lab 2 milestone — version control deep dive
Good "git" signature for 45727078+danielpancake@users.noreply.github.com with ED25519 key SHA256:9X3YQHiqrWoDjoaRwFmJ5YC04AAtZX8GDBNeS3atwEk
```

### 2.2: Rebase + force-with-lease

Move `main` forward, then rebase `feature/lab2` and force-push with lease:

```console
$ git switch main
Already on 'main'
Your branch is up to date with 'origin/main'.
$ git commit -S -s --allow-empty -m "docs: upstream moved while you worked"
[main 221274b] docs: upstream moved while you worked
$ git push origin main
To https://github.com/danielpancake/DevOps-Intro
6f63665..221274b main -> main
$ git switch feature/lab2
Switched to branch 'feature/lab2'
$ git fetch origin
$ git rebase origin/main
Successfully rebased and updated refs/heads/feature/lab2.
$ git push --force-with-lease origin feature/lab2
To https://github.com/danielpancake/DevOps-Intro
* [new branch] feature/lab2 -> feature/lab2
```

### 2.3: Before/after graphs + reflection

**Before rebase** (WIP commits sit directly on `6f63665`):

```console
$ git log --oneline --graph
* 24be0e1 (HEAD -> feature/lab2) wip(lab2): more progress
* 4b156ac wip(lab2): start
* 6f63665 (tag: v0.1.0-lab2-danielpancake) docs: add PR template
* bfa345b (upstream/main, upstream/HEAD) docs(lab3): matrix renames required checks — warn + ci-ok gate pattern; set honest cache expectations
* 356419b docs(lab1,lab2): clarify GitHub auth vs signing SSH key roles; add publickey-denied pitfalls
```

**After rebase** (`221274b` inserted below the WIP commits; SHAs change to `598c46f`/`8e5c5e8`):

```console
$ git log --oneline --graph
* 8e5c5e8 (HEAD -> feature/lab2, origin/feature/lab2) wip(lab2): more progress
* 598c46f wip(lab2): start
* 221274b (origin/main, origin/HEAD, main) docs: upstream moved while you worked
* 6f63665 (tag: v0.1.0-lab2-danielpancake) docs: add PR template
* bfa345b (upstream/main, upstream/HEAD) docs(lab3): matrix renames required checks — warn + ci-ok gate pattern; set honest cache expectations
```

**Merge vs rebase.** I use **rebase** on a private, in-progress feature branch to keep its history linear and replay my work on top of the latest `main`, with no merge-bubble noise. The trade-off is that it rewrites commit SHAs, so it is only safe on branches nobody else has based work on (hence `--force-with-lease`, never plain `--force`). I'd choose **merge** for integrating a shared or completed branch: it preserves the true history, doesn't rewrite commits others may have pulled, and records when integration happened. Rule of thumb: rebase to tidy local history before sharing, merge to combine published history.