Try it now: Open the — run real Git commands in your browser with live commit graphs. No install required.

Learn by doing: Spend 30 minutes with Learn Git Branching — a visual tutorial for branching puzzles. The muscle memory will save you hours later.

Quick reference: Need a command fast? Hit ⌘K / Ctrl+K to search, or open the Git Cheat Sheet from the header for a complete command reference.

What Is Git?

Branch the risky experiments, contain the failures, merge the wins — every save becomes a recoverable moment

Git is a version control system — software that tracks every change you make to your code and lets you travel back in time to any previous version. Think of it like an unlimited undo history for your entire project, not just a single file.

If you're using AI tools like Copilot, Cursor, or Claude to write code, Git becomes even more critical. AI can generate hundreds of lines in seconds — some brilliant, some broken. Without Git, a bad AI suggestion could overwrite your working code with no way back. With Git, you can:

  • Review every AI change before it becomes permanent
  • Undo any mistake instantly — whether it's yours or the AI's
  • Branch to experiment in a safe playground without risking stable code
  • Collaborate with teammates by sharing code through a structured review process

Git was created in 2005 by Linus Torvalds (the creator of Linux) and is used by virtually every software team in the world. Learning it is non-negotiable if you want to write code professionally — with or without AI.

Installing Git

Before anything else, you need Git on your machine. Pick your operating system:

The easiest way is to install the Xcode Command Line Tools, which include Git. Open Terminal and run:

Install Xcode CLI Tools
xcode-select --install

A dialog will pop up asking you to install. Click Install and wait a few minutes.

Alternatively, if you use Homebrew:

Or via Homebrew
brew install git

To confirm Git is installed, open a terminal and run:

Verify installation
git --version
# git version 2.44.0

If you see a version number, you're ready to go. The exact number doesn't matter much — anything 2.30+ is fine.

What Is a Repository?

A repository (or "repo") is simply a project folder that Git is tracking. Inside it, Git maintains a hidden .git folder that stores the entire history of every file — every change, by whom, and when.

There are two kinds of repositories you'll work with:

Local Repository

The copy on your own computer. You make changes, stage them, and commit them here. It's completely private until you decide to share.

Remote Repository

A copy hosted on a service like GitHub, GitLab, or Bitbucket. This is how you share code with teammates and keep a backup in the cloud.

The typical workflow is: you clone (download) a remote repo to your machine, make changes locally, then push (upload) your changes back. Git keeps both copies in sync.

Every change in Git goes through three stages — your Working Directory (where you edit files), the Staging Area (where you prepare a snapshot), and the Repository (where snapshots are permanently saved as "commits"). Here's how they relate:

You edit files in your Working Directory, stage the ones you approve, commit them as a permanent snapshot, and push to share with your team.

Part 1

Enterprise Onboarding: Connecting to Your Codebase

"Every great journey begins with a single git clone."

Before you write your first line of code — or prompt your first AI — you need Git set up and talking to your team's repository. This is a one-time ritual: configure your identity, authenticate, and clone. Once it's done, it's done forever.

1.1 First-Time Local Configuration

Every commit you make carries a name and email — your digital signature. Before anything else, Git needs to know who you are.

Your identity is baked into every commit — configure it once and forget about it
Note
The Problem: You have a new machine with a fresh Git installation. Before your first commit, Git requires you to set your identity -- a permanent digital signature baked into every change you make.

In an enterprise, traceability is paramount. Every commit must be tied to a specific individual. Using your correct enterprise name and email is non-negotiable.

Set your identity
git config --global user.name "Your Name"
git config --global user.email "your-enterprise-email@company.com"
Tip
The --global flag saves this for every Git repository on your computer. You only need to do this once.

Don't want to use the terminal? No problem. VS Code will actually prompt you to configure your identity the first time you try to use Git. You can also open the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) and search for "Git: Config" to set these values without touching the terminal.

Vibe it

"Set up my Git config with my name and email for this project"

"Configure Git to use VS Code as my default editor"

1.2 Authentication with Personal Access Token

Your company's code lives in a private repository. To access it, you need to prove you're allowed in — and passwords are no longer enough.

A personal access token proves your identity to GitHub without a password
Warning
The Problem: Your company's code is in a private repository. Most enterprises have disabled password authentication for Git operations. You need a Personal Access Token (PAT).
  1. Go to GitHub SettingsDeveloper settingsPersonal access tokens
  2. Click Generate new token (classic)
  3. Name it descriptively (e.g., "Work Laptop")
  4. Set an expiration (90 days recommended)
  5. Select scopes: repo and read:org
  6. Click Generate token and copy it immediately
Clone using your token
git clone https://github.com/Your-Enterprise/your-project.git
# Username: your-github-username
# Password: your-personal-access-token

Storing Your Credentials

Save credentials (choose your OS)
# macOS - Store in Keychain (recommended)
git config --global credential.helper osxkeychain

# Windows - Use Windows Credential Manager
git config --global credential.helper manager

# Linux - Store in encrypted file
git config --global credential.helper libsecret
Tip
After configuring a credential helper, the next time you clone, pull, or push, Git will prompt you once and then save the credentials for future use.

That said, if you're using VS Code, you can skip the PAT setup entirely. VS Code handles GitHub authentication for you -- when you clone a private repo or push for the first time, it opens your browser to sign in. No tokens to generate, copy, or store:

VS Code
VS Code automatically opens your browser to sign in to GitHub -- no tokens to manage.
Vibe it

