Safeguard
DevSecOps

How to Use Git Branch (and git checkout) Safely

A working reference for creating, switching, and checking out Git branches, plus the security habits that keep secrets and bad commits out of your history.

Marcus Chen
DevSecOps Engineer
6 min read

git branch is the command that lists, creates, and deletes branches in a Git repository, and paired with git checkout (or the newer git switch) it is how you isolate work so that one line of development never contaminates another. Getting the mechanics right is table stakes; the part most guides skip is that your branching habits are also a security control, because history is forever and secrets committed to a branch do not disappear when you delete the branch.

Here is the working reference I hand to engineers joining a team, plus the parts that keep the repo clean.

Creating and Listing Branches

To see what exists:

git branch          # local branches, current one starred
git branch -a       # include remote-tracking branches
git branch -v       # show the last commit on each

To create a branch from your current commit:

git branch feature/new-parser

That creates it but leaves you where you are. Most of the time you want to create and move onto it in one step, which is where git checkout comes in.

git checkout: The Multi-Tool

The command git checkout does several distinct jobs, which is exactly why it confused people enough that Git 2.23 split it into git switch and git restore. Both old and new syntax still work.

To create a branch and switch to it in one move (this is the git checkout new branch pattern):

git checkout -b feature/login-rate-limit
# modern equivalent:
git switch -c feature/login-rate-limit

To switch to an existing local branch (git checkout branch):

git checkout main
# modern equivalent:
git switch main

git checkout remote branch

A common stumbling block: a teammate pushed a branch, you can see it with git branch -a as remotes/origin/their-feature, but git checkout their-feature seems like magic. It works because Git auto-creates a local tracking branch when the name is unambiguous:

git fetch origin
git checkout their-feature
# Git prints: "Set up to track 'origin/their-feature'"

If the name is ambiguous or you want to be explicit:

git switch -c their-feature --track origin/their-feature

Always git fetch first so your view of the remote is current; checking out a stale remote branch is a common source of "why is my code missing" confusion.

git checkout file from another branch

You do not have to switch branches to grab a single file from one. This is genuinely useful when you want one fixed config or one function from another branch without the rest of its changes:

git checkout other-branch -- path/to/file.js
# modern equivalent:
git restore --source=other-branch path/to/file.js

The file lands in your working tree, staged, and you keep working on your current branch. Use this instead of copy-pasting between two checkouts, which is how people accidentally drop half a change.

The Security Habits That Matter

Now the part that turns branching from a convenience into a control.

Secrets in history are the classic mistake. If you git commit an API key on a branch, deleting the branch does not remove the commit if it was ever pushed or merged, and even locally the object lingers in the reflog. The fix is prevention: run a secret scanner as a pre-commit hook (gitleaks or git-secrets) so the key never enters a commit. If one slips through, treat it as compromised and rotate it immediately, then purge history with git filter-repo. Rotation is the real remediation; history rewriting is cleanup.

Protect the important branches. On the server side, mark main (and release branches) as protected: require pull requests, require review, and require passing CI before merge. This is not bureaucracy, it is what stops an unreviewed commit, or a compromised developer laptop, from pushing straight to what you deploy. A short-lived feature/<slug> branch that goes through review is the whole point of branching.

Keep branches short-lived. A branch that lives for three months accumulates merge conflicts and, more importantly, drifts away from the security fixes landing on main. Rebase or merge from main regularly so you inherit dependency bumps and patches rather than shipping a stale tree. When you scan a feature branch, an SCA tool checks the dependencies as they are on that branch, so a long-lived branch can hide vulnerabilities that main has already fixed.

Verify what you check out. When you git checkout a contributor's branch from a fork, you are running their code. Review the diff before you run their build scripts or install their dependencies, because a malicious postinstall in a package.json on a fork branch runs the moment you npm install.

Cleaning Up

Delete merged branches so git branch stays readable:

git branch -d feature/login-rate-limit     # safe: refuses if unmerged
git branch -D feature/abandoned-experiment  # force delete
git push origin --delete feature/login-rate-limit

The lowercase -d refuses to delete a branch that has not been merged, which is a small guardrail against throwing away work. Reach for -D only when you genuinely mean to discard.

FAQ

What is the difference between git branch and git checkout?

git branch manages branches: it lists, creates, and deletes them. git checkout moves your working tree, whether that means switching to a branch, creating and switching in one step with -b, or pulling a single file from another branch. Newer Git splits checkout's jobs into git switch and git restore.

How do I check out a remote branch?

Run git fetch to update your view of the remote, then git checkout branch-name. Git automatically creates a local branch that tracks the remote one when the name is unambiguous. If it is ambiguous, use git switch -c name --track origin/name.

How do I get one file from another branch without switching?

Use git checkout other-branch -- path/to/file (or the modern git restore --source=other-branch path/to/file). The file is copied into your current working tree and staged, and you stay on your current branch.

Does deleting a branch remove secrets I committed to it?

No. If the commit was ever pushed or merged, the secret persists in history, and locally it lingers in the reflog and object store. Rotate the exposed credential immediately, then rewrite history with a tool like git filter-repo. Prevent it next time with a pre-commit secret scanner.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.