Git Gud

From zero to your first pull request.

01What you'll walk out with

  • A repo on your machine — forked and cloned, not downloaded
  • Commits you wrote yourself — with messages that make sense
  • A branch pushed to GitHub — your name on it
  • A pull request opened and reviewed — into a repo you don't own
  • A branch you merged yourself — on the fork that is yours
  • A merge conflict you fixed — on purpose, calmly
  • The flow open source runs on — and the one your group project needs

02Setup check

Run these now. Raise a hand if anything errors.

git --version                                     # is Git installed?
java -version                                     # JDK 17 or newer
javac -version                                    # compiler, not just Java

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 should match your GitHub account.

03Why bother

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.

  • No more final.html, final2.html, final_FINAL_v3.html
  • Every change is reversible and you can see who did what, when, and why
  • Try risky things safely on a branch, throw it away if it fails

04The only diagram that matters

Working directory
your edits
papers on your desk
Staging area
git add
the envelope you're filling
Repository
git commit
sealed and labeled
Remote
git push
GitHub — called "origin"

git status tells you where everything currently sits. Run it after every command today.

05The demo repo: Booko

Just something to practice on — a tiny buko juice ordering app that runs in the terminal. Plain Java — no Maven, no Gradle, nothing to install beyond a JDK.

booko/
└── src/
    ├── Main.java           # menu loop
    ├── Drink.java
    └── BookingService.java
├── team.md                 # you'll add your name here
├── ISSUES.md               # mirrors the GitHub issues
└── .gitignore

Run it:

javac -d out src/*.java   # compile every .java into out/
java -cp out Main         # run the Main class from out/
Lab 1 · 15 min

Fork, clone, commit

You can't push to a repo you don't own — that's why open source runs on forks. Fork JanDexter/booko, unchecking "Copy the main branch only".

git clone https://github.com/<your-username>/booko.git   # get your own copy
cd booko                                                 # go into it
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

06Writing a commit message

Finish this sentence: "This commit will…"

  • Add my name to the team list — good
  • Fix typo in the welcome banner — good
  • update — useless in three weeks
  • asdfgh — we've all done it

Imperative mood, under ~50 characters, one logical change per commit.

07Branches

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
Lab 2 · 13 min

Your own feature branch

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.

08Heads up: GitHub login

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.

  • Windows — nothing to install. A browser window opens on your first push. Sign in, done.
  • macOS / Linux — run gh auth login first, pick HTTPS, authenticate in the browser
  • Say yes to the browser — the credential is stored once; you never do this again

Stuck? Raise a hand — it's faster than the fallback (Settings → Developer settings → tokens (classic), tick repo, paste as password).

09Issues

An issue is a to-do item that lives in the repo instead of in someone's head. That's all it is.

  • A title, a description, a number — #1, #2, #3…
  • Anyone can open one — bug reports, feature ideas, questions
  • Comment to ask questions — that's where the maintainer answers
  • Write "Closes #3" in your PR — GitHub closes it automatically on merge

Six open issues, all labeled good first issue. Pick any — you're each on your own fork, so duplicates are fine.

Lab 3 · 10 min

Open a pull request

  • Refresh your fork on GitHub — click the "Compare & pull request" banner
  • Check the base repo says JanDexter/booko — you're proposing into the original
  • Write a title and two lines — what changed, and why
  • Add "Closes #<your issue number>" — links the PR to the issue
  • Create pull request
  • Then review someone else's — in the PR list, pick one with no comments yet

A PR is a proposal, not a delivery. It's the conversation before code reaches main — and we'll merge one of yours on screen.

10Merge conflicts

A conflict happens when two branches change the same lines of the same file. Git refuses to guess which one you meant.

<<<<<<< HEAD
static final String HEADER = "Booko — fresh buko, booked daily";
=======
static final String HEADER = "Booko — 20% off all buko!";
>>>>>>> origin/promo-banner

Top is yours, bottom is theirs. These are plain text. Delete the markers, keep the version the file should end up with, save.

Lab 4 · 16 min

Break it on purpose

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 src/Main.java, resolve the markers, then:

git add src/Main.java            # marks the conflict resolved
git commit                       # message is pre-filled, just save
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.

11Close your own loop

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.

12Undo, by situation

Throw away edits to a filegit restore <file>
Unstage something you addedgit restore --staged <file>
Fix the last commit messagegit commit --amend
Undo a commit already pushedgit revert <hash>
Bail out of a mergegit merge --abort
See what you didgit log --oneline --graph

13.gitignore

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.

14Every command, in plain English

git clone <url>copy a repo onto your machine
git remote -vwhich GitHub repos you're wired to
git statuswhat changed, and what's staged
git diffthe 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 pulldownload 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

15Your loop from now on

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.

That's it

You now use Git.

Fork → branch → PR → review is what every open-source project runs on. You just did it end to end.

  • Go find a real issue — search GitHub for label:"good first issue"
  • git stash — park unfinished work
  • git rebase — tidy history before a PR
  • learngitbranching.js.org — visual practice, genuinely good

Questions → open an issue on the workshop repo.