"Help me set up SSH authentication for GitHub"

"Generate an SSH key and add it to my GitHub account"

1.3 The First Pull (Cloning the Repository)

Your team's code exists on a remote server. Cloning is the act of bringing the entire project — every file, every branch, every commit in its history — right onto your machine.

Cloning creates a complete copy of the remote repository on your machine
Note
The Problem: The code exists on the server, but not on your machine. You need to download a complete copy ("clone") of the repository.

To get a copy of the project on your machine, run the clone command with the repository URL your team shared with you:

Clone the repository
git clone https://github.com/Your-Enterprise/your-project.git

The VS Code Way

  1. Open VS Code. Click "Clone Repository" on the Welcome page
  2. Or use the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) and type Git: Clone
  3. Paste the HTTPS URL. VS Code handles authentication automatically
  4. Choose a save location, then open the folder
VS Code
Use Cmd+Shift+P → 'Git: Clone' and paste the repository URL. VS Code handles the rest.

One thing to keep in mind after cloning:

Note
When you clone, you only get the default branch (e.g., main) checked out. Other branches exist as remote-tracking branches until you explicitly check them out.
Vibe it

"Clone the repo at github.com/our-team/project into my projects folder"

"Clone this repository and set up the development environment"

Part 2

The Core Safety Loop: Your "Save Game" for AI Coding

"Commit early, commit often. Every save point is a universe you can return to."

This is the heartbeat of your entire Git workflow. Every time the AI generates code, you'll follow this three-step rhythm: check what changed, approve what you trust, and freeze it in time. Master this loop and you'll never lose work again.

The diagram above shows the full cycle you'll repeat every time you work with AI-generated code. Let's break it down:

Important
This is your fundamental daily workflow. It's a three-step process: the AI makes a change, you review it, and you "save" it. In Git, this loop is Status → Stage → Commit. For this to be an effective safety net, commit after every single logical, working change.

2.1 "What Did the AI Just Do?"

You just prompted the AI to refactor a module, and it went silent for a moment. What exactly did it touch? Before you do anything, you need situational awareness.

Always check your status before staging — know exactly what the AI changed
Note
The Problem: You prompted Copilot or Cursor to "refactor this function." It applies changes across several files. What exactly did it touch?

git status is your "heads-up display." The output shows two categories:

"Changes not staged" (Red)

Files Git tracks that were modified but not yet approved for the next save.

"Untracked files" (Red)

Brand-new files the AI created that Git has never seen before.

The good news? You don't actually need to type git status in the terminal. VS Code shows you all of this visually. Just click the Source Control icon in the Activity Bar (the branch icon on the left sidebar). The badge shows how many files changed, and each file is labeled M (modified), U (untracked), or D (deleted):

VS Code
The Source Control panel is your visual 'git status' — modified (M), untracked (U), and deleted (D) files are listed with clear badges.

You can also spot changes right in the editor without opening the Source Control panel. VS Code adds colored indicators in the gutter (the narrow strip to the left of your code): green for added lines, blue for modified lines, and a red triangle for deleted lines. Click any indicator to preview the change inline:

VS Code
Colored gutter indicators let you spot changes at a glance — green (added), blue (modified), and red (deleted). Click to preview.
Vibe it

"What files did you just change? Show me a summary"

"Check git status and explain what each changed file does"

2.2 Reviewing and Staging the AI's Work

Now you know what changed. The next step is the most important one: reviewing the AI's work line by line, and only approving what you trust. This is staging — your quality gate.

Selective staging lets you approve AI changes hunk by hunk
Warning
The Problem: git status shows the AI changed five files. Blindly trusting this is how bugs are introduced. You must review every line and then "stage" the changes you approve.

Option 1: Stage All (the "trusting" add)

Stage everything
git add .
Caution
This is fast but dangerous. If the AI added a temporary debug file or a flawed change, you just approved it without review.

Option 2: Stage One File (the "surgical" add)

Stage specific file
git add src/my_file.py

Option 3: Stage Parts of a File (the "AI-first developer's" add)

Tip
This is your single most powerful review tool. The AI made multiple changes in one file, and you only want to accept some of them. git add --patch walks you through every individual block of changes ("hunk") interactively.

Here's how to start an interactive staging session:

Interactive staging
git add --patch  # or git add -p

For each hunk, Git asks: y (stage), n (skip), s (split into smaller pieces), q (quit). In the Try it yourself playground below, git add -p is simplified to file-by-file staging — type y or n on the next line for each file.

The VS Code Way: Visual Staging

This is where VS Code really shines. Instead of typing cryptic y/n/s/q responses in the terminal, you get a beautiful side-by-side Diff Editor. To stage an entire file, just hover over it and click the + button:

VS Code
Hover over any file and click + to stage it. The file moves from 'Changes' to 'Staged Changes'.

When you click a file in the Changes list, VS Code opens the Diff Editor -- a side-by-side view showing the old version (left) and new version (right). This makes it easy to review exactly what changed before staging:

VS Code
The Diff Editor shows your changes side-by-side: red highlights deletions, green highlights additions. Review before you stage.

For even more precision, click a file to open the Diff Editor, then select specific lines and right-click → "Stage Selected Ranges". This is the visual equivalent of git add -p, but far easier to use:

VS Code
In the Diff Editor, select specific lines and use the gutter to stage just those changes -- even more precise than git add -p.
Vibe it

"Stage only the files related to the authentication feature"

"Review the diff of each changed file and stage the ones that look correct"

