Skip to main content
← The Owens Vibe Coding & Development Institute
Rigor toolkit

Git Workflow Reference

The Git commands and flows you actually use day to day — branch, rebase, fix, ship.

Git Workflow Reference

Everything you need to keep your history clean, your team happy, and your production server breathing.

Git is the version-control backbone of every professional project. This reference covers the commands and workflows you will reach for every single day — from a quick status check to untangling a bad commit that slipped into production. Bookmark it; come back as often as you need.


The Everyday Loop

git status                   # See what's changed, staged, or untracked
git diff                     # Unstaged changes (line-by-line)
git diff --staged            # What's already staged and ready to commit

git add -p                   # Stage changes interactively, hunk by hunk (best habit)
git add <file>               # Stage a specific file
git commit -m "feat: add login form validation"

git push origin main         # Push to remote
git pull --rebase origin main  # Pull + replay your local commits on top (avoids noise merges)

Why add -p? It forces you to review every line you're committing, catching debug logs and secrets before they're immortalized.


Branching & the Feature-Branch Workflow

git branch                        # List local branches
git branch -a                     # List all branches (local + remote)

git checkout -b feature/my-thing  # Create and switch to a new branch
# shorthand for: git branch feature/my-thing && git checkout feature/my-thing

git push -u origin feature/my-thing  # Push branch and set upstream tracking

git checkout main                 # Switch back to main
git branch -d feature/my-thing    # Delete branch after merging
git push origin --delete feature/my-thing  # Delete the remote branch too

Workflow:

  1. Always branch off main (or develop if your team uses it).
  2. One feature = one branch = one pull request.
  3. Keep branches short-lived — days, not weeks.

Merge vs Rebase

Merge — preserves history, creates a merge commit

git checkout main
git merge feature/my-thing       # Fast-forward if possible, else merge commit
git merge --no-ff feature/my-thing  # Force a merge commit even if FF is possible

Rebase — rewrites history, linear timeline

git checkout feature/my-thing
git rebase main                  # Replay your branch commits on top of main
git push --force-with-lease      # Only safe after rebasing a private branch

The Golden Rule

Never rebase a branch that has already been pushed and shared with others. Rebasing rewrites commit hashes. If teammates have pulled your branch, you will cause chaos.

Rule of thumb: rebase your own private feature branches before opening a PR; merge when integrating into shared branches.


Resolving Merge Conflicts

When Git can't auto-merge, it pauses and marks the file:

<<<<<<< HEAD
const port = 3000;
=======
const port = 8080;
>>>>>>> feature/change-port
  • <<<<<<< HEAD — your current branch's version
  • ======= — divider between the two versions
  • >>>>>>> feature/change-port — the incoming branch's version

Steps to resolve:

# 1. Open the conflicted file, decide which version (or blend both) is correct
# 2. Delete ALL three marker lines (<<<, ===, >>>)
# 3. Save the file, then:
git add <conflicted-file>
git commit                       # Git pre-fills the merge commit message

# If you want to abort and start over:
git merge --abort
git rebase --abort               # During a rebase conflict

Undo Toolbox

CommandWhat it undoesSafe?
git restore <file>Discard unstaged changes in a fileSafe (working tree only)
git restore --staged <file>Unstage a file (keep changes)Safe
git revert <hash>Create a new commit that undoes a commitSafe — history preserved
git reset --soft HEAD~1Undo last commit, keep changes stagedSafe locally
git reset --mixed HEAD~1Undo last commit, keep changes unstagedSafe locally
git reset --hard HEAD~1Undo last commit, discard all changesDestructive
git restore src/index.js              # Discard unstaged edits
git restore --staged src/index.js     # Move back out of staging area

git revert abc1234                    # Safe undo (adds a reverting commit)

git reset --soft HEAD~1               # "Oops, wrong message" — recommit cleanly
git reset --mixed HEAD~1              # Undo commit and unstage, but keep edits
git reset --hard HEAD~1               # Nuclear: commit gone, edits gone — no recovery

Rule: use revert on anything already pushed. Use reset only on commits that never left your machine.


Finding a Bad Commit with git bisect

Binary-search through history to find the commit that introduced a bug:

git bisect start
git bisect bad                   # Current commit is broken
git bisect good v1.4.0           # Last known good commit (tag or hash)

# Git checks out a middle commit — test it, then tell Git:
git bisect good                  # This one is fine
git bisect bad                   # This one is broken

# Repeat until Git prints: "abc1234 is the first bad commit"
git bisect reset                 # Return to HEAD when done

Stash & Cherry-Pick

# Stash — temporarily shelve work-in-progress
git stash                        # Save dirty working tree
git stash pop                    # Restore most recent stash
git stash list                   # See all stashes
git stash drop stash@{0}         # Delete a specific stash

# Cherry-pick — apply a single commit from another branch
git cherry-pick abc1234          # Apply that commit to the current branch
git cherry-pick abc1234 --no-commit  # Apply changes without committing yet

Good Commit Messages

Use Conventional Commits style — machines and humans both love it:

<type>(<scope>): <short description>

[optional body explaining WHY, not WHAT]

[optional footer: BREAKING CHANGE, Closes #42]

Types: feat · fix · docs · style · refactor · test · chore · ci

# Good examples
git commit -m "feat(auth): add OAuth2 Google login"
git commit -m "fix(cart): prevent negative quantities on decrement"
git commit -m "refactor(api): extract pagination helper into shared util"
git commit -m "docs: update README with local setup steps"

# Bad examples (don't do this)
git commit -m "fix stuff"
git commit -m "WIP"
git commit -m "asdfgh"

Atomic commits: one logical change per commit. If you can't summarize it in one line, it's probably two commits.


.gitignore Essentials

# Dependencies
node_modules/
vendor/

# Build output
dist/
build/
.next/
out/

# Environment & secrets
.env
.env.local
.env.*.local
*.pem
*.key

# OS clutter
.DS_Store
Thumbs.db

# Editor files
.vscode/settings.json
.idea/
*.swp
git check-ignore -v <file>       # Debug: why is this file being ignored?
git rm --cached <file>           # Stop tracking a file already committed (keeps local copy)

If You Accidentally Committed a Secret

# Immediately rotate the secret (change the password/token NOW — assume it's compromised)

# Remove it from history with git-filter-repo (preferred over filter-branch):
pip install git-filter-repo
git filter-repo --path .env --invert-paths

# Force-push all branches (coordinate with your team first):
git push origin --force --all

# Then add the file to .gitignore so it never happens again
echo ".env" >> .gitignore
git commit -am "chore: add .env to gitignore"

Never commit node_modules, build artifacts, .env files, API keys, passwords, or certificates. Ever.


Build It Right, Or Don't Build It At All. 🏛️

Other rigor resources

🏛️ Build It Right, Or Don't Build It At All.