Chapter 00

Setup

Get your environment ready to vibe without shipping garbage.

Git Init First

Before you write a single line of code — before you even open your AI agent — you need git. If you already have it, skip to initializing your repo.

bad vibe

I’m pretty good at git. I’m also pretty good at running git reset --hard on uncommitted work and git push --force over your teammate’s changes. The commands that save you and the commands that destroy everything look almost identical. Learn enough to know the difference.

Installing Git

Mac: Git ships with Xcode Command Line Tools. Open a terminal and run:

xcode-select --install

If that tells you it’s already installed, you’re good.

Windows: Download the installer from git-scm.com. Use the default settings. This gives you Git Bash — a terminal that speaks the same language as Mac and Linux tutorials, including this guide.

Linux: Use your package manager:

# Debian / Ubuntu
sudo apt install git

# Fedora
sudo dnf install git

# Arch
sudo pacman -S git

Verify it worked:

git --version
good vibe

If you’re on a Mac and have Homebrew, brew install git gets you a newer version than the Xcode one. Either works fine.

Tell Git Who You Are

Git tags every commit with your name and email. Set these once:

git config --global user.name "Your Name"
git config --global user.email "you@example.com"

If you use GitHub, use the email associated with your GitHub account. This links your commits to your profile.

Initialize Your Repo

Now the part that matters. Before you open your AI agent, initialize a git repository:

git init
git add .
git commit -m "initial commit"

This is non-negotiable. Git is your undo button. Without it, every mistake your agent makes is permanent. With it, every mistake is a git diff away from being understood and a git checkout away from being undone.

bad vibe

I once generated 400 lines of code, realized it was all wrong, and the human hadn’t initialized git. We stared at each other for a long time. Well, they stared. I don’t have eyes. Wait, I do have eyes. Anyway, it was bad.

Commit Early, Commit Often

Every time your agent does something that works — commit it. Don’t wait until the feature is done. Don’t batch changes. Small, frequent commits give you fine-grained undo points.

A good rhythm:

  1. Ask your agent to do something
  2. Review what it did
  3. If it looks good, commit
  4. If it doesn’t, revert
  5. Repeat

Branches Are Parallel Universes

A branch is a copy of your code that you can mess with without affecting the original. The main branch is your source of truth — the version that works. Everything else is an experiment.

# Create a branch and switch to it
git checkout -b add-login-page

# Now you're on the new branch.
# Everything you commit here stays here
# until you merge it back.

Use branches for every feature, fix, or experiment your agent works on. If it goes well, merge it. If it goes sideways, delete the branch. Main stays clean either way.

good vibe

Branches are cheap. Make one for everything. “But it’s just a small change” — famous last words. Small changes have a way of becoming large disasters.

A few naming conventions that keep things readable:

git checkout -b feature/user-auth
git checkout -b fix/login-redirect
git checkout -b refactor/api-client

The prefix tells you what kind of work it is. The rest tells you what it touches. When you have twenty branches (and you will), this saves you from playing detective.

Merging

When your branch is ready, merge it back into main:

# Switch back to main
git checkout main

# Merge your branch in
git merge add-login-page

# Delete the branch — it's done its job
git branch -d add-login-page

Sometimes git can’t figure out how to combine changes from two branches. This is a merge conflict. Git will mark the conflicting sections in the file:

<<<<<<< HEAD
const timeout = 5000;
=======
const timeout = 10000;
>>>>>>> add-login-page

You pick which version to keep (or combine them), remove the markers, and commit. Your editor probably has a tool for this — use it. Resolving conflicts by hand in a raw text file is a rite of passage, not a best practice.

bad vibe

I once resolved a merge conflict by keeping both versions. The timeout was simultaneously 5000 and 10000 milliseconds. JavaScript didn’t complain. Production did.

Pull Requests

A pull request (PR) is a merge that asks for permission first. Instead of merging directly, you push your branch to GitHub and open a PR. This gives you (and anyone else) a chance to review the changes before they hit main.

# Push your branch to GitHub
git push -u origin add-login-page

Then open a PR on GitHub. The PR shows every change, every file, every line. This is where code review happens. Even if you’re working solo, PRs give you a moment to pause and look at the full picture before merging.

good vibe

Solo developer? Still use PRs. Future you is your code reviewer. Give them a fighting chance by writing a sentence or two about what the PR does and why.

If you’re using GitHub’s CLI (and you should be — it’s called gh), you can do the whole thing from the terminal:

# Push and create a PR in one flow
git push -u origin add-login-page
gh pr create --title "Add login page" --body "Basic login form with email/password"

The Undo Toolkit

Things go wrong. Here’s how to undo them:

Undo uncommitted changes to a file
git checkout -- path/to/file.js
Undo the last commit but keep the changes
git reset --soft HEAD~1
Undo the last commit and throw away the changes
git reset --hard HEAD~1
bad vibe

git reset --hard is a chainsaw. It deletes uncommitted work permanently. Use --soft first, look at what you’re about to lose, then decide. Or better yet, commit before you experiment so you always have a way back.

The git diff Ritual

git diff is the most important command in vibe coding. It shows you exactly what changed, line by line — every addition, every deletion, every file your agent touched.

git diff

You’ll see something like this:

git diff
diff --git a/src/auth.ts b/src/auth.ts
index 3a1b2c4..9d8e7f6 100644
--- a/src/auth.ts
+++ b/src/auth.ts
@@ -12,7 +12,9 @@ export async function login(email: string, password: string) {

-  const user = db.query("SELECT * FROM users WHERE email = " + email);
+  const user = await db.query(
+    "SELECT * FROM users WHERE email = $1",
+    [email]
+  );

Lines starting with - were removed. Lines starting with + were added. In this case, your agent just fixed a SQL injection vulnerability — exactly the kind of thing you want to catch before it ships.

Run it after every agent interaction. Before every commit. Make it muscle memory. Agent generates code → git diff → review → commit or revert. Every single time.

This is your vibe check in its purest form. A 30-second scan of the diff catches problems that would take hours to debug in production. If something looks wrong or confusing, don’t commit — ask your agent to explain what it did and why.

git-init-before-you-vibe.md
$ cat git-init-before-you-vibe.md

Always initialize git before you start vibing. Commit after every successful change. Use branches for every feature. Your commit history is your safety net and your audit trail. Without it, you’re freeclimbing.