A Git branch lets work continue from a chosen commit without moving another branch. Teams use branches to isolate features, fixes, experiments, and release work until those changes are ready to integrate.
Read Git Fundamentals and Git Remotes first if HEAD, commits, or remote-tracking branches are unfamiliar.
What a Branch Is
A branch is a lightweight, movable name that points to a commit. It is not another copy of the repository.
C1 ← C2 ← C3 ← C4
▲ ▲
│ │
main feature/search-filtersBoth branches initially point to the same commit. A new commit made while feature/search-filters is checked out moves that branch forward; main remains where it was.
HEAD normally points to the currently checked-out branch:
HEAD → feature/search-filters → C4The working tree contains the files from the checked-out commit plus any local edits. Uncommitted edits belong to the working tree, not to a branch.
Note: A repository’s primary branch may be named
main,master, or something else. These notes usemainexplicitly rather than assuming a default.
Inspect Branches
# List local branches
git branch
# Show local and remote-tracking branches
git branch --all
# Print only the current branch name
git branch --show-current
# Display the commit graph and branch pointers
git log --graph --oneline --decorate --allIn ordinary git branch output, * marks the current branch:
* main
feature/search-filters
fix/login-timeoutThe asterisk does not indicate that main is more important. It only shows which branch is checked out in the current working tree.
Create and Switch Branches
Create a branch from the current commit and switch to it:
git switch -c feature/search-filtersThis combines two operations:
git branch feature/search-filters
git switch feature/search-filtersCreate a branch from another starting point:
git switch -c fix/login-timeout origin/mainThe new branch starts at the commit identified by origin/main.
Switch between existing branches:
git switch main
git switch feature/search-filters
# Return to the previously checked-out branch
git switch -git checkout -b <branch> is an older, still-supported way to create and switch branches. git switch -c <branch> is clearer because git checkout also performs unrelated file and commit operations.
Git may refuse to switch if doing so would overwrite local changes. Inspect git status, then commit coherent work or stash unfinished work instead of forcing the switch.
Scenario: Pause a Feature for an Urgent Fix
Suppose a report-export feature is in progress on feature/report-export when production checkout requests begin timing out.
flowchart LR C0["C0"] --> C1["C1"] C1 --> H1["H1<br/>Payment timeout fix"] C1 --> F1["F1<br/>Report export"] --> F2["F2"] C1 --> M1["M1<br/>fix merged"] H1 --> M1 M1 --> M2["M2<br/>feature merged"] F2 --> M2
main follows C0 → C1 → M1 → M2. The fix and feature work begin from separate commits and later merge into the main line.
1. Preserve the unfinished feature work
Check the current state:
git statusCommit the work if it forms a useful checkpoint:
git add src/reports/export.ts
git commit -m "Add initial report export"If it is not ready for a commit, stash tracked and untracked changes:
git stash push -u -m "Report export in progress"See Temporarily Store Unfinished Work for stash behavior and limitations.
2. Create the fix from current production history
git switch main
git pull --ff-only
git switch -c fix/payment-timeoutThis assumes the local main branch tracks the shared main branch covered in Git Remotes. Updating it first prevents the fix from starting at an unnecessarily old commit.
3. Make, inspect, and publish the fix
git status
git add config/payment-service.yaml
git diff --staged
git commit -m "Handle payment service timeout"
git push -u origin fix/payment-timeout-u records origin/fix/payment-timeout as the local branch’s upstream. Later pushes from this branch can normally use git push without repeating both names.
The usual team workflow is then:
- Open a pull request from
fix/payment-timeouttomain. - Run automated tests and review the change.
- Merge using the repository’s configured merge policy.
- Deploy and validate the fix through the team’s release process.
Git records and integrates the application change. It does not deploy or validate the live service by itself.
4. Resume the feature
After the fix is merged remotely:
git switch main
git pull --ff-only
git switch feature/report-export
git merge mainIf the feature work was stashed, apply it after updating the feature branch:
git stash popThe merge brings the production fix into the feature branch. Some teams use git rebase origin/main instead. Follow one agreed workflow: rebasing rewrites the feature commits and needs extra care if other developers already use that branch.
Merge Direction
git merge <source> integrates the source branch into the currently checked-out branch.
To merge fix/payment-timeout into main locally:
git switch main
git merge fix/payment-timeoutRead the second command as:
merge fix/payment-timeout into the current branch, mainThis local merge-and-push workflow works only when project policy allows direct updates to main:
git push origin mainMany shared repositories protect main and require a pull request instead.
Fast-Forward and Three-Way Merges
Git chooses the merge result from the commit graph.
| Situation | Result |
|---|---|
| Current branch has not advanced since the other branch diverged | Git can move the current branch pointer forward without a merge commit |
| Both branches contain new commits | Git normally performs a three-way merge and creates a commit with two parents |
| Both sides changed the same area incompatibly | Git pauses for conflict resolution |
Fast-forward
Before:
C1 ← C2 main
\
C3 ← C4 featureAfter merging feature into main, main can simply move to C4:
C1 ← C2 ← C3 ← C4
▲
│
main, featureThree-way merge
When both branches advanced, Git compares the two tips and their common ancestor:
C1 ── C2 ── M1 ─────┐
└── F1 ───────┴── M2 ← main
▲
│
featureThe merge commit has two parents. Repository settings may instead require squash merging, rebasing, or a merge commit even when a fast-forward is possible.
Branching Strategy Is a Team Decision
Git supplies branch and merge mechanics; it does not require one branching model.
| Approach | Typical shape | Useful when |
|---|---|---|
| Short-lived topic branches | Branch from main, review, merge, delete | Teams integrate small changes frequently |
| Trunk-based development | Very short branches or direct, guarded changes to the main line | Strong automated testing and rapid integration are available |
| Gitflow-style branches | main, long-lived develop, plus feature, release, and hotfix branches | A team deliberately manages scheduled releases through multiple long-lived stages |
A permanent develop branch is therefore a workflow choice, not a requirement or default created by Git. Likewise, “never commit directly to main” is a common repository policy, not a limitation of the Git command-line tool.
Long-lived branches usually diverge further and require more integration work. Small changes, frequent integration, automated tests, and clear ownership reduce conflict risk.
Compare Work with git diff
The meaning of - and + in diff output depends on the two compared states:
-marks a line present on the left or earlier side but absent on the right side.+marks a line present on the right or later side but absent on the left side.
Useful comparisons include:
| Command | Comparison |
|---|---|
git diff | Working tree against the staging area |
git diff --staged | Staging area against HEAD |
git diff HEAD | Working tree, including staged and unstaged changes, against HEAD |
git diff main feature/metrics-dashboard | Snapshot at main against the snapshot at the feature tip |
git diff main...feature/metrics-dashboard | Changes on the feature side since its merge base with main |
For git diff, main..feature/metrics-dashboard compares the same two endpoint snapshots as main feature/metrics-dashboard. Three dots have different meaning: they start the comparison at the branches’ common ancestor.
Use a path after -- to restrict a comparison:
git diff main...feature/metrics-dashboard -- src/metrics/dashboard.tsHandle a Merge Conflict
Git automatically combines non-overlapping changes. It may stop when both branches change the same lines differently, or when one branch deletes a path that the other modifies.
Start from a clean working tree before merging:
git status
git switch main
git merge fix/cache-expiryA textual conflict may appear as:
<<<<<<< HEAD
cache_ttl_seconds: 300
=======
cache_ttl_seconds: 600
>>>>>>> fix/cache-expiryIn this merge:
HEADis the current receiving branch.fix/cache-expiryis the branch being merged.=======separates the two versions.
The correct result may use either side, combine both sides, or replace both. Edit the file so it contains the intended final configuration and remove all conflict markers.
Then inspect, test, and stage the resolution:
git status
git diff
git add config/cache.yaml
git diff --staged
git merge --continuegit add marks that path as resolved. git merge --continue completes the paused merge after all conflicts are resolved.
To abandon the merge and try to reconstruct the pre-merge state:
git merge --abortgit merge --abort is safest when the merge began with a clean working tree. It may be unable to reconstruct unrelated uncommitted changes exactly.
Warning: A file with no remaining conflict markers is not necessarily correct. Validate syntax, tests, and operational intent before completing the merge.
Delete a Finished Branch
After verifying that the work is integrated, delete the local branch:
git switch main
git branch -d fix/payment-timeout-d refuses deletion when Git cannot confirm that the branch is merged into its upstream or the current branch. Force deletion bypasses that protection:
git branch -D fix/payment-timeoutUse -D only when the unmerged commits are intentionally disposable or recoverable elsewhere.
Note: After a squash merge,
-dmay refuse deletion because the original branch commits are not ancestors ofmain. Verify the merged result and repository history before deliberately using-D.
Deleting a local branch does not delete its remote counterpart:
git push origin --delete fix/payment-timeoutDeleting a branch removes its name, not the commits that are still reachable through another branch or tag.
Command Summary
| Command | Purpose |
|---|---|
git branch | List local branches |
git switch -c <branch> | Create and switch to a branch |
git switch <branch> | Switch to an existing branch |
git merge <branch> | Merge a source branch into the current branch |
git merge --continue | Complete a merge after resolving conflicts |
git merge --abort | Abandon a merge in progress |
git diff <a> <b> | Compare two endpoint snapshots |
git diff <a>...<b> | Compare the merge base with the second endpoint |
git branch -d <branch> | Safely delete a merged local branch |
git push origin --delete <branch> | Delete a branch from the named remote |
Mistakes to Avoid
- Treating a branch as a complete copy of the repository
- Assuming
git branch <name>also switches to the new branch - Merging while unsure which branch is currently checked out
- Starting urgent work from a stale local
main - Forcing a branch switch when local work has not been preserved
- Using
git branch -Das the normal cleanup command - Treating a
developbranch as a Git requirement - Removing conflict markers without validating the combined result
- Assuming deletion of a local branch also deletes the remote branch
- Assuming a successful Git merge means the change was deployed successfully
TL;DR
- A branch is a movable name pointing to a commit, not a duplicate repository.
git switch -c <branch>creates and checks out a branch.- Preserve unfinished work before switching to an urgent fix.
git merge <branch>merges the named branch into the current branch.- A fast-forward moves a pointer; diverged histories normally require a three-way merge.
- Branching models and protected-branch rules are team policies, not Git requirements.
- Resolve conflicts by editing the intended result, staging it, testing it, and continuing the merge.
- Prefer
git branch -dover force deletion.
Resources
- Git branches in a nutshell
git switchgit branch- Basic branching and merging
git mergegit diff- Distributed Git workflows
Continue with Undoing Changes for stashing work and choosing between restore, reset, and revert.
Note: Branch, merge, and diff behavior was checked against current Git documentation in July 2026.