Warning
Accidentally staged everything with git add .? Use git restore --staged <file> to unstage specific files before committing. This is especially critical if you accidentally staged .env files with secrets or debug files. Try the "Staged secrets and debug files" playground scenario to practice this.

2.3 Creating the Save Point

You've reviewed the changes and staged the ones you trust. Now it's time to freeze this moment in time — a commit is your permanent save point that you can always travel back to.

Each commit is a checkpoint you can always travel back to
Note
The Problem: You've staged your reviewed changes. Now, bundle them into a permanent, immutable "save point" -- a commit.
Create a commit with a message
git commit -m "feat: Add user authentication endpoint"

The command itself is simple, but the message you write matters more than you might think.

Important
Writing Good Commit Messages: Your code shows how a change was made; your commit message must explain the why. Use Conventional Commits format:
TypeWhen to UseExample
feat:A new feature for the userfeat: Add login button to homepage
fix:A bug fix for the userfix: Resolve dimension mismatch
docs:Documentation only changesdocs: Update API reference
style:Formatting, missing semicolons, etc.style: Fix indentation in utils
refactor:Code change that neither fixes a bug nor adds a featurerefactor: Simplify form validation
test:Adding or correcting teststest: Add unit tests for auth
chore:Build process or tools changeschore: Update dependencies
perf:A code change that improves performanceperf: Cache database queries
Tip
AI Integration: GitHub Copilot and Cursor can analyze your staged changes and suggest a commit message. Always verify it follows your team's standards.

In VS Code, committing is just as simple: type your message in the input box at the top of the Source Control panel and click the Commit button (or press Cmd+Enter). Notice the sparkle icon next to the input -- click it to let AI generate a commit message from your staged changes:

VS Code
The full Source Control view: your staged changes, the commit message input, and the Commit button. Click the sparkle icon to auto-generate a message.

Here's the AI commit message feature in action. After staging your changes, click the sparkle icon and Copilot will analyze your diff and write a descriptive message for you:

VS Code
Click the sparkle icon and AI generates a commit message based on your staged changes. Always review it before committing!

Try It: The Complete Loop

Run real Git commands in your browser. Type help in the terminal for the full command list.
The Core Safety Loop

Loading playground...

Vibe it

"Commit the staged changes with a good conventional commit message"

"Write a descriptive commit message for these changes and commit them"

Part 3

Parallel Universes: Branching for AI Experiments

"A branch is a safe space to be wrong. Create one every time you have an idea."

Branches are what make Git magical. They let you experiment freely — try a wild AI refactor, explore an alternative architecture — without ever risking the stable codebase. Think of them as parallel timelines that you can merge back or discard entirely.

Important
The most important rule in collaborative software development: you never, ever work directly on the main branch. The main branch represents the official, stable, production-ready code. Your work must happen in an isolated "parallel universe" called a branch.

3.1 "I Have a New Idea (or AI Prompt)"

You have a feature idea — or maybe an ambitious AI prompt that might refactor half your codebase. Before you do anything, create a branch where it's safe to experiment.

Branches let you experiment without risking the stable codebase
Note
The Problem: You want to try a new feature or a massive AI-driven refactor. Before you write a single line or prompt, create a safe, isolated branch.

First, make sure you're on main and it's up to date. Then create your branch:

Create and switch to a new branch
git switch -c "feature/my-new-idea"
# Older equivalent: git checkout -b "feature/my-new-idea"

In VS Code, this is even easier. Look at the bottom-left corner of your window -- you'll see the current branch name (e.g., "main"). Click it and you'll get a dropdown where you can switch to existing branches or select "+ Create new branch..." to make a new one:

VS Code
Click the branch name in the bottom-left corner to switch branches or create a new one.

When you click the branch name, VS Code opens a Quick Pick menu listing all your branches. Select "+ Create new branch..." at the top, type a name like feature/my-new-idea, and you're immediately switched to it:

VS Code
The branch Quick Pick lets you create, switch, or check out branches without touching the terminal.
Tip
You are now in a perfect, safe copy of main. If the AI destroys everything, it does not matter. Simply discard this branch and switch back. This workflow enables fearless experimentation.
Warning
Common mistake — committed to main by accident? Don't panic. If you haven't pushed yet, the fix is simple: create the feature branch (your commits come with it), then switch back to main and git reset --hard HEAD~1 to remove the commit from main. Try it yourself below:

Try It: Oops — Committed to Main

The playground starts with a payment commit on main that should be on a feature branch. Create the branch, then reset main with git reset --hard HEAD~1.
Move Commit to Feature Branch

Loading playground...

Vibe it

"Create a new branch called feature/user-auth and switch to it"

"I need to start working on the payment integration — set up a branch for me"

3.2 "My Teammate Pushed Updates" (Syncing)

You're not working in a vacuum. While you've been building your feature, your teammates have been merging theirs. Staying in sync is how you avoid painful surprises later.

Fetch checks for updates, pull downloads them, push shares your work
Note
The Problem: You've been working on your feature branch for a few days. Your teammates have merged their work into main. Your branch is now "stale."

Before diving into the commands, here's how the three main remote operations relate to each other:

Fetch downloads without merging. Pull = fetch + merge. Push uploads your commits.

Option 1: The "Safe" Sync (fetch + merge)

Two-step controlled sync
git fetch origin        # Download new commits (doesn't apply them)
git merge origin/main   # Merge the updates into your branch

Option 2: The "Easy" Sync (pull)

