This is my running log of Git moves I reach for when I do work. Each mini-how-to includes the exact commands plus a quick note on what to watch for.

Squash Multiple Commits Into One#

Use interactive rebase to collapse the last n commits into a single, tidy changeset.

Optional safety: create a backup branch before rebasing:

git branch backup/feature-branch-before-squash
git rebase -i HEAD~3

Replace 3 with however many commits you want to include, counting the current HEAD as part of that total. HEAD refers to the current commit, HEAD~1 to its parent, HEAD~2 to the one before that, and so on. When you run git rebase -i HEAD~3, Git lists the last three commits including HEAD. Run git log --oneline to count backward until you reach the oldest commit you intend to squash.

Tip: Use HEAD~3^ if you need to include the fourth commit in the interactive list.

For example, if your history looks like this (newest first):

a1b2c3 (HEAD)
d4e5f6
g7h8i9
j0k1l2

The command git rebase -i HEAD~3 opens the editor with:

pick j0k1l2
pick g7h8i9
pick d4e5f6

In the editor:

  • Leave the first commit as pick
  • Change the rest to squash (or s)
  • Save, then compose the final commit message

If conflicts appear, resolve them and resume with git rebase --continue.

To abort the squash at any point, run:

git rebase --abort

Force Push After Squashing#

Once history changes, update the remote branch.

git push --force-with-lease origin feature/my-branch

--force-with-lease protects teammates by refusing to overwrite work you haven’t fetched.

Create a Local Repo and Wire Up a Remote#

mkdir my-project && cd my-project
git init
# add files, then commit
git add .
git commit -m "Initial commit"
git remote add origin [email protected]:username/my-project.git
git push -u origin main

