Skip to content

Git with PowerShell

Note

A practical guide to running Git commands in PowerShell — from daily workflows like branching and pushing to recovering from mistakes with resets and reverts.

Overview

Git is the most widely used version control system. You can run all Git commands directly in PowerShell with no special modules required. This guide covers the commands you'll reach for most often — organized by task so you can find what you need fast.

Basic Syntax

# Most git commands follow this structure:
git <command> [options] [arguments]

# Check your git version
git --version

# Get help on any command
git <command> --help

Key Points

  • Git commands run natively in PowerShell — no extra modules needed
  • Commands behave the same in PowerShell, CMD, or Bash
  • Use git <command> --help for built-in docs on any command

Common Use Cases

Status & Log

What it does: Check what's changed in your working directory and review commit history.

# See modified, staged, and untracked files
git status

# Compact version
git status -s

# View commit history
git log

# Compact one-line log
git log --oneline

# Visual branch graph
git log --oneline --graph --all

# See unstaged changes
git diff

# See staged changes only
git diff --staged

Commits

What it does: Stage changes and save snapshots of your work.

# Stage a specific file
git add FileName.ps1

# Stage everything in the current directory
git add .

# Stage changes interactively (choose which parts to include)
git add -p FileName.ps1

# Commit with a message
git commit -m "Your commit message here"

# Stage all tracked files and commit in one step
git commit -am "Your commit message here"

# Amend the last commit (fix message or add a forgotten file)
git add ForgottenFile.ps1
git commit --amend -m "Updated commit message"

Amend with Caution

git commit --amend rewrites history. Only use it on commits that have not been pushed to a shared remote.

Branches & Switching

What it does: Create isolated lines of development and move between them.

# List local branches (* = current)
git branch

# List all branches including remote
git branch -a

# Create a new branch
git branch feature/my-new-feature

# Switch to a branch
git switch feature/my-new-feature

# Create AND switch in one step
git switch -c feature/my-new-feature

# Rename the current branch
git branch -m new-name

# Delete a branch (must be merged first)
git branch -d feature/old-feature

# Force delete (even if not merged)
git branch -D feature/old-feature

switch vs checkout

git switch is the modern replacement for git checkout when changing branches. It's clearer and less error-prone. Use git restore if you need to discard file changes instead.

Remotes

What it does: Manage connections to remote repositories like GitHub or GitLab.

# List remotes and their URLs
git remote -v

# Add a remote
git remote add origin https://github.com/YourUsername/YourRepo.git

# Remove a remote
git remote remove origin

# Rename a remote
git remote rename origin upstream

# Download changes from remote without merging
git fetch origin

# Fetch and clean up deleted remote branches
git fetch --prune

Push & Pull

What it does: Upload local commits to a remote, or download remote commits locally.

# Push to the tracked remote branch
git push

# Push and set tracking for a new branch
git push -u origin feature/my-new-feature

# Pull (fetch + merge) from tracked remote
git pull

# Pull from a specific branch
git pull origin main

# Pull using rebase for cleaner history
git pull --rebase

Force Push

Avoid git push --force — it overwrites remote history. Use git push --force-with-lease instead. It does the same thing but fails safely if someone else has pushed changes you haven't seen.

Merging & Conflicts

What it does: Combine changes from one branch into another and sort out any conflicts.

# Merge a branch into your current branch
git merge feature/my-new-feature

# Merge and keep the merge commit (no fast-forward)
git merge --no-ff feature/my-new-feature

# Abort a merge gone wrong
git merge --abort

# After resolving conflicts manually, stage the fixed files
git add ConflictedFile.ps1

# Then complete the merge
git commit

Resolving a Merge Conflict

Scenario: You merged feature/login into main and auth.ps1 has a conflict.

git merge feature/login
# CONFLICT (content): Merge conflict in auth.ps1

# Open auth.ps1 — you'll see conflict markers:
# <<<<<<< HEAD
#     (your code on main)
# =======
#     (incoming code from feature/login)
# >>>>>>> feature/login

# Edit the file, decide what to keep, remove the markers
# Then:
git add auth.ps1
git commit

Stashes

What it does: Temporarily shelve uncommitted changes so you can switch context without committing half-done work.

# Stash your changes
git stash

# Stash with a descriptive message
git stash push -m "WIP: login feature"

# List all stashes
git stash list

# Apply the most recent stash (keeps it in the list)
git stash apply

# Apply a specific stash
git stash apply stash@{2}

# Apply and remove the most recent stash
git stash pop

# Drop a stash without applying
git stash drop stash@{1}

# Clear all stashes
git stash clear

# Include untracked files in the stash
git stash push -u -m "Including new files"

Stashes Are Short-Term

If you're holding onto a stash for more than a day or two, commit to a feature branch instead. Stashes are easy to lose track of.

Undoing Changes

What it does: Discard or reverse changes at different stages — working directory, staging area, or already committed.

# Discard changes to a file (not yet staged)
git restore FileName.ps1

# Discard ALL unstaged changes
git restore .

# Unstage a file (keep changes, remove from staging)
git restore --staged FileName.ps1