One-step sync
git pull origin main    # Fetch + merge in one command
Tip
As a best practice, git fetch first to see what's coming before merging. git pull is just a "black box" shortcut.

VS Code makes syncing visual. Look at the status bar at the bottom of your window -- you'll see small arrows with numbers showing how many commits are incoming (to pull) and outgoing (to push). Click the sync icon (circular arrows) to pull and push in one step:

VS Code
The incoming/outgoing section shows exactly which commits you need to pull and which you'll push.

You'll also see a prominent "Sync Changes" button right in the Source Control panel. It shows the exact count of incoming and outgoing commits, so you always know what's about to happen:

VS Code
The Sync Changes button combines pull + push in one click. The numbers show incoming (↓) and outgoing (↑) commit counts.

Try It: Fetch and Merge Remote Updates

The playground simulates a remote called origin — no real network calls. After git fetch origin, run git log --oneline --all to see both local and remote branches.
Sync with Remote

Loading playground...

Vibe it

"Pull the latest changes from main and update my branch"

"Fetch from origin and tell me if my branch is behind main"

3.3 "My AI-Generated Feature is Ready" (The Pull Request)

Your feature is built, tested, and committed. But you don't just push it into production — you propose it. A pull request is a conversation: "Here's what I built. Let's review it together."

Pull requests are the quality gate between your branch and production
Note
The Problem: Your feature is complete, tested, and ready to be merged into main. You do not merge it directly. You "propose" the change via a Pull Request (PR).

Once your feature is ready, push your branch to the remote so your teammates can see it:

Push your branch to the remote
git push -u origin feature/my-new-idea
# -u links your local branch to the remote branch

Then on GitHub, you'll see a yellow banner: "feature/my-new-idea had recent pushes. Compare & pull request." Click it to create your PR.

Important
A Pull Request is a request for discussion. It is the formal, auditable gate where your human teammates review your AI-generated code, suggest changes, and ultimately "sign off" before it enters main.

Writing a good PR description can feel tedious, but AI tools can help with that too:

Tip
AI Integration: GitHub Copilot can write your PR descriptions by summarizing your commits. Claude Code can even automate the PR creation process.

You don't even need to leave VS Code to create a PR. Install the GitHub Pull Requests and Issues extension and you can create PRs, review diffs, add comments, approve, and merge -- all without opening your browser:

VS Code
Create Pull Requests directly in VS Code with the GitHub Pull Requests extension. AI can even generate the PR description for you.

Try It: Branch, Commit, and Push

git push in the playground updates a simulated remote — try git remote -v to see it.
Branching Workflow

Loading playground...

Vibe it

"Push this branch and create a pull request with a good description"

"Create a PR from this branch to main, summarizing all the changes we made"

Part 4

The "Undo" Toolkit: Reversing AI Mistakes

"The AI will break things. Your job isn't to prevent that — it's to recover instantly."

No matter how good your AI assistant is, it will occasionally hallucinate, delete the wrong file, or introduce a subtle bug. Git gives you a full spectrum of undo tools — from gentle nudges to nuclear resets. Knowing which tool to reach for in each situation is what separates a confident developer from a panicked one.

Choose the least destructive tool that solves the problem
Important
This is the most critical section. The AI will misunderstand a prompt, generate buggy code, or delete something important. Your value as an engineer is your ability to recover instantly and safely.

4.1 "Discard This Mess" (Local, Not Committed)

The AI just rewrote half your file and it's completely wrong. You haven't committed anything yet. This is the simplest undo — just throw it all away and go back to your last save point.

Discard local edits and return to the last committed state
Note
The Problem: The AI modified files and the result is completely wrong. You haven't staged or committed. You want to revert to your last save point.

The fix is simple -- one command wipes the slate clean and takes you back to your last commit:

Discard changes
git restore .              # Discard ALL local changes
git restore src/bad_file.py  # Discard a single file

In VS Code, you don't need the terminal for this. In the Source Control panel, hover over the file you want to discard under "Changes" and click the curved arrow icon. To discard ALL changes at once, click the curved arrow next to the "Changes" header. You can also right-click any file and choose "Discard Changes".

Caution
This is a "dangerous" command: your local changes are gone forever. But in this case, that's exactly what you want.
Vibe it

"That last change broke everything — throw it all away and go back to my last commit"

"Discard all the changes you just made, they're not working"

4.2 "I Staged This by Accident" (Staged, Not Committed)

You hit git add . a bit too quickly and staged files you didn't mean to include. No worries — unstaging is completely harmless and doesn't touch your code.

Unstage files without losing your edits — a gentle undo
Note
The Problem: You used git add . and accidentally staged a file with a bad AI change. You need to "unstage" it.

No worries -- unstaging is a safe operation that simply moves a file back out of the staging area:

Unstage a file
git restore --staged src/bad_file.py
# Older equivalent: git reset HEAD src/bad_file.py

In VS Code, this is a one-click fix. In the Source Control panel, look under "Staged Changes", hover over the file you want to unstage, and click the (minus) button. The file moves right back to "Changes":

VS Code
Click the − button next to any staged file to unstage it. It moves back to the 'Changes' section.

Try It: Unstage Dangerous Files

You ran git add . too quickly and staged .env with credentials and a debug file. Unstage them with git restore --staged before committing.
Unstage Secrets & Debug Files

Loading playground...

Vibe it

"Unstage config.py, I don't want that in this commit"

"I accidentally staged everything — unstage all files except auth.py"

4.3 "I Forgot a File in My Last Commit"