If the remote is empty, main (or master) becomes the default branch once you push with -u. Double-check the URL format (git@ for SSH, https:// for HTTPS) before adding the remote.

Track a Remote Branch Locally#

When you create a local branch that should follow an existing remote branch, set the upstream explicitly.

git switch -c feature/api-integration origin/feature/api-integration
# or, if branch already exists locally
git branch --set-upstream-to=origin/feature/api-integration

Now git pull and git push know which remote branch to use. If Git complains that the remote ref is missing, fetch it first (git fetch origin feature/api-integration) and rerun the command.

Create a Branch and Push It Upstream#

Shortcut to create a branch, commit, and publish it with upstream tracking in one go.

git switch -c feature/search-bar
git commit -am "Add search bar styles"
git push -u origin feature/search-bar

-u (or --set-upstream) wires the remote for future pushes. Remember that git commit -am only stages files Git already tracks—run git add first if you created new files.

Sync With the Latest From Main Without Merge Commits#

Rebase your current branch onto main to replay your commits on top of the latest state.

Optional safety: create a backup before rebasing:

git branch backup/feature-search-bar-before-rebase
  1. Make sure you have no pending edits: git status -sb should report a clean tree.
  2. Update main so you are rebasing onto the real latest code.
    git switch main
    git pull --ff-only origin main
    
  3. Return to your feature branch (replace with your branch name).
    git switch feature/search-bar
    
  4. Replay your commits on top of the freshly updated main.
    git rebase main
    

⚠️ Rebase pointer:
In merges: ours = current branch, theirs = incoming.
In rebases: ours = target branch, theirs = replayed commit.
Pick the pieces you need, git add each resolved file, and continue with git rebase --continue.
If the rebase turns chaotic, bail out with git rebase --abort.

Once the history looks right, rerun your tests and publish the new linear history:

git push --force-with-lease origin feature/search-bar

If you prefer to preserve merge commits instead, use git merge origin/main.

Rebase Onto the Remote Version of Your Branch#

When teammates update the remote feature branch, pull those commits in and resolve conflicts locally.

Optional safety: create a backup before rebasing:

git branch backup/feature-payment-before-rebase
  1. Ensure a clean tree first: git status -sb.
  2. Update your knowledge of the remote branch.
    git fetch origin feature/payment
    
  3. Switch to your local branch that you want to replay.
    git switch feature/payment
    
  4. Rebase onto the remote tracking branch you fetched.
    git rebase origin/feature/payment
    

⚠️ Rebase pointer:
In merges: ours = current branch, theirs = incoming.
In rebases: ours = target branch, theirs = replayed commit.
Merge the pieces you want, stage them with git add, and continue (git rebase --continue).
If the rebase turns chaotic, bail out with git rebase --abort.
Alternatively, if your upstream is set, you can pull and rebase in one step:

git pull --rebase

After the rebase, rerun tests and share the rewritten history safely:

git push --force-with-lease origin feature/payment

Cherry-Pick a Fix Onto Another Branch#

Grab a single commit and apply it elsewhere.

git switch release/1.2
git cherry-pick <commit-sha>

If conflicts arise, fix them, git add the files, and run git cherry-pick --continue.

For multiple commits, cherry-pick a range (the upper bound is exclusive):

git cherry-pick A..B

Tip: Use A^..B if you want to include commit A itself.

Quick Patch From a File Diff#

Generate a patch for one file and drop it into another branch or repo.

git diff main..feature/payment checkout.swift > checkout.patch
git switch hotfix/payment-crash
git apply checkout.patch

Review the applied changes before committing.

git apply only affects the working tree; follow up with git add and git commit once you confirm the patch looks right.

Tip: Run git am checkout.patch instead if you want to preserve the original author and commit message from the patch.

Merge Main Into Your Branch (Keep the Merge Commit)#

If your team relies on merge commits for context, integrate the latest main without rewriting history.

git fetch origin
git merge --no-ff origin/main

Resolve conflicts, run the test suite, and let Git create the merge commit message. --no-ff retains the merge node even when a fast-forward is possible, preserving the branch narrative.

See What Changed Between Two Branches#

Compare your feature branch to main, highlighting only the files or commits that differ.

git log --oneline main..feature/billing
git diff --stat main...feature/billing

Two dots (..) show unique commits; three dots (...) reveal files that diverged from the common ancestor.

Undo the Last Commit (Keep Changes)#

Keep your working tree but remove the most recent commit.

git reset --soft HEAD~1

HEAD is the current commit, so HEAD~1 targets the one before it. The changes remain staged. To unstage but keep edits, use git reset --mixed HEAD~1.

Recover Work You Thought Was Gone#

If a commit vanished after a reset or rebase, scan the reflog.

git reflog

You can use git show <reflog-sha> to inspect the commit before checking it out.

git switch --detach <reflog-sha>

Create a new branch from that SHA to rescue the work: git switch -c rescue/forgotten <sha>.

Stash Selective Files#

Avoid stashing the whole tree by selecting specific paths.

git stash push -- src/HomeView.swift
git stash list
git stash pop

Combine with --keep-index to stash only unstaged changes. Stashes are stored in order; use git stash list to view entries and git stash pop stash@{1} to apply a specific one.

Clean Untracked Files Safely#

Preview deletions before scrubbing untracked files and directories.

git clean -nd
git clean -fd

-n performs a dry run; -f is required to delete, and -d includes directories. Double-check the dry-run output carefully—git clean is irreversible once it runs with -f.

Revert a Commit That Already Hit Main#

Create a new commit that undoes a previous one (keeps history intact).

git revert <commit-sha>

Grab the commit SHA from git log --oneline. If the revert itself fails because of conflicts, resolve them, git add the files, and run git revert --continue.

Tip: Need to revert several commits in one go? Use git revert -n <sha1> <sha2> ... to stage the reversions and commit once at the end.

Rename a Branch Locally and Remotely#

git branch -m old-name new-name
git push origin --delete old-name
git push -u origin new-name

If the branch is protected, you may need admin permissions (or to lift protection temporarily) before deleting it remotely. Afterwards, clean up stale references locally:

git fetch --prune

Anyone else using the old branch should do the same and check out the new name.


I add to this page whenever I find myself repeating a Git flow. If you’re reading along and need another scenario covered, let me know and I’ll expand the list.