Everything the Nexus team needs to work on shared code without fear — commits, branches, forks, pull requests — with pictures. Built from our own repos, using our own mistakes.
Git is a chain of snapshots. Every time you commit, git photographs your entire project and links the photo to the previous one. That's it. Every other git concept — branches, merges, reverts — is just an operation on this chain.
536c2af), an author, a date and a message.main) — just a movable name-tag pointing at one commit..git folder.Commits are never edited — history only grows. "Undoing" means either adding a new commit that cancels an old one (safe), or moving a name-tag backwards and abandoning commits (destructive). Section 07 covers both.
A change travels through three stations on its way into history. Understanding this one picture removes 80% of git confusion.
Why the middle station exists: you might touch five files but only want three of them in this snapshot. git add lets you choose what the commit contains.
git status # where is everything right now? (use constantly)
git add helloworld.py # stage one file
git add . # stage everything changed
git commit -m "Add greeting for Emilio" # snapshot, with a message
git log --oneline # see the chain
Run git status before and after every command until it becomes reflex. It always tells you which area each file is in, and usually suggests the next command.
Everything so far happened on your machine. GitHub holds a second copy of the repo — a remote — so the team can share one history. Four verbs move commits between the two:
| Command | Direction | What it does |
|---|---|---|
git clone <url> | GitHub → you | First-time download: full copy of the repo + its whole history. |
git pull | GitHub → you | Bring down commits teammates pushed, merge them into your branch. Start every session with this. |
git push | you → GitHub | Upload your new commits. Rejected if you're missing commits that GitHub has — pull first, then push. |
git fetch | GitHub → you | Like pull but look, don't touch: downloads info without changing your files. |
Commits only exist on GitHub after you push. Committing all day without pushing = your work is safe locally, but invisible to the team (and to backups).
A branch lets you build something without touching main. Since a branch is just a name-tag (section 01), creating one is instant and free. The team rule is simple: nobody commits directly to main — every change rides a branch, then merges in.
# start from fresh main
git checkout main
git pull
# create + switch to a branch (name it after the task)
git checkout -b feature/add-name
# ...edit files, then commit as usual...
git add .
git commit -m "Add my name to helloworld"
# publish the branch to GitHub
git push -u origin feature/add-name
# jump between branches anytime
git checkout main
git checkout feature/add-name
Switching branches physically swaps the files in your folder to that branch's snapshot. Nothing is lost — the other branch's work waits on its own name-tag.
A conflict happens when two branches change the same lines of the same file and git refuses to guess who wins. It is not an error — it's git asking you a question. The file gets marked up like this:
print("hello world")
<<<<<<< HEAD
print("made by Emilio")
=======
print("made by David")
>>>>>>> feature/david-name
Read it as: between <<<<<<< and ======= is your version; between ======= and >>>>>>> is theirs. To resolve:
git add <file> then git commit — that commit records the resolution.Conflicts can't destroy work — both versions are saved in history. If you panic mid-merge, git merge --abort rewinds to before the merge and you can try again with a teammate.
Prevention beats cure: pull often, keep branches short-lived, and avoid two people editing the same file in the same sprint when possible.
A fork is your personal server-side copy of the team repo. You push freely to your fork, then ask the team to take your changes via a pull request (PR) — the review gate where code gets discussed before touching team main.
# 1 · sync with the team
git checkout main
git pull upstream main
# 2 · branch for your task
git checkout -b feature/my-task
# 3 · work: edit → add → commit (repeat)
# 4 · publish to your fork
git push -u origin feature/my-task
# 5 · open the PR on GitHub (fork page → “Compare & pull request”)
# teammates review · discuss · approve · merge
# 6 · after merge: sync again, delete the branch
git checkout main
git pull upstream main
git branch -d feature/my-task
The PR is where a second pair of eyes catches bugs, where decisions get written down, and where main stays permanently deployable. It feels slower; it's much faster than debugging broken main.
Different mistakes need different tools. Ordered from gentlest to most dangerous:
| Situation | Command | Danger |
|---|---|---|
Un-stage a file (undo git add) | git restore --staged <file> | none |
| Discard edits in a file (back to last commit) | git restore <file> | ⚠ edits gone |
| Undo a pushed commit, safely | git revert <commit> | none — adds an inverse commit |
| Fix the last commit message / add a forgotten file (not pushed yet) | git commit --amend | low if unpushed |
| Erase local commits entirely (not pushed) | git reset --hard <commit> | ⚠⚠ commits abandoned |
| Rewrite history on GitHub | git push --force | 🔥 breaks teammates' clones |
A normal push can only add commits — GitHub rejects anything that would erase history. --force overrides that check and replaces the branch wholesale. Rule: force-push your own fork freely; force-push a shared branch never — and if you absolutely must, warn the team so everyone runs git fetch + git reset --hard origin/main to resync.
We practiced this live on Vault: three files were added, then removed with three revert commits (safe — history preserved), one was restored by reverting the revert, and finally the whole branch was rewound with reset + force push to tsuresuregusa's last commit — acceptable only because the team was tiny and warned. Every tool above, used on purpose. The erased commits stayed recoverable in the local reflog for weeks.
git checkout main && git pull upstream main # 1 · sync
git checkout -b feature/<task> # 2 · branch
...edit files...
git status # 3 · check
git add . && git commit -m "<what & why>" # 4 · snapshot
git push -u origin feature/<task> # 5 · publish
open PR on GitHub → review → merge # 6 · ship
Pull before you start. Working on stale code is how conflicts are born.
Never commit to main. Branch per task, always, even for one-line fixes.
Commit small, message well. One idea per commit; the message says why.
Push daily. Unpushed work is invisible to the team and unbacked-up.
Never force-push shared branches. Your fork: fine. Team main: never.
When lost: git status. It tells you where you are and what to do next.