GitBeginner

A Practical Git Branching Workflow for Beginners

Stop committing everything to main. Learn a simple, team-friendly branching workflow with feature branches, pull requests and clean merges.

A feature branch splitting off the main branch and merging back in
On this page

When you first learn Git, it's natural to commit everything straight to main. That works until you need to fix a bug halfway through a feature, or a teammate pushes changes that collide with yours.

Branches solve this. In this guide you'll learn a simple workflow used by teams of every size: create a branch for each piece of work, commit freely, then merge it back when it's ready.

What a branch really is#

A branch in Git is just a movable pointer to a commit. Creating one is instant and costs almost nothing, because Git doesn't copy your files. When you make a new commit, the branch you're on moves forward to point at it.

ABCDEMF main feature/login git switch -c merge commit
A feature branch splits from main, gets its own commits, then merges back

Here, feature/login branches off main after commit C and gets two commits of its own, D and E. Work on one branch doesn't touch the other until you merge, which creates the merge commit M.

The workflow at a glance#

  1. Update your local main.
  2. Create a feature branch.
  3. Commit your work in small steps.
  4. Push the branch and open a pull request.
  5. Keep the branch up to date with main.
  6. Merge, then delete the branch.

Let's walk through each step.

Step 1: Start from an up-to-date main#

Bash
git switch main
git pull origin main

git switch (Git 2.23+) is the modern, clearer alternative to git checkout for changing branches.

Step 2: Create a feature branch#

Bash
git switch -c feature/login-form

The -c flag creates the branch and switches to it in one go. Use descriptive, prefixed names so everyone can tell what a branch is for:

Prefix Use it for Example
feature/ New functionality feature/login-form
fix/ Bug fixes fix/password-reset-email
docs/ Documentation docs/api-examples
refactor/ Code improvements with no behaviour change refactor/user-service

Step 3: Commit in small, meaningful steps#

Make a change, review it, then commit:

Bash
git status              # what changed?
git diff                # review the exact changes
git add src/login.js    # stage specific files
git commit -m "Add login form markup and validation"

Write commit messages for your future self

Use the imperative mood ("Add validation", not "Added validation") and describe what changed and why, not how. A good test: your message should complete the sentence "If applied, this commit will…"

Step 4: Push and open a pull request#

The first time you push a new branch, tell Git which remote branch it should track:

Bash
git push -u origin feature/login-form

-u sets the upstream, so afterwards a plain git push is enough. On GitHub, GitLab or Bitbucket you'll now see a prompt to open a pull request (called a merge request on GitLab). This is where teammates review your code, leave comments and run automated tests before anything reaches main.

Step 5: Keep your branch up to date#

If main moves on while you work, bring those changes into your branch so you resolve conflicts early and in small pieces:

Bash
git switch main
git pull origin main
git switch feature/login-form
git merge main

Some teams prefer git rebase main instead of git merge main. It replays your commits on top of the latest main for a straight-line history. Both are valid, so follow your team's convention.

Never rebase shared history

Rebasing rewrites commits. Only rebase branches that nobody else has based work on. Otherwise you'll create painful conflicts for your teammates.

Resolving a merge conflict#

A conflict happens when two branches change the same lines. Git pauses and marks the file:

Text
<<<<<<< HEAD
const MAX_ATTEMPTS = 5;
=======
const MAX_ATTEMPTS = 3;
>>>>>>> main

The HEAD section is your branch's version and the bottom section comes from main. Edit the file to keep the correct version, delete the markers, then finish the merge:

Bash
git add src/config.js
git commit

Step 6: Merge and clean up#

Once the pull request is approved, merge it through your hosting platform. Then tidy up locally:

Bash
git switch main
git pull origin main
git branch -d feature/login-form

git branch -d refuses to delete a branch that hasn't been merged, so it's a safe default. If your team uses squash merges, Git may not recognise the branch as merged. Once you've confirmed the pull request was merged, git branch -D forces the deletion.

Handy commands to remember#

Bash
git branch                        # list local branches
git branch -a                     # include remote branches
git log --oneline --graph --all   # visualise history
git switch -                      # jump back to the previous branch
git stash                         # shelve uncommitted changes temporarily
git stash pop                     # bring them back

Recap#

  • A branch is a lightweight pointer, so create them freely.
  • One branch per feature or fix keeps main always deployable.
  • Commit in small steps, write clear messages and open a pull request for review.
  • Merge main into your branch regularly to avoid giant conflicts.
  • Delete branches after merging to keep your repository tidy.

Adopt this workflow even on solo projects. It builds habits that make joining a team effortless.