You just committed — and immediately realized you forgot a file, or there's a typo in the message. Instead of creating a messy "oops" commit, you can quietly fix the last one.

Note
The Problem: You just committed but missed a file, or there's a typo in your commit message. The commit has not been pushed yet.

Instead of creating a whole new commit, you can tack the missing file onto the one you just made:

Amend the last commit
git add src/forgotten_file.py   # Stage the missed file
git commit --amend --no-edit     # Add it to the last commit

# Or just fix the message:
git commit --amend

In VS Code, click the dropdown arrow next to the Commit button and select "Commit (Amend)". This adds your newly staged files to the last commit without needing the terminal. You can also find this under the ... menu → Commit → Commit Staged (Amend).

Warning
This rewrites your last commit. This is 100% safe if and only if you have not pushed that commit to the remote server yet.
Vibe it

"I forgot to include the test file in my last commit — add it without creating a new commit"

"Fix my last commit message, it should say 'fix' not 'feat'"

4.4 "Nuke This Whole Feature" (Locally, Committed)

Sometimes the AI experiment was a dead end — three commits deep, and none of it is salvageable. If you haven't pushed yet, you can erase those commits entirely and start fresh.

Three reset modes from gentle (soft) to nuclear (hard)
Note
The Problem: Your last three commits were a single bad AI experiment. You have not pushed them. You want to permanently delete them.

This is where the nuclear option comes in. A hard reset rolls your branch back as if those commits never happened:

Hard reset: destroy commits and changes
git reset --hard HEAD~3   # Delete last 3 commits + all changes

The "Safer" Resets

--soft: Keep changes staged

Deletes commits but keeps changes in the Staging Area. Useful for "squashing" commits into one.

--mixed (default): Keep changes unstaged

Deletes commits but keeps changes in the Working Directory (unstaged).

--hard: Destroy everything

Deletes commits AND all code changes. Your files reset to the older commit's state.

Caution
CRITICAL: git reset rewrites history. Never use this on a branch your teammates have already pulled. This is for local cleanup only.
Vibe it

"The last 3 commits were all bad — nuke them but keep the code changes so I can redo it"

"Completely undo my last 2 commits, I want to start fresh from before them"

4.5 "I Pushed a Bug to the Team!" (Public, Pushed)

This is the "oh no" moment — you pushed a bad commit and your teammates already pulled it. You can't erase history, but you can create a new commit that perfectly reverses the damage.

Revert creates a new commit that undoes the damage — safe for shared branches
Caution
The Problem: You pushed a bad AI-generated commit. It's on main. Your teammates have already pulled it.

The WRONG Solution: You cannot use git reset. It rewrites history that others have, causing repository divergence.

The RIGHT Solution: Create a new commit that undoes the bad commit. This is a revert.

Here's how to create that revert commit in the terminal:

Safely undo a pushed commit
git log --oneline          # Find the hash: a1b2c3d
git revert a1b2c3d         # Create an inverse commit
git push                   # Push the revert

Notice that you're not erasing anything -- you're adding a new commit on top that reverses the damage:

Important
The bad commit stays in history, but a new "revert" commit undoes its changes. This is safe because no history is deleted. The history clearly shows: "Feature was added" → "Feature was reverted."

VS Code has this built in too. Open the ... menu in the Source Control panel -- this is your gateway to all advanced Git operations. From here you can access Commit, Changes, Pull, Push, Branch, Stash, and more:

VS Code
The ... menu is your Git command center. Look under Commit for Undo Last Commit, Commit (Amend), and other recovery options.

For reverting pushed commits, use the Source Control Graph: right-click any commit and select "Revert Commit" to create the inverse commit safely.

Vibe it

"I pushed a broken commit to main — safely undo it without rewriting history"

"Revert commit a1b2c3d, it introduced a bug in production"

4.6 The "Break Glass" Command

You rewrote local history with a reset or amend — and now Git refuses to push because local and remote have diverged. This is the emergency tool: a force push with a built-in safety net.

Force push with --force-with-lease protects teammates' work
Warning
The Problem: You used git reset or git commit --amend on a branch you already pushed. Local and remote history have diverged. Git refuses to let you push.

You have two flavors of force push, and picking the right one matters a lot:

git push --force

Replaces the server unconditionally. If a teammate pushed in the last 5 minutes, you permanently destroy their work.

git push --force-with-lease

Conditional force push. Only succeeds if the remote branch hasn't changed since your last fetch. Always use this instead.

Caution
What does the error look like? When you try to push after rewriting history, Git will reject it with: ! [rejected] (non-fast-forward) — hint: Updates were rejected because the tip of your current branch is behind This is Git protecting you. Try it yourself below:

Try It: Reset and Force Push

Your feature branch has two bad commits already pushed. Use git reset --hard HEAD~2 to go back, then git push --force to overwrite the remote. Never do this on shared branches!
Reset and Force Push

Loading playground...

Vibe it

"I amended a commit I already pushed and now I can't push — help me fix it safely"

"What's the safest way to force push after rewriting history on my branch?"

4.7 The Git "Undo" Recovery Matrix

The recovery matrix — match your mistake to the right undo tool

Before moving to advanced topics, here's a quick-reference matrix summarizing every undo technique and when to use it:

