From zero to your first pull request.
Open gitgud.jandexter.me to access workshop material and demo repos.
Run these now. Raise a hand if anything errors.
git --version # is Git installed? java -version # Java track only javac -version # Java track only, JDK 8+ git config --global user.name "Your Name" # whose name is on commits git config --global user.email "you@example.com" # match your GitHub login git config --global init.defaultBranch main # name the first branch main git config --global core.editor "code --wait" # if you use VS Code
The email must match your GitHub account. On the JavaScript track, skip the two Java lines — you need nothing installed but Git.
Git is a save-point system for your work — and the only sane way for several people to write on the same project without overwriting each other.
git status tells you where everything currently sits. Run it after every command today.
A tiny buko juice ordering app. Two versions, same menu and same prices — pick the language you're comfortable in. The Git is identical either way.
Both carry team.md for your name, ISSUES.md mirroring the GitHub issues, and a promo-banner branch we break on purpose later.
You can't push to a repo you don't own — that's why open source runs on forks. On the fork page, below the description, untick "Copy the main branch only". It is ticked by default, and you need the other branches in Lab 4.
Fork it: github.com/JanDexter/booko/fork — Java
github.com/JanDexter/booko-js/fork — JavaScript
git clone https://github.com/<your-username>/booko.git # ...or booko-js cd booko # ...or booko-js git remote -v # origin = your fork git log --oneline # the history so far
Open team.md, add your name and your favorite place in Davao. Then:
git status # look at this output git diff # the exact lines you changed git add team.md # stage it for the next commit git status # now look again — what moved? git commit -m "Add <name> to team list" # save it, with a message
Finish this sentence: "This commit will…"
Imperative mood, under ~50 characters, one logical change per commit.
A branch is just a movable label pointing at a commit. Creating one is instant and costs nothing.
main A───B───C
\
feat/quantity D───E # your work, isolated
The rule: main always works. All new work happens on a branch.
git branch # where am I? git switch -c feat/my-thing # create and move git switch main # go back
GitHub will not accept your account password from the terminal. Your first push has to sign you in — don't type a password, let the browser do it.
gh auth login first, pick HTTPS, authenticate in the browserStuck? Raise a hand — it's faster than the fallback (Settings → Developer settings → tokens (classic), tick repo, paste as password).
Pick an issue from the list, then:
git switch main # back to the trunk git pull # get the latest git switch -c feat/<short-name> # -c creates it, then moves you # edit your files, save git add . # stage everything you changed git commit -m "<what you changed>" # save it, with a message git push -u origin feat/<short-name> # upload it, first time only
-u is only needed on the first push. After that, plain git push.
An issue is a to-do item that lives in the repo instead of in someone's head. That's all it is.
Six open issues, all labeled good first issue. Pick any — you're each on your own fork, so duplicates are fine.
JanDexter/booko — you're proposing into the originalA PR is a proposal, not a delivery. It's the conversation before code reaches main — and we'll merge one of yours on screen.
A conflict happens when two branches change the same lines of the same file. Git refuses to guess which one you meant.
Top is yours, bottom is theirs. These are plain text. Delete the markers, keep the version the file should end up with, save.
On booko-js it's the same one line in app.js: const HEADER = "Booko - fresh buko, booked daily";
git switch feat/<short-name> # back onto your branch git fetch origin # download, do not merge yet git merge origin/promo-banner # this WILL conflict
Open the conflicted file — src/Main.java on Java, app.js on JavaScript — resolve the markers, then:
git add src/Main.java # Java — marks the conflict resolved git add app.js # JavaScript — same thing git commit -m "Resolve merge conflict" # -m skips the editor git push # send it up
No promo-banner? You forked main-only. Run git remote add upstream https://github.com/JanDexter/booko.git, then merge upstream/promo-banner instead.
A conflict is not an error. If you panic: git merge --abort puts everything back.
Stuck in an editor you can't type in? That's vim. Type :wq then Enter to save and quit.
Your PR is a proposal to a repo you don't own, so it lands when the maintainer says so. The fork, though, is yours — merge it there yourself.
git switch main # your fork's main git merge feat/<short-name> # fast-forward, nothing to resolve git push # your repo, your merge
Two things with your name on them: a branch you merged, and an open PR proposing the same work to someone else's project.
| Throw away edits to a file | git restore <file> |
| Unstage something you added | git restore --staged <file> |
| Fix the last commit message | git commit --amend |
| Undo a commit already pushed | git revert <hash> |
| Bail out of a merge | git merge --abort |
| See what you did | git log --oneline --graph |
Some things must never reach a repo. List them once and Git stops seeing them.
out/ *.class # compiled output, never commit this .env # API keys, passwords — the big one *.log .DS_Store .idea/
A secret pushed once is a secret leaked forever. Rotating the key is the only real fix — deleting the commit is not enough.
| git clone <url> | copy a repo onto your machine |
| git remote -v | which GitHub repos you're wired to |
| git status | what changed, and what's staged |
| git diff | the exact lines you changed |
| git add <file> | stage it for the next commit |
| git commit -m "…" | save what's staged, with a message |
| git switch -c <name> | create a branch and move onto it |
| git pull | download the latest and merge it in |
| git push -u origin <name> | upload your branch the first time |
| git merge <branch> | join another branch into yours |
git switch main && git pull # start from the latest # on a fork: git pull upstream main git switch -c feat/thing # branch # ... work ... git add . # stage git commit -m "Do the thing (closes #3)" git push -u origin feat/thing # push # open a PR, get it reviewed, merge
That's 90% of professional Git. Everything else is a lookup.
Fork → branch → PR → review is what every open-source project runs on. You just did it end to end.
label:"good first issue"Questions → open an issue on the workshop repo.