Posts in category “Git”

Got personal files to ignore? Use .git/info/exclude, not the shared .gitignore

When you want Git to ignore something that's yours — a local scratch dir, editor cruft, a personal plans/ folder, machine-local config — don't add it to the tracked .gitignore. That file is shared: a rule like plans/ or wiki-drafts/ forces your personal directory conventions onto everyone, and they don't have those dirs.

Put it in .git/info/exclude instead. Same syntax as .gitignore, but it's per-clone and never committed — so it's invisible to teammates and travels with nothing:

# .git/info/exclude
.claude/settings.local.json
.claude/plans/
.claude/wiki-drafts/

The rule of thumb: **.gitignore is for what the project should ignore (build output, node_modules/, *.user); .git/info/exclude is for what you happen to ignore on this machine.** If a teammate cloning fresh wouldn't also produce the file, it doesn't belong in the shared list.

One gotcha with worktrees: info/exclude lives in the common git dir, so it's shared across all linked worktrees of the same clone — but still not across separate clones. Find it with git rev-parse --git-common-dir if you're not sure where it is.

And if you ever need to start tracking something a blanket exclude was hiding (e.g. you had .claude excluded but now want .claude/skills/ committed), narrow the exclude line to the specific paths you still want ignored — don't delete it and shove replacement rules into the shared .gitignore.

Two GitHub accounts on one Windows box, HTTPS only? Don't let `gh` be your git credential helper

If you run gh auth setup-git, the GitHub CLI becomes git's credential helper — and it only ever hands out the token for the active account. The moment you git pull a repo belonging to your other account, you get the wrong token (403, or commits land under the wrong identity). There's no per-repo routing; you'd have to gh auth switch every single time you cross accounts.

You can prove it to yourself — ask the helper for the non-active account and it returns nothing:

"protocol=https`nhost=github.com`nusername=second-account`n`n" |
  & gh auth git-credential get      # exit 1, no token

The fix is to hand git over to Git Credential Manager (it already ships with Git for Windows). GCM picks the token by the username embedded in the remote URL, so routing becomes automatic. gh keeps working for gh issue/gh pr — it uses its own keyring, separate from the git helper.

Switch the helper and point GCM at GitHub:

git config --global --unset-all credential.https://github.com.helper
git config --global credential.helper manager
git config --global credential.https://github.com.provider github
git config --global credential.guiPrompt false   # terminal prompts, no GUI popup on a server
…more

Git Worktree: Checkout an Existing Branch Into a Separate Directory

Need to work on two branches simultaneously without stashing or cloning? git worktree creates a separate working directory that shares the same .git — no duplicate objects, no wasted space.

git worktree add <path> <branch>

For example, to checkout feature/login into a sibling directory:

git worktree add ../my-feature feature/login

This creates ../my-feature with the branch checked out and ready to work. Commits, branches, and remotes are shared — it's one repository, multiple workspaces.

Day-to-day operations:

  • git worktree list — see all linked worktrees
  • git worktree remove <path> — clean up when done

One restriction: the same branch cannot be checked out in two worktrees at once. Git enforces this to prevent conflicting writes to the ref.

Git over SSH blocked on public WiFi? Try port 443

Some public networks (libraries, hotels, offices) block SSH's default port 22, which breaks git push/pull to GitHub.

GitHub supports SSH over port 443 as a workaround. Test it first:

ssh -T -p 443 [email protected]

If you see Hi <username>!, it works. Update your repo's remote URL:

git remote set-url origin ssh://[email protected]:443/your-username/your-repo.git

Then git push as normal.

Want this permanently? Add to ~/.ssh/config:

Host github.com
  Hostname ssh.github.com
  Port 443

This transparently redirects all GitHub SSH traffic to port 443 — no need to change remote URLs in any of your repos.

Using `git diff HEAD` to show All Changes

You probably know:

  • git diff shows unstaged changes.
  • git diff --cached shows staged changes.

But how do you see all changes in one go? Just use:

git diff HEAD

Here's the breakdown:

  • git diff compares the working directory to the staged index. If nothing is staged, it's the same as git diff HEAD.
  • git diff --cached compares the staged index to HEAD. It's a shortcut for git diff --cached HEAD.
  • git diff HEAD (or git diff <commit/branch/tag>) compares your current working directory with the specified commit.