ScenarioCommandWhat It DoesSafe?VS Code
AI's change is bad, not committedgit restore .Discards all local changes in the working directorySafe (Local)Right-click file → "Discard Changes"
File staged by accidentgit restore --staged <file>Unstages a file, moving it from Staging back to ChangesSafe (Local)Right-click staged file → "Unstage Changes"
Typo in last commit messagegit commit --amendEdits the message of the most recent commitSafe (Local)... → Commit → Commit (Amend)
Forgot a file in last commitgit add <file>
git commit --amend --no-edit
Adds new files to the most recent commitSafe (Local)Stage files → ... → Commit Staged (Amend)
Last 3 local commits are badgit reset --hard HEAD~3Destroys the last 3 commits and all their code changesLocal Only! (Rewrites history)GitLens → Right-click commit → Reset
Pushed a bug to the teamgit revert <hash>Creates a new commit that is the inverse of the bad one100% Safe (Public)GitLens → Right-click commit → "Revert Commit..."
Reset a public branch, need to pushgit push --force-with-leaseForcefully overwrites remote, only if no one else pushedEnterprise "Break Glass"Terminal only

Try It: The Undo Toolkit

The playground includes git revert HEAD and git commit --amend. Try reverting the pushed bad commit, then amending after staging a fix.
Undo Operations

Loading playground...

Part 5

Advanced Scenarios: Managing a Multi-Branch Workflow

"Real projects are messy. Stash your work, resolve your conflicts, and keep moving."

By now you know the fundamentals. But real-world development is rarely linear — you'll be mid-feature when a critical bug drops, your branch will diverge from a teammate's, and two files will clash during a merge. These advanced tools handle the chaos.

Note
As you grow, you'll often work on multiple tasks at once. Your AI-driven workflow will be interrupted by urgent bugs or questions. Git provides the tools to manage this context-switching seamlessly.

5.1 "I Need to Switch Branches, but My Work Isn't Ready"

You're deep in a feature branch with ten modified files when your manager says "urgent bug on main." You can't commit half-finished work, and you can't lose it either. The stash is your escape hatch.

Stash your work-in-progress to switch context without losing anything
Note
The Problem: You're in the middle of a complex AI refactor with 10 modified files. Your manager says: "Urgent bug on main!" You can't commit half-baked work, and Git may block you from switching branches if your uncommitted changes conflict with the target branch.

The stash is a temporary, private holding area for your dirty changes.

Stash, fix, and return
# 1. Stash your changes
git stash push -m "WIP: refactoring pipeline, AI changes"

# 2. Fix the urgent bug
git switch main
git pull
git switch -c "hotfix/urgent-bug"
# ... fix, test, commit, push, create PR ...

# 3. Return to your work
git switch feature/A
git stash pop

git stash pop re-applies your changes and removes them from the stash. Use git stash apply to keep the stash entry for reuse.

In VS Code, you can do all of this without memorizing commands. Open the ... menu in the Source Control panel -- you'll see a Stash submenu with all the options you need:

VS Code
The ... menu includes a Stash submenu with 'Stash (Include Untracked)' and 'Pop Latest Stash' -- everything you need for context-switching.

Choose "Stash (Include Untracked)" to save all your work. When you're ready to come back, go to ... → Stash → "Pop Latest Stash" to restore everything exactly where you left off.

Try It: The Stash Workflow

You're mid-refactor on feature/A when a critical bug comes in. Stash your work, fix the bug on a hotfix branch, then come back and pop the stash.
Stash: Context-Switch Safely

Loading playground...

Vibe it

"I need to switch branches but I'm not done here — save my work temporarily"

"Stash my current changes, switch to main to fix a bug, then come back and restore them"

5.2 "My Branch is Out of Date" (Rebase vs. Merge)

Your feature branch has been alive for a few days and main has moved on without you. Now you need to catch up — and Git offers two philosophies with very different trade-offs.

Merge preserves history, rebase rewrites it — choose based on your team's convention
Note
The Problem: Your feature branch is "stale." main has moved on. There are two philosophies for updating it.

You have two options for catching up with main, and each tells a different story in your commit history.

git merge main

Creates a new "Merge Commit" on your branch. Preserves the exact history -- messy but 100% accurate.

History: "Worked on feature... merged main... worked on feature..."

git rebase main

"Replays" your commits on top of the latest main. Creates a clean, linear history as if you started today.

History: "A, B, E, F, C', D'" -- all in a straight line.

Caution
The Golden Rule of Rebasing: Never rebase a public branch (one your team is also using), as it rewrites history.

VS Code supports both approaches. Use the ... menu in Source Control → "Pull (Rebase)" to rebase instead of merge when pulling. For merging, use the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) → "Git: Merge Branch..." and select the branch to merge.

Tip
The AI-First Developer's Choice: Since your experiment branch is your private playground, rebase is preferred to keep it clean before creating a PR. It avoids cluttering the PR with "I merged main" commits.

Try It: Merge vs. Rebase

Your feature branch and main have diverged. Try git merge main first, then reset and try git rebase main to compare the resulting history.
Merge vs. Rebase

Loading playground...

Vibe it

"My branch is behind main — rebase my changes on top of the latest main"

"Update my feature branch with the latest changes from main using rebase"

5.3 "We Both Edited the Same File" (Merge Conflicts)

This is the moment every developer dreads the first time — and handles calmly by the tenth. Two people changed the same lines, and Git needs a human to decide which version wins.

When two edits collide, Git asks you to choose — this is a merge conflict
Warning
The Problem: You run git pull and Git halts with CONFLICT. You and a teammate edited the same lines. Git needs you, the human, to resolve it.

