Commit to Success: Mastering Git From Init to Push
Branching and Merging Strategies
Work in Parallel, Then Bring It Back

In plain words: a branch lets you try something in its own lane without touching the working version. In this article you will create and switch branches, merge them back together, fix the one situation where Git cannot merge by itself (a conflict), and learn what rebasing is and when to avoid it.
You can already commit and undo. Now suppose you want to try a new feature without risking the version that works. If it goes badly, Undo Mistakes Safely is there, but a branch means you may not need it.
A branch is its own lane of commits. Two people, or one person with two ideas, can work in parallel, and main stays stable until a branch is ready to join it. The branch commands from part 1 (list, create, rename, delete) are assumed here. What we add is moving between branches, merging, and conflicts.
Understanding Branches: More Than Just a Name#
What Branches Actually Are#
At their core, branches in Git are simply lightweight, movable pointers to specific commits. When we create a branch, we're not actually duplicating code—we're just creating a new reference to a commit. That is why branching in Git is nearly instant, however big the project is.
Each branch name points to the commit at its tip, and as we add new commits to a branch, this pointer automatically moves forward. Several lines of work cost almost nothing to keep.
The HEAD Pointer: Your Current Location#
In the Git universe, HEAD is a special pointer that indicates which branch (or commit) you're currently working with. Think of HEAD as "you are here" on a map—it's your current position in the repository's history.
When you checkout a branch, HEAD points to that branch, which in turn points to a commit. This is known as being in "attached HEAD" state. Sometimes, you might checkout a specific commit directly (rather than a branch), putting you in "detached HEAD" state—useful for exploring history but requiring care when making changes.
Local vs. Remote Branches#
Git distinguishes between branches that exist on your machine (local branches) and those that exist on remote repositories (remote branches).
Local branches are yours to control—you can create, modify, and delete them freely without affecting others. A remote is a copy of the project hosted elsewhere (such as on GitHub), and origin is the usual nickname for it. Remote branches, like origin/main, represent the state of branches on remote repositories. These serve as bookmarks showing you where branches were the last time you communicated with the remote repository.
Changes to remote branches only happen when you explicitly sync with the remote using commands like push, fetch, or pull.
Branch Operations: Creating Your Development Paths#
Creating Branches#
Creating a branch in Git is straightforward and can be done in multiple ways:
# Traditional two-step approach
git branch feature-login # Create branch
git checkout feature-login # Switch to branch
# Shorthand approach (creates and switches in one command)
git checkout -b feature-login
# Modern approach (Git 2.23+)
git switch -c feature-login
Each approach creates a new branch pointer at your current commit. The -b or -c flag combines creation and switching into a single step.
Switching Between Branches#
When you switch, Git updates your working directory to match the snapshot stored in the target branch:
# Traditional approach
git checkout main
# Modern approach (Git 2.23+)
git switch main
When switching branches, Git tries to preserve uncommitted changes if possible. However, if those changes conflict with the target branch, Git prevents the switch to avoid losing work.
Listing, renaming, and deleting#
Those are in part 1: git branch lists, -m renames, -d deletes a merged branch, and -D deletes one that still has unmerged work. The practice terminal below ends with a delete.
Merging Fundamentals: Bringing Changes Together#
The Concept of Merging#
Merging is the process of integrating changes from one branch into another. When you've completed work on a feature branch, you typically merge it back into your main development branch.
Git's merge process:
-
Identifies the common ancestor commit of the two branches
-
Determines changes introduced since that common ancestor
-
Applies those changes to the target branch
-
Creates a new "merge commit" that combines both histories (in most cases)
Fast-Forward vs. Three-Way Merges#
Git performs two types of merges depending on the branch structure:
Fast-forward merges occur when the target branch hasn't changed since your feature branch was created. In this case, Git simply moves the target branch pointer forward to match the feature branch—no new commit needed.
# Example of fast-forward merge
git checkout main
git merge feature-simple
Three-way merges happen when both branches have new commits since they diverged. Git creates a new "merge commit" with two parent commits (one from each branch).
# Three-way merge (creates a merge commit)
git checkout main
git merge feature-complex
You can force a merge commit even for fast-forward merges:
git merge --no-ff feature-branch
That keeps a visible record of each feature branch in the history.
Merge Conflicts and How to Resolve Them#
Merge conflicts occur when Git can't automatically reconcile competing changes to the same part of a file. When this happens, Git pauses the merge process and marks the conflicted areas:
<<<<<<< HEAD
Code from the current branch
=======
Code from the branch being merged
>>>>>>> feature-branch
To resolve conflicts:
-
Open conflicted files in your editor
-
Decide which changes to keep (or combine them)
-
Remove the conflict markers
-
Stage the resolved files with
git add -
Complete the merge with
git commit
VS Code and most other editors have a visual conflict view if you prefer clicking to editing markers.
See it fail first#
Here is a real conflict. Both branches changed the color line of site.txt since they split: main made it red, feature made it green. Standing on main, we merge:
$ git merge feature
Auto-merging site.txt
CONFLICT (content): Merge conflict in site.txt
Automatic merge failed; fix conflicts and then commit the result.
$ git status -s
UU site.txt
$ cat site.txt
title: Home
<<<<<<< HEAD
color: red
=======
color: green
>>>>>>> feature
Nothing is broken. UU means "unmerged on both sides", and Git has written both versions into the file for us to choose between. The top half (between <<<<<<< HEAD and =======) is the branch we are standing on, main. The bottom half is the branch we are merging in, feature. To give up instead, git merge --abort returns to the state before the merge.
Challenge: finish the merge
You are in the conflicted state above and have decided the site should be green.
- TODO 1: edit
site.txtso it holds exactlytitle: Homeandcolor: green, with no marker lines. - TODO 2: type the command that tells Git this file is resolved.
- TODO 3: type the command that completes the merge.
Expected result: git status -s after TODO 2 shows M site.txt, and after TODO 3 git log --oneline --graph shows two lines of history joining in one merge commit, titled Merge branch 'feature'.
Check your answer
After editing the file: git add site.txt, then git commit --no-edit (or git commit and save the message that opens).
Try the merge yourself in a safe, in-memory repository.
Starting state: one branch, main, with one commit ("Start project") that created README.md. Do this in order:
git switch -c feature, thengit commit -m "Add notes" -f notes.md.git switch main, thengit commit -m "Add todo" -f todo.md.git merge feature.
What to check: because the branches changed different files, the merge succeeds and the history graph shows a merge commit joining both branches (a commit with two parents).
Now reset and repeat, but make both commits edit README.md (leave off -f). The merge stops with a conflict naming README.md. Fix it with resolve --ours README.md (or --theirs), then git commit to finish. git merge --abort gives up instead.
The sandbox above lets you explore. Here you follow the everyday routine on purpose: branch for a feature, commit, come back to main, merge, and tidy up. Git has several spellings for most of these, and any correct one is accepted.
Type these commands in order, in a terminal inside a practice folder:
- Create a branch called feature/login and switch to it. One command, or
git branchthengit switch. Trygit switch -c feature/login.-cmeans create. Without it, switch only moves to a branch that already exists.git checkout -b feature/login, orgit branch feature/loginfollowed bygit switch feature/login. - Commit your work with a message in quotes. (This practice repository already has a staged change.) Try
git commit -m "Add login form". The commit landed on feature/login. main has not moved. - Go back to main. Try
git switch main. Your files now match main again, without the login form.git checkout mainandgit switch -(previous branch) work too. - Merge feature/login into main. Try
git merge feature/login. Always merge while standing on the branch that should receive the work. main had not moved, so Git slid the label forward: a fast-forward.--no-ffmakes a merge commit anyway. - Delete the finished branch. Try
git branch -d feature/login. The work is safe on main. The label was all that you deleted.
Because main had not moved while you worked, Git only slid its label forward. That is a fast-forward merge. When both branches have new commits, Git makes a merge commit instead.
Rebasing vs. Merging: Different Paths to Integration#
What Rebasing Does#
Rebasing is an alternative to merging that rewrites history to keep it in a straight line. Instead of creating a merge commit, rebasing:
-
Temporarily sets aside your branch's commits
-
Moves your branch pointer to the tip of the target branch
-
Replays your commits one by one on top of this new base
The result is a linear history that looks as if you had started your branch from the current state of the target branch.
git checkout feature-branch
git rebase main
When to Use Rebase vs. Merge#
Use merge when:
-
You want to preserve the exact history of branch development
-
You're collaborating on a branch that others are using
-
You want explicit documentation of where features were integrated
Use rebase when:
-
You want a clean, linear project history
-
You're working on a personal feature branch
-
You want to incorporate the latest changes from the main branch into your feature
A common workflow combines both: rebase your feature branch to incorporate updates from main, then merge (which will be fast-forward) when complete.
Dangers of Rewriting History#
Rebasing changes commit history, creating new commits with different hashes even though the content changes may be identical. This can cause serious problems if:
-
You've pushed your branch to a remote repository
-
Others have based their work on your original commits
The golden rule: avoid rebasing commits that other people already have. Your own branch that nobody else has pulled is safe to rebase. If you do need to rebase a shared branch, coordinate with your team first and use git push --force-with-lease rather than --force for an extra layer of safety (it refuses to overwrite remote commits you have not seen).
Branching Strategies: Frameworks for Collaboration#
Feature Branching#
The simplest branching strategy involves creating a separate branch for each feature or bugfix. This isolates changes and allows developers to work independently.
Basic feature branching workflow:
-
Create a branch for your feature from main
-
Develop and commit changes to your branch
-
Merge the feature branch back to main when complete
-
Delete the feature branch
This approach forms the foundation of most Git workflows.
Choosing a strategy#
The strategies are conventions about how a team uses branches: Git Flow for scheduled releases, GitHub Flow for shipping often, trunk-based development for very short branches. Git Best Practices and Workflows, part 8, compares them and has a quiz on which fits when. Start with feature branches and add rules only when the team needs them.
What we learned#
- A branch is a pointer to a commit, so creating one is cheap.
git switchmoves between branches, andgit switch -ccreates and moves in one step.- A merge fast-forwards when it can and makes a merge commit when it cannot.
- A conflict is Git asking us to decide.
git merge --abortbacks out. - Rebase replays commits as new ones, so leave commits that other people have alone.
So far everything has stayed on one computer. Remote Repositories and Collaboration is next: how to share a branch with a teammate, and what Git says when two people push to the same place.
Comments require JavaScript.