Broken Gitlinks
Course 1, Chapter 9 introduced the broken-gitlink incident from the website→debserver reorg as a teaser — enough to recognise the symptom. This final chapter of Course 2 goes the rest of the way: what a submodule actually is when set up correctly, why a folder can end up tracked as one by accident, and the full diagnose-and-fix process.
During the reorg, a subfolder that used to be its own separate git repository lost its .git directory in the move. The parent repository, however, still had a recorded entry treating that subfolder as a gitlink — git's internal mechanism for "this folder is itself a repository, tracked by commit reference rather than by its actual file contents." With the inner .git gone, that reference pointed at a commit that no longer existed anywhere reachable.
The result: git status on the parent repo showed a single confusing M website line instead of the real, individual file changes inside that folder — because git was treating the entire folder as one opaque unit, exactly as it would a properly configured submodule.
What a Submodule Actually Is, Set Up Correctly
A real git submodule is a deliberate, supported feature: embedding one git repository inside another, where the outer repo tracks which exact commit of the inner repo to use — not the inner repo's file contents directly. This is genuinely useful for shared libraries or vendored dependencies that need to stay pinned to a specific version.
$ git submodule add https://github.com/someone/shared-lib.git libs/shared-lib
Cloning into 'libs/shared-lib'...
This creates a proper .gitmodules file at the repo root, recording the submodule's URL and path — and the inner folder gets a gitlink entry (mode 160000, same mode flagged in Course 1, Chapter 9) that's intentional and documented.
.gitmodules. A folder tracked with mode 160000 but with no corresponding .gitmodules entry is the unambiguous signature of an accident — exactly what the reorg produced. This is the single fastest way to distinguish "someone meant to do this" from "something broke."
How a Folder Becomes an Accidental Gitlink
The Full Diagnose-and-Fix Process
cat .gitmodules (or note its absence entirely) — confirms whether this was ever intentional.$ git rm --cached website
rm 'website'
$ # Re-add the folder's actual contents as ordinary tracked files
$ git add website/
$ git status
Changes to be committed:
new file: website/index.html
new file: website/styles/main.css
... (every individual file, now tracked normally)
$ git commit -m "Stop tracking website/ as a broken gitlink; track contents normally"
After this, git status shows real, individual file changes inside that folder again — exactly the fix this session's actual incident needed, demonstrated here as a repeatable, named procedure rather than a one-off troubleshooting session.
.git per project, full stop, unless deliberately using a properly documented submodule — sidesteps this entire category of problem. When reorganising folders (Course 1, Chapter 9), explicitly checking for stray .git directories with find . -name .git -type d before and after a move catches this before it becomes a confusing future incident.
Chapter 10 Quick Reference — and Course 2 Wrap-Up
- A real submodule always has a matching .gitmodules entry — its absence is the signature of an accident
- git ls-files -s, mode 160000 — confirms a path is tracked as a gitlink, intentional or not
- Common causes: a nested repo lost its .git, an accidental git init inside a tracked folder, a wholesale-copied third-party project with its own .git left in place
- The fix: git rm --cached <path> (removes the broken gitlink reference) → git add <path>/ (re-tracks contents normally) → commit
- Prevention: one .git per project; check for stray nested .git folders before/after any reorg
- Course 2 recap: branching strategies (Ch1) → merge vs rebase (Ch2) → conflicts (Ch3) → forks (Ch4) → stash/cherry-pick/tags (Ch5) → issues/projects (Ch6) → code review (Ch7) → Actions basics (Ch8) → team-scale collaboration (Ch9) → broken gitlinks (Ch10)
- Next: Course 3 — Advanced Git & GitHub Mastery (internals, interactive rebase, reflog, proper submodules, advanced Actions, security, large repos, bisect, and full disaster-recovery scenarios)