Don't panic -- conflicts look intimidating at first, but they follow a simple pattern. Git inserts special markers into your file to show you exactly where the disagreement is.

The Conflict Markers

What you'll see in the file
<<<<<<< HEAD
# Your AI's change
x = 10
=======
# Your teammate's change
x = 5
>>>>>>> origin/main

Delete all the markers (<<<, ===, >>>) and edit the code to be the correct final version, then stage and commit. In the playground, you can write the resolved file with echo 'x = 10' > src/model.py.

The VS Code Way (The Superior Way)

Editing conflict markers by hand works, but VS Code makes the whole process much more visual and less error-prone.

Tip
This is one of the best features of the IDE. VS Code opens a 3-way Merge Editor:

Left Pane: "Incoming" (teammate's changes)
Right Pane: "Current" (your changes)
Bottom Pane: "Result" (what will be saved)

Above each conflict block, VS Code shows clickable links: "Accept Current" | "Accept Incoming" | "Accept Both".
VS Code
VS Code highlights conflicts inline with clickable actions: Accept Current Change, Accept Incoming Change, or Accept Both Changes.

For complex conflicts with multiple overlapping changes, click "Resolve in Merge Editor" to open the full 3-way view. This gives you the most control over the final result:

VS Code
The 3-way Merge Editor: Incoming changes (left), your changes (right), and the final result (bottom). Use checkboxes to select which changes to keep.

Try It: Resolving a Merge Conflict

The scenario starts mid-merge with conflict markers in src/model.py. Use echo to overwrite the file, then git add and git commit to finish.
Merge Conflict Resolution

Loading playground...

Vibe it

"I have a merge conflict in model.py — help me resolve it, keeping both changes"

"Show me the conflicts and suggest the best resolution for each one"

Part 6

Your AI-Assisted Cockpit: Mastering Git in VS Code

"The best tools disappear into your workflow. VS Code makes Git visual, intuitive, and fast."

Everything you've learned so far in the terminal works beautifully from VS Code's built-in Git UI. Staging, committing, branching, merging, resolving conflicts — all with rich visual feedback and just a few clicks. Let's explore the cockpit.

VS Code bundles a rich set of Git tools right into the editor, so you can do almost everything without opening a terminal.

Note
While the command line is powerful, the VS Code UI is your "cockpit." It provides rich, visual feedback that makes abstract Git concepts concrete.

6.1 The Source Control View

This single panel replaces a dozen terminal commands. Status, staging, committing, branching — it's all here in one visual interface that makes Git feel approachable.

VS Code's Source Control panel — your visual command center for Git

Everything you've learned maps directly to the UI:

Changes

Your working directory (git status). Modified and untracked files appear here.

Staged Changes

Your staging area. Files you've approved for the next commit.

Commit Box

Your git commit -m "...". Type the message and click the checkmark.

... Menu

All advanced commands: Pull, Push, Stash, Commit (Amend), Branch, Revert, and more.

Here's what it looks like in action. Press Ctrl+Shift+G (or Cmd+Shift+G on Mac) to open the Source Control panel from anywhere:

VS Code
Your command center: the Source Control panel shows everything at a glance -- changed files, staged files, commit input, and the branch graph.

Below the commit area, you'll find the Source Control Graph -- a visual representation of your commit history and branch structure. This is incredibly helpful for understanding how branches relate to each other:

VS Code
The Source Control Graph visualizes your commit history and branch structure -- a powerful way to understand how branches relate.
Vibe it

"Show me how to stage and commit changes using the VS Code Source Control panel"

"Walk me through the VS Code Git workflow without using the terminal"

6.2 The Timeline View & GitLens

When you're staring at a line of code and wondering "who changed this, and why?" — VS Code has the answer built right in. Timeline and GitLens turn your editor into a time machine.

Note
The Problem: An AI changed a line of code, and you have no idea why or when.

Open any file, then look in the Explorer panel for the "Timeline" pane at the bottom. This shows the complete commit history for that specific file. Click any commit to see a diff, or right-click and select "Restore."

Here's the Timeline in action. Each entry represents a commit that touched this file -- click any entry to see exactly what changed in that commit:

VS Code
The Timeline view (in the Explorer panel) shows the complete commit history for any file. Click any entry to see the diff.

VS Code also has built-in Git Blame. Hover over any line of code and you'll see who changed it and when, right in the status bar. For even richer inline annotations on every single line, install the GitLens extension from the VS Code Marketplace -- it's practically essential for professional work:

VS Code
Built-in Git blame shows the author and commit message for the current line right in the status bar.
Vibe it

"Show me the history of changes to this file — who changed what and when"

"Who last modified this function and what was the commit message?"

6.3 The 3-Way Merge Editor

We touched on merge conflicts earlier -- now let's look at the tool that makes resolving them almost enjoyable.

Important
This tool transforms merge conflicts from a terrifying, marker-filled text-editing nightmare into a visual, point-and-click process. This alone is a reason to use VS Code for Git integration.

When a conflict occurs, VS Code highlights the conflicting files. Clicking one opens the 3-way editor with three panes:

Left Pane: "Incoming" Your teammate's changes
Right Pane: "Current" Your local changes
Bottom Pane: "Result" The final merged output

Here's the merge editor in action. Use the checkboxes next to each change to select which version you want to keep -- or manually edit the Result pane at the bottom for a custom resolution:

VS Code
The 3-way Merge Editor transforms scary merge conflicts into a visual, point-and-click experience. Use the checkboxes to select changes.

And if you have GitHub Copilot installed, there's an even easier option. VS Code can use AI to analyze both sides of a conflict and suggest an intelligent resolution. Look for the "Resolve with AI" option in the merge editor:

VS Code
GitHub Copilot can analyze conflicting changes and suggest an intelligent resolution -- the future of merge conflict handling.
Vibe it

"I have a merge conflict — open the VS Code merge editor and help me resolve it"

"Accept the incoming changes for all conflicts in this file"

Part 7

Conclusion: Best Practices for AI-Augmented Teams

"Git isn't just version control — it's the bridge between human intent and AI capability."

You've learned the full toolkit. Now let's put it all together into a cohesive workflow — the daily rhythm that keeps you productive, your code safe, and your AI assistants working within guardrails you control.

7.1 The AI-First Workflow (Summary)

The complete 8-step AI-first Git workflow — your daily rhythm

This is your new "save game" loop — the practical rhythm between you and your agent. Follow these 8 steps for every piece of work. Encode your Git conventions once in the repo (see section 7.3) so agents follow them automatically instead of re-explaining branch rules in every chat.

Here's what each step looks like in practice, along with the commands you'll use.

1

Branch

Create an isolated branch — or practice every step in the (Try real Git commands in your browser from each lesson). git switch -c ai-experiment/new-feature

2

Generate

Work with your AI agent to implement the change. With AGENTS.md and skills configured, it already knows your branch naming, commit format, and safety rules.

3

Review

Use git add -p or VS Code "Stage Selected Ranges" to review every line.

4

Save

git commit -m "feat: <message>" -- Commit small, commit often.

5

Sync

git fetch origin followed by git rebase origin/main.

6

Push

git push --force-with-lease if you rebased. Updates remote safely.

7

Propose

Create a Pull Request for human review.

8

Recover

If you push a mistake, never reset a public branch. Always use git revert.

Vibe it

"Walk me through the full Git workflow for starting a new feature from scratch"

"I just finished coding — what Git steps should I follow before creating a PR?"

7.2 Quick Reference Card

Keep this cheat sheet handy — terminal commands and their VS Code equivalents

Keep this handy. It covers the most common Git tasks with both the terminal command and the VS Code equivalent, so you can use whichever feels more natural.

TaskCommandVS Code
Check what changedgit statusSource Control panel
Stage specific linesgit add -pStage Selected Ranges
Commit changesgit commit -m "feat: ..."Type message + checkmark
Create new branchgit switch -c feature/nameClick branch name (bottom-left)
Discard local changesgit restore .Discard Changes
Undo last commit (keep)git reset --soft HEAD~1GitLens: Reset
Revert public commitgit revert <hash>Revert Commit
Stash work in progressgit stash push -m "message"... menu: Stash
Update branchgit fetch && git rebase origin/main... menu: Pull, Rebase
Safe force pushgit push --force-with-leaseTerminal only
Practice all commandsTry it yourself tabs in Parts 2–5

7.3 Teaching Your AI to Use Git

Encode your conventions once and let AI agents follow them automatically

The next level is not just using Git to manage AI — it's encoding your Git workflow so agents follow it automatically. Modern tools share a simple pattern: always-on project instructions for conventions that apply everywhere, plus skills for detailed procedures that load only when relevant.

Always-on instructions: AGENTS.md & friends

AGENTS.md is the cross-tool standard for project-wide rules — recognized by GitHub Copilot, Claude Code, Codex, and other agents. In monorepos, the nearest file to the code you're editing takes precedence. Claude Code also reads CLAUDE.md for the same role. In VS Code, add .github/copilot-instructions.md for Copilot-specific standards. Put your team's Git constitution here: branch naming, Conventional Commits, "never reset shared branches," PR expectations. Keep it concise — this loads on every session.

Agent Skills (SKILL.md)

Skills are the open Agent Skills format: a folder with a SKILL.md file (name + description in YAML frontmatter, instructions in the body). Store them in .agents/skills/ for portable, version-controlled workflows your whole team shares. Agents discover skills at startup and load the full instructions only when a task matches — perfect for detailed Git procedures without bloating every chat. Example: a git-save-game/ skill that walks through the 8-step loop before every PR.

VS Code: scoped rules & custom agents

For rules that apply only to certain files, add *.instructions.md files under .github/instructions/ with an applyTo glob in the frontmatter. For specialized personas, define custom agents as .github/agents/*.agent.md — YAML frontmatter sets the name, description, tools, and model; the body holds focused instructions (e.g., a "Git Review" agent that inspects staged diffs and suggests commit splits). Use /create-instruction or /create-agent in VS Code chat to scaffold these files.

CI & repository automations

Repo instructions also power GitHub Copilot code review and cloud agents on pull requests. Combine with GitHub Actions to auto-review PRs, flag risky Git operations, or update docs when code changes — Git remains the audit trail even when agents operate in CI.

Vibe it

"Draft an AGENTS.md with our Git branch naming and Conventional Commits rules"

"Create a git-save-game SKILL.md that walks through our 8-step workflow before every PR"

"Set up a VS Code custom agent (.agent.md) that reviews staged changes before commit"

Important
Final Thoughts: Your AI assistants are powerful tools that lack context and accountability. Git is your system of accountability. It provides the immutable history, the instant "undo" button, and the human-in-the-loop review layer that transforms high-velocity AI coding from a risky experiment into a professional, safe, and scalable engineering discipline. Master it, and you'll transform AI-assisted coding into a superpower.

Built for the vibe coding generation.