# Revert a commit safely (creates a new "undo" commit)
git revert abc1234

# Remove untracked files
git clean -f

# Remove untracked files AND directories
git clean -fd

# Dry run — preview what clean would delete
git clean -n

restore vs revert vs reset

These three get confused constantly:

  • git restore — fixes your working directory or staging area (nothing committed yet)
  • git revert — creates a new commit that undoes a previous one (safe on pushed commits)
  • git resetmoves the branch pointer to a different commit (see Resets — careful on pushed commits)

Resets

What it does: Move your branch pointer to a previous commit, with control over what happens to your changes.

# Soft — move HEAD back, keep changes staged
git reset --soft HEAD~1

# Mixed (default) — move HEAD back, unstage changes but keep them
git reset HEAD~1

# Hard — move HEAD back and DISCARD changes
git reset --hard HEAD~1

# Reset to a specific commit hash
git reset --hard abc1234

# Go back 3 commits (soft)
git reset --soft HEAD~3

The Three Resets at a Glance

Think of it as how far back the reset reaches:

  • Soft — moves the pointer only. Changes stay staged, ready to re-commit.
  • Mixed — moves the pointer and unstages. Changes still exist in your files.
  • Hard — moves the pointer and wipes your files clean. Changes are gone.

Hard Reset Is Destructive

git reset --hard discards changes permanently. If you do it by accident, git reflog may save you — but act fast. Never hard reset pushed commits on a shared branch.

Cherry-Pick

What it does: Grab a single commit from another branch and apply it to your current branch — without merging everything.

# Apply one specific commit
git cherry-pick abc1234

# Apply without auto-committing (lets you edit first)
git cherry-pick --no-commit abc1234

# Apply multiple commits
git cherry-pick abc1234 def5678

# Abort if something goes wrong
git cherry-pick --abort

Cherry-Pick a Bugfix

Scenario: You fixed a bug on feature/hotfix but only need that one commit on main.

# Find the commit
git log feature/hotfix --oneline
# abc1234 Fix null reference in auth.ps1

# Switch to main and apply just that commit
git switch main
git cherry-pick abc1234

Real-World Examples

Example: Full Feature Branch Workflow

Scenario: You need to build and ship a new PowerShell module without touching main until it's ready.

# Start from an up-to-date main
git switch main
git pull

# Create your feature branch
git switch -c feature/new-module

# Work and commit as you go
git add NewModule.ps1
git commit -m "Add initial module scaffold"

# Push your branch to remote
git push -u origin feature/new-module

# When it's ready, merge to main
git switch main
git pull                              # Stay up to date
git merge feature/new-module
git push

# Clean up
git branch -d feature/new-module
git push origin --delete feature/new-module

Example: Oops — Undo That Last Commit

Scenario: You committed to main by accident and it hasn't been pushed yet.

# Keep the changes, just undo the commit
git reset --soft HEAD~1

# Or discard the changes entirely
git reset --hard HEAD~1

Important Parameters

Command Flag Description Example
git log --oneline Compact single-line format git log --oneline
git log --graph --all Visual branch graph git log --oneline --graph --all
git push -u Set upstream tracking git push -u origin main
git push --force-with-lease Safe force push git push --force-with-lease
git stash push -u Include untracked files git stash push -u -m "msg"
git reset --soft Move HEAD, keep staged git reset --soft HEAD~1
git reset --hard Move HEAD, discard changes git reset --hard HEAD~1
git clean -n Dry run preview git clean -n
git clean -fd Remove untracked files+dirs git clean -fd
git branch -a Show local + remote git branch -a
git cherry-pick --no-commit Apply without committing git cherry-pick --no-commit abc1234
git fetch --prune Remove stale remote refs git fetch --prune

Common Patterns

# Pattern 1: Quick save and context switch
git stash push -m "mid-feature work"
git switch main
# ... handle something on main ...
git switch feature/my-feature
git stash pop

# Pattern 2: Nuke all local changes and start fresh
git restore --staged .
git restore .

# Pattern 3: See what a branch changed before merging
git log main..feature/my-branch --oneline
git diff main..feature/my-branch

# Pattern 4: Rebase your branch on top of main (clean history)
git switch feature/my-branch
git pull --rebase origin main

# Pattern 5: See who changed what in a file
git log -p FileName.ps1          # Full diff history
git blame FileName.ps1           # Line-by-line authorship

Tips & Tricks

Set Up Git Aliases

Cut down on repetitive typing with git's built-in aliases:

git config --global alias.st "status -s"
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.co "switch"
Now git lg gives you a full branch graph at a glance.

Reflog Is Your Safety Net

Accidentally hard reset or lost a commit? git reflog shows everywhere HEAD has been — even after resets:

git reflog
# abc1234 HEAD@{0}: reset: moving to HEAD~1
# def5678 HEAD@{1}: commit: Add login feature   <-- that's the one

git reset --hard HEAD@{1}       # Recover it

Don't Force Push Shared Branches

# BAD — silently overwrites other people's work
git push --force

# GOOD — fails if the remote has changes you haven't seen
git push --force-with-lease

Additional Resources