-
Notifications
You must be signed in to change notification settings - Fork 5
appendix aa advanced git
Episode coming soon: Advanced Git Operations - a conversational audio overview of this appendix. Listen before reading to preview the concepts, or after to reinforce what you learned.
Who this is for: You have completed Chapter 11 (Git & Source Control) and feel comfortable with the basics — cloning, branching, committing, pushing, and pulling. This appendix covers the next tier of Git skills that come up constantly in real open source contribution: cherry-picking fixes across branches, cleaning up messy commit history before a PR, safely undoing mistakes, and understanding why your push sometimes gets blocked.
Every section shows three paths: VS Code, GitHub CLI (
gh), and Git CLI. Use whichever fits your workflow — they all produce the same result.
- Cherry-Pick — Grabbing a Specific Commit
- Interactive Rebase — Cleaning Up Your History
- git reset — Undoing at Different Depths
- git revert — The Safe Undo for Shared Branches
- Tags — Marking Important Moments
- Detached HEAD — What It Is and How to Get Out
- Force Pushing Safely
- git bisect — Finding the Commit That Broke Things
- git clean — Clearing Out Untracked Files
- Branch Protection — Why Your Push or Merge May Be Blocked
- Using GitHub Copilot for Git Operations
What it is: Cherry-pick lets you take a single commit from any branch and apply it to your current branch. Think of it like copy-pasting a specific change — without bringing the entire branch along with it.
When you'd use it:
- You fixed a bug on a feature branch, but
mainalso needs that fix right now - A teammate landed a commit on their branch and you need just that one change
- You accidentally committed to the wrong branch and need to move that commit somewhere else
Before cherry-picking, you need the commit's SHA (the unique ID for that commit).
- Open the Timeline panel: Click View → Open View → Timeline (or press
Ctrl+Shift+Pand type "Timeline") - Switch to the branch that has the commit you want, browse the Timeline, and copy the commit SHA shown in the details panel
# See commits on another branch without switching to it
git log feature/bug-fix --oneline
# Output:
# a1b2c3d Fix null pointer error in auth module
# e4f5g6h Add unit tests for loginThe short SHA is the first 7 characters (a1b2c3d).
- Press
Ctrl+Shift+P(orCmd+Shift+Pon macOS) - Type "cherry" and select "Git: Cherry Pick..."
- Paste or type the commit SHA
- Press
Enter— VS Code applies the commit to your current branch
The GitHub CLI doesn't have a direct cherry-pick command (it's a local Git operation), but you can use it to find the SHA first:
# List commits on a branch via gh to find the one you want
gh api repos/{owner}/{repo}/commits?sha=feature/bug-fix --jq '.[].sha, .[].commit.message' | head -20
# Then cherry-pick using git
git cherry-pick a1b2c3d# Apply a single commit
git cherry-pick a1b2c3d
# Apply a range of commits (from older to newer, exclusive of first)
git cherry-pick a1b2c3d..e4f5g6h
# Apply without automatically committing (lets you review changes first)
git cherry-pick --no-commit a1b2c3dCherry-pick can hit conflicts just like a merge. When it does:
- Git pauses and marks the conflicting files (same
<<<<<<< HEADmarkers as merge conflicts) - Resolve the conflicts in VS Code's conflict editor (see Chapter 7: Merge Conflicts)
- Stage the resolved files
- Then either:
# Continue the cherry-pick after resolving
git cherry-pick --continue
# Or cancel it entirely and go back to where you started
git cherry-pick --abortScreen reader tip: When a cherry-pick stops due to a conflict, run
git statusin the terminal — it announces exactly which files need attention. The conflict markers are plain text and read naturally line by line.
GitHub Copilot can help: Before cherry-picking a commit you're not sure about, open Copilot Chat (
Ctrl+Shift+I) and ask: "What does commit a1b2c3d do? Should I cherry-pick it onto my branch?" Paste thegit show a1b2c3doutput into the chat for context. After cherry-picking, if a conflict opens, Copilot can suggest a resolution — see Section 11 for prompts.
What it is: Interactive rebase (git rebase -i) is like a time machine for your commits. Before you open a PR, you can reorder commits, combine several small commits into one clean commit, rewrite commit messages, or remove commits that were just experiments.
When you'd use it:
- You made 8 "WIP" commits while working and want to combine them into 1 clean commit for your PR
- You want to reword a commit message to better describe what changed
- You accidentally committed a debug file and want to remove that commit entirely
Golden rule: Only rebase commits that have not been pushed to a shared branch yet. Rewriting public history creates problems for everyone who has pulled that branch. If you've already pushed, see Force Pushing Safely.
VS Code has basic rebase support via the Command Palette, but for full interactive rebase you'll want the terminal:
- Open the Integrated Terminal:
Ctrl+Backtick - Run the command below to rebase the last N commits (replace N with how many commits you want to edit)
git rebase -i HEAD~3
# This opens your last 3 commits for editing- Your default editor opens with a list of your commits. If it opens in
vim, typeito enter insert mode, make your edits, then pressEscfollowed by:wqto save. If you'd prefer VS Code as the editor:
git config --global core.editor "code --wait"After that, git rebase -i will open the commit list in VS Code itself — much more screen-reader-friendly.
# Rebase the last 3 commits
git rebase -i HEAD~3
# Or rebase everything since you branched from main
git rebase -i mainWhen the editor opens, you see something like this:
pick a1b2c3d Add accessibility section to README
pick e4f5g6h Fix typo in intro
pick f7g8h9i Fix another typo in intro
Each line starts with a command word. Change the word to change what happens to that commit:
| Command | What it does |
|---|---|
pick |
Keep the commit as-is (default) |
squash (or s) |
Combine this commit into the one above it |
fixup (or f) |
Same as squash but discard this commit's message |
reword (or r) |
Keep the commit but edit the message |
drop (or d) |
Delete this commit entirely |
edit (or e) |
Pause here so you can amend the commit |
Change the file to:
pick a1b2c3d Add accessibility section to README
squash e4f5g6h Fix typo in intro
squash f7g8h9i Fix another typo in intro
Save and close. Git opens a second editor for you to write the combined commit message. Write a clean summary and save — done. You now have one tidy commit instead of three.
reword a1b2c3d Add accessibility section to README
pick e4f5g6h Fix typo in intro
Save and close. Git opens the commit message for a1b2c3d for you to edit. Write the new message, save — done.
# Abort the rebase and go back to where you started
git rebase --abort
# If you're mid-rebase and hit a conflict, resolve it then continue
git rebase --continueScreen reader tip: Run
git rebase -iwith VS Code as your editor (git config --global core.editor "code --wait") — the commit list opens in a VS Code tab that your screen reader can navigate normally with arrow keys.
GitHub Copilot can help: Not sure how to word a squashed commit message? After combining your commits, open Copilot Chat and say: "I just squashed these commits into one: [paste your old messages]. Write a clear, concise commit message that describes all the changes." Copilot is also great at explaining what an interactive rebase file is asking you to do — paste the whole thing and ask: "What will happen when I save this rebase file?"
What it is: git reset moves the tip of your current branch backward to a previous commit. The three modes (--soft, --mixed, --hard) control what happens to the changes that were in those commits.
When you'd use it:
- You committed too early and want to add more changes to that commit
- You staged the wrong files and want to unstage them
- You want to completely throw away the last few commits and start fresh
Think of Git as having three layers: your working files (what you can see in the editor), the staging area (what git add puts there), and the commit history.
| Mode | What gets reset | Your working files | Your staged changes |
|---|---|---|---|
--soft |
Commit history only | Kept | Kept (still staged) |
--mixed (default) |
History + staging | Kept | Unstaged (back to working files) |
--hard |
Everything | Discarded | Discarded |
--hardis the dangerous one. It permanently discards your uncommitted changes. If you're not sure, use--softor--mixed— they never lose work. And if you do accidentally use--hard, checkgit reflogimmediately (see Chapter 11, Section 10b).
- Open Source Control:
Ctrl+Shift+G - Click the "..." (More Actions) menu at the top of the panel
- Select "Commit → Undo Last Commit"
This is equivalent to git reset --soft HEAD~1 — your changes come back as staged files, nothing is lost.
Ctrl+Shift+P → type "git undo" → select "Git: Undo Last Commit"
# Undo last commit — keep changes staged (safest)
git reset --soft HEAD~1
# Undo last commit — keep changes but unstage them
git reset --mixed HEAD~1
# Undo last 3 commits — keep all changes unstaged
git reset --mixed HEAD~3
# Undo last commit — DISCARD all changes (cannot be undone without reflog)
git reset --hard HEAD~1
# Reset to a specific commit SHA
git reset --soft a1b2c3dIf you just want to remove a file from the staging area without touching commit history:
In the Source Control panel, click the minus (–) icon next to a staged file, or right-click it and select "Unstage Changes".
# Unstage a specific file
git restore --staged docs/README.md
# Unstage everything
git restore --staged .What it is: git revert creates a new commit that undoes the changes from a previous commit. Unlike git reset, it does not rewrite history — it adds to it. This makes it the right choice when you need to undo something on a shared branch (like main) where other people may already have the history you'd be rewriting.
When you'd use it:
- A commit made it to
mainand it broke something — you need to roll it back without force-pushing - You want to undo a change but keep a record that the undo happened
- You're working on a protected branch where force-push is disabled
- Open the Timeline panel and navigate to the commit you want to undo
- Right-click the commit and select "Revert Commit"
- VS Code creates a new commit with message
Revert "your original message"— review it and push
# Revert a specific commit (opens editor to confirm the message)
git revert a1b2c3d
# Revert without opening the editor (uses default message)
git revert --no-edit a1b2c3d
# Stage the revert but don't commit yet (lets you edit the message manually)
git revert --no-commit a1b2c3d
git commit -m "Revert: remove broken auth change, will revisit in #42"
# Revert a merge commit (you must specify which parent to revert to)
git revert -m 1 a1b2c3d| Situation | Use |
|---|---|
| Commit is only local (not pushed) |
git reset — cleaner, no extra commit |
Commit is on a shared branch (main, dev) |
git revert — preserves history, safe for others |
| Branch has protection rules (no force push) |
git revert — the only option |
| You want a clear audit trail of the undo |
git revert — the revert commit appears in history |
GitHub Copilot can help: Not sure whether to use
resetorrevert? Describe your situation to Copilot Chat: "I pushed a commit to main that broke the login page. Should I use git reset or git revert to undo it?" Copilot will explain the tradeoffs and give you the exact command to run.
What it is: A tag is a permanent label you attach to a specific commit — usually to mark a release version like v1.0.0. Unlike a branch (which moves as you commit), a tag always points to the exact same commit forever.
When you'd use it:
- Releasing a new version of a project
- Marking a stable checkpoint before starting a big refactor
- Documenting when a major feature shipped
GitHub's Releases feature builds on tags. When you create a release on GitHub, you're creating a tag plus release notes and attached files. See Appendix H: Releases, Tags, and Insights for the GitHub web interface side of this.
| Type | What it is |
|---|---|
| Lightweight | Just a pointer to a commit — like a bookmark |
| Annotated | Includes a message, author, and date — recommended for releases |
Ctrl+Shift+P → type "git tag" → select "Git: Create Tag"
Type the tag name (e.g., v1.2.0) and optionally a message. VS Code creates an annotated tag.
# Create a tag and push it to GitHub in one step (using the API)
gh release create v1.2.0 --title "Version 1.2.0" --notes "Bug fixes and accessibility improvements"
# This creates both a GitHub Release and the underlying tag# Create a lightweight tag at the current commit
git tag v1.2.0
# Create an annotated tag (recommended for releases)
git tag -a v1.2.0 -m "Release version 1.2.0 - bug fixes and accessibility improvements"
# Tag a specific past commit
git tag -a v1.1.5 a1b2c3d -m "Retroactive tag for 1.1.5"
# List all tags
git tag
# List tags matching a pattern
git tag -l "v1.*"
# Show details of an annotated tag
git show v1.2.0Tags are not pushed automatically when you run git push. You need to push them explicitly:
# Push a specific tag
git push origin v1.2.0
# Push all local tags at once
git push origin --tags# Delete a local tag
git tag -d v1.2.0
# Delete the tag on GitHub (remote)
git push origin --delete v1.2.0What it is: Normally, you're working on a branch — Git tracks your commits and moves the branch forward as you commit. A "detached HEAD" happens when you check out a specific commit SHA (or a tag) directly instead of a branch. You're no longer on any branch — you're floating at a specific point in history.
How you get into it:
git checkout a1b2c3d # Check out a specific commit
git checkout v1.0.0 # Check out a tagGit warns you when this happens:
Note: switching to 'a1b2c3d'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, but any commits you make in this state will not be
associated with any branch...
Why it matters: Any commits you make in detached HEAD state are not attached to a branch. When you switch away, those commits become hard to find (and Git may eventually garbage-collect them).
git checkout main
# or whatever branch you were on
git switch main# Create a new branch at the current (detached) position to save your work
git checkout -b my-experiment
# Now you're on a real branch and those commits are safeVS Code shows the current branch name in the bottom-left status bar. If you're in detached HEAD, it shows something like (HEAD detached at a1b2c3d) instead of a branch name.
To return to a branch: Click that status bar area, or use Ctrl+Shift+P → "Git: Checkout to..." and pick a branch from the list.
Screen reader tip: In VS Code, the branch indicator is in the status bar at the bottom of the window. NVDA/JAWS users: press
Insert+Endto read the status bar, or navigate there withTab. VoiceOver users:VO+End. If it says "detached", check out a branch before committing anything new.
What it is: After you rebase or amend commits that have already been pushed, the remote branch has a different history than your local branch. A regular git push will fail because Git sees them as diverged. A force push overwrites the remote with your local version.
Force pushing to
mainor a shared branch is almost always the wrong move. It rewrites history that other people may have pulled, causing them significant pain. Force pushing is appropriate mainly on your own feature branches — and even then, use the safer variant.
| Option | What it does |
|---|---|
--force |
Overwrites the remote unconditionally — even if someone else pushed since you last pulled |
--force-with-lease |
Overwrites the remote only if no one else has pushed since your last fetch — safer |
Always use --force-with-lease instead of --force.
- You rebased a feature branch to squash commits before a PR review
- You amended the last commit with
git commit --amendafter already pushing - A reviewer asked you to rebase onto
mainand you've now done so
VS Code doesn't have a "force push" button in the UI — this is intentional to prevent accidents. Use the integrated terminal:
Ctrl+Backtick → then type the command below
# Force push your current branch
gh repo sync # This is for syncing FROM remote, not for force pushing
# For force pushing, use git directly:
git push --force-with-lease origin your-branch-name# Safe force push — fails if someone else pushed since your last fetch
git push --force-with-lease origin feature/my-branch
# Check what will happen before pushing
git push --force-with-lease --dry-run origin feature/my-branch
# Unconditional force push (avoid unless you know exactly what you're doing)
git push --force origin feature/my-branch# 1. You're on your feature branch — rebase onto main to get latest changes
git fetch origin
git rebase origin/main
# 2. Resolve any conflicts, then continue
git rebase --continue
# 3. Force push your rebased branch (origin already has the old version)
git push --force-with-lease origin feature/my-branchWhat it is: git bisect performs a binary search through your commit history to find exactly which commit introduced a bug. Instead of checking 100 commits one by one, Git cuts the search in half each time — usually finding the culprit in 7-10 steps.
When you'd use it:
- "This was working last week, now it's broken — what changed?"
- You need to find the exact commit so you can revert or fix it
- A test that used to pass now fails and you don't know why
# 1. Start bisect mode
git bisect start
# 2. Mark the current commit as bad (broken)
git bisect bad
# 3. Mark a commit you know was good (working)
# Use a tag, SHA, or branch name from before the problem started
git bisect good v1.0.0
# or
git bisect good a1b2c3dGit now checks out a commit in the middle of your history. Test your code — does the bug exist here?
# If the bug IS present at this commit
git bisect bad
# If the bug is NOT present at this commit
git bisect goodGit cuts the range in half again and checks out another commit. Repeat until Git prints:
a1b2c3d is the first bad commit
# End the bisect session and return to your original branch
git bisect resetIf you have a test command that exits with code 0 on success and non-zero on failure, Git can run bisect automatically:
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
# Run automatically — git runs your test script at each step
git bisect run npm test
# or
git bisect run python -m pytest tests/test_auth.pyScreen reader tip: Bisect output is plain text — each step tells you exactly where it checked out and how many steps remain. The terminal reads it cleanly line by line.
What it is: git clean removes untracked files and directories from your working directory — files that Git doesn't know about yet (not staged, not committed, not in .gitignore). This is useful when you have build artifacts, generated files, or experimental files cluttering your project.
git clean cannot be undone. The files it removes are permanently deleted — they're not moved to the trash or recoverable from
git reflog. Always run with--dry-runfirst.
When you'd use it:
- After a build that left temporary files everywhere
- You want a completely fresh state matching the last commit
- Clearing out generated files before running a clean build
# See what WOULD be deleted without actually deleting anything
git clean -n
# or equivalently
git clean --dry-runVS Code's Source Control panel shows untracked files in the "Changes" section. To remove them:
- Open Source Control:
Ctrl+Shift+G - Right-click an untracked file
- Select "Discard Changes" — this removes new untracked files
For bulk removal, use the terminal (see Git CLI below).
# Dry run — see what would be removed
git clean -n
# Remove untracked files (NOT directories)
git clean -f
# Remove untracked files AND directories
git clean -fd
# Remove untracked files AND ignored files (be careful — removes build artifacts AND things in .gitignore)
git clean -fx
# Interactive mode — confirm each file before deleting
git clean -i| Flag | Meaning |
|---|---|
-n |
Dry run — show what would be removed |
-f |
Force — required to actually delete (safety measure) |
-d |
Also remove untracked directories |
-x |
Also remove files listed in .gitignore
|
-i |
Interactive — confirm each deletion |
What it is: Branch protection rules are settings a repository administrator applies to specific branches (usually main or release branches). They prevent direct pushes, require pull requests, require approvals before merging, and enforce status checks passing.
You don't configure these as a contributor — but you will encounter them, and understanding them helps you avoid frustration when your push or merge gets blocked.
| What happened | Why it happened | What to do |
|---|---|---|
git push origin main fails with "remote: error: GH006" |
Direct push to main is blocked |
Create a branch and open a PR instead |
| Your PR has a "Merge" button but it's grayed out | Required approvals not met, or status checks failing | Request a review; wait for CI to pass |
| PR says "Required review from code owners" | A CODEOWNERS file routes reviews to specific people |
Wait for or ping the code owner |
| CI check is failing | An automated test or lint step failed | Fix the failing check and push again |
| PR says "Branch is out of date" |
main moved forward after your PR opened |
Update your branch (merge or rebase from main) |
# 1. Never push directly to main — always work on a branch
git checkout -b feature/my-change
# 2. Make your changes, commit them
git add .
git commit -m "Add screen reader support to navigation"
# 3. Push your branch (not main)
git push origin feature/my-change
# 4. Open a PR on GitHub — protection rules apply to the merge, not the push
gh pr create --title "Add screen reader support to navigation" --body "Closes #42"
# 5. Wait for reviews and CI checks to pass, then merge through the PRWhen GitHub says your branch is out of date with main:
- Open Source Control →
Ctrl+Shift+P - Type "merge" → select "Git: Merge Branch..."
- Choose
origin/mainfrom the list - Resolve any conflicts, then push again
# Option A: Merge main into your branch (creates a merge commit)
git fetch origin
git merge origin/main
# Option B: Rebase onto main (cleaner history, requires force push after)
git fetch origin
git rebase origin/main
git push --force-with-lease origin feature/my-change# Update your PR branch from the GitHub UI via CLI
gh pr update-branch --rebase
# or
gh pr update-branch # uses merge by default# View branch protection rules for main
gh api repos/{owner}/{repo}/branches/main/protection --jq '{
required_reviews: .required_pull_request_reviews.required_approving_review_count,
require_status_checks: .required_status_checks.contexts,
enforce_admins: .enforce_admins.enabled
}'Navigate to Settings → Branches in the repository. (You need admin access to see the full config; contributors can see the effect through blocked PRs and the merge box status.)
For a deep dive on branch protection rules, rulesets, and diagnosing why your PR can't merge: See Appendix K: Branch Protection and Rulesets — it includes a full diagnosis guide, screen reader navigation of the merge box, and what each status check means.
| Task | VS Code | Git CLI | GitHub CLI |
|---|---|---|---|
| Cherry-pick a commit |
Ctrl+Shift+P → "Cherry Pick" |
git cherry-pick <sha> |
Find SHA via gh, then git cherry-pick
|
| Squash commits | Terminal: git rebase -i HEAD~N
|
git rebase -i HEAD~N |
— |
| Undo last commit (keep changes) | Source Control → "..." → "Undo Last Commit" | git reset --soft HEAD~1 |
— |
| Safely undo a pushed commit | Timeline → right-click → "Revert Commit" | git revert <sha> |
— |
| Create a release tag |
Ctrl+Shift+P → "Create Tag" |
git tag -a v1.0.0 -m "..." |
gh release create v1.0.0 |
| Push tags to GitHub | — | git push origin --tags |
(included in gh release create) |
| Exit detached HEAD | Status bar → pick a branch | git switch main |
— |
| Force push safely | Terminal (no UI button) | git push --force-with-lease origin <branch> |
— |
| Find bug-introducing commit | Terminal: git bisect start
|
git bisect start/good/bad |
— |
| Remove untracked files | Source Control → Discard |
git clean -fd (dry run: -n) |
— |
| Update PR branch | Source Control → Merge Branch | git fetch && git rebase origin/main |
gh pr update-branch |
GitHub Copilot isn't just for writing code — it's genuinely useful for Git operations, especially when you're doing something unfamiliar, hit a conflict, or need to understand what a command did. Here's how to use it across the advanced operations in this appendix.
Opening Copilot Chat in VS Code: Press
Ctrl+Shift+I(Windows/Linux) orCmd+Option+I(macOS), or click the Copilot Chat icon in the sidebar. Screen reader users: the chat input is a text field — type your prompt and pressEnter.
When a cherry-pick, rebase, or branch merge stops due to a conflict, VS Code highlights the conflict regions. Place your cursor inside a conflict block and ask Copilot:
- "Resolve this merge conflict. Keep meaningful changes from both sides."
- "Explain what each side of this conflict is trying to do."
- "Which version of this change should I keep, and why?"
Copilot reads the conflict markers and suggests a resolution. You review it, accept or adjust, then stage the file and continue.
Tip: If you have multiple conflict files, handle them one at a time — paste the conflicting block into Copilot Chat with context about what the file does. You'll get much better suggestions than if you just say "fix this."
Copilot is excellent at turning "WIP: stuff" into a clear, conventional commit message.
Open Copilot Chat after staging your changes and try:
- "Write a conventional commit message for these changes." (Copilot can see open files)
- "I changed the navigation component to add keyboard focus indicators. Write a commit message."
- "Here are my last 5 WIP commit messages: [paste them]. Write one clean message that summarizes all of them."
Conventional commit format (feat:, fix:, docs:, refactor:) is especially useful on open source projects — ask Copilot to use it.
Git's error messages and status output can be cryptic. Paste them directly into Copilot Chat:
# Paste this kind of thing into Copilot and ask "what does this mean?"
error: Your local changes to the following files would be overwritten by merge:
src/auth/login.js
Please commit your changes or stash them before you merge.
- "I got this git error message: [paste it]. What does it mean and how do I fix it?"
- "My git status output looks like this: [paste it]. What happened and what should I do next?"
- "I accidentally ran git reset --hard. What are my options for recovering my changes?"
When you're not sure which git command to reach for, describe what you want to do:
- "I committed a fix on my feature branch but main also needs it urgently. What's the right git command to use?" → Copilot will suggest cherry-pick
- "I have 6 messy commits on my PR branch before I open the PR. How do I clean them up?" → Interactive rebase with squash
- "I pushed a commit that broke CI and I need to undo it without force-pushing." → git revert
- "My PR branch hasn't been updated from main in two weeks. How do I bring it up to date?" → fetch + rebase or merge
When git bisect lands on a commit and you're not sure what to test:
- "I'm running git bisect to find a bug. Git just checked out commit a1b2c3d. Here's the diff: [paste
git show a1b2c3d]. What changed in this commit and what should I test?"
Paste the full error message from a rejected push into Copilot:
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Required status check "CI / build" is failing.
- "I got this error when pushing to my repository: [paste error]. What does it mean and what do I do?"
- "My PR can't merge because of a required status check. Here's the check output: [paste it]. What's wrong?"
| Use case | Best tool |
|---|---|
| Explaining a git error or status message | Copilot Chat (paste the output) |
| Writing a commit message | Copilot Chat |
| Resolving a merge conflict | Copilot Chat (with cursor in conflict block) |
| Generating the right git command | Copilot Chat or GitHub Copilot CLI (gh copilot suggest) |
| Autocompleting a long command you've started | Copilot inline (in terminal with shell integration) |
If you have the GitHub CLI with Copilot extension installed, you can ask for git commands directly in the terminal:
# Ask Copilot to suggest a git command for what you want to do
gh copilot suggest "squash my last 4 commits into one"
gh copilot suggest "undo my last commit but keep the changes"
gh copilot suggest "find which commit broke the login tests"Copilot CLI explains the command before running it and asks for confirmation — great for learning while doing.
See also: Chapter 13: GitHub Copilot for the full guide to Copilot Chat, inline suggestions, and effective prompting. Appendix W: Copilot Reference for the complete command and participant reference.
Related appendices: Appendix D: Git Authentication · Appendix H: Releases, Tags, and Insights · Appendix K: Branch Protection and Rulesets · Chapter 11: Git & Source Control
- 00 · Pre-Workshop Setup
- 01 · GitHub Web Structure
- 02 · Navigating Repositories
- 03 · The Learning Room
- 04 · Working with Issues
- 05 · Pull Requests
- 06 · Merge Conflicts
- 07 · Culture and Etiquette
- 08 · Labels, Milestones, Projects
- 09 · Notifications
- 10 · VS Code Accessibility
- 11 · Git & Source Control
- 12 · GitHub PRs Extension
- 13 · GitHub Copilot
- 14 · Accessible Code Review
- 15 · Issue Templates
- 16 · Accessibility Agents
- D · Git Authentication
- AA · Advanced Git Operations
- AB · GitHub Desktop
- AC · GitHub CLI
- AD · Git Security
- C · Accessibility Standards
- E · Markdown (GFM)
- F · GitHub Gists
- G · GitHub Discussions
- H · Releases, Tags & Insights
- I · GitHub Projects
- J · Advanced Search
- K · Branch Protection
- L · Security Features
- M · VS Code Accessibility Ref
- N · GitHub Codespaces
- V · Accessibility Agents Ref
- W · Copilot Reference
- X · Copilot AI Models