Branching & Merging
Branches are Git's superpower. This page covers creating and switching branches, getting changes reviewed, and resolving the conflicts that come with teamwork.
Branching
A branch is your own private workspace. When you start on a new feature or bug fix, you create a branch so your changes do not affect the rest of the team until you are ready.
Think of branches like separate copies of the project — except they are very cheap to create and Git is smart enough to merge them back together later.
# Create a new branch and switch to it
git switch -c feature/user-login
# Switch to an existing branch
git switch main
# List your local branches
git branch
# List ALL branches, including ones that only exist on the remote
git branch -a
# Switch onto a branch that exists on the remote but not yet locally
# (Git auto-creates a local copy that tracks the remote one)
git switch develop
# Delete a branch (only after it has been merged)
git branch -d feature/user-login
main). If your team's active work lives on develop or a feature branch, run git branch -a to see it, then git switch develop to start from the right place.feature/user-login or fix/null-error keep things organised. Use a short description of what you are working on.main. Always work on a branch and merge it through a Merge Request.See the side-by-side comparison →
Detached HEAD — What It Means
Normally HEAD points to a branch name, and the branch moves forward as you commit. A detached HEAD means HEAD is pointing directly to a commit hash instead of a branch — any commits you make won't belong to any branch and will be lost when you switch away.
It happens when you run git checkout <commit-hash> or git checkout <tag> to inspect old code. Git warns you:
HEAD detached at a1b2c3d
How to get out safely:
# Just go back to a branch (discard any commits made in detached state)
git switch main
# Or, if you made commits you want to keep — save them to a new branch first
git switch -c my-exploration-branch
Merge Requests (GitLab) / Pull Requests (GitHub)
When your feature branch is ready, you open a Merge Request (MR) — called a Pull Request (PR) on GitHub — on your Git host. This is how your code gets reviewed by a teammate and merged into the main branch.
How to open a Merge Request:
- Push your branch:
git push -u origin feature/your-branch - Go to your project on the host — a banner will appear offering to open the merge/pull request. Click it.
- Fill in a clear title and a short description of what changed and why
- Set the target branch to
main(ordevelopif your team uses GitFlow) - Assign a reviewer from your team
- Tick Delete source branch when merge request is accepted — keeps the repo tidy
- Click Create Merge Request
Your reviewer will read the code, leave comments if needed, and approve it. Once approved, click Merge.
Closes #42 (replace 42 with the issue number) and the host will close the issue when the MR is merged.Closes #42 in the PR description auto-closes a linked issue the same way.Resolving Conflicts
A conflict happens when two people edit the same lines in the same file. Git cannot decide which version to keep, so it asks you to choose.
When a conflict happens, the file will contain markers like this:
<<<<<<< HEAD (your version)
public string GetName() => "Alice";
=======
public string GetName() => "Bob";
>>>>>>> feature/rename-user (their version)
Everything between <<<<<<< and ======= is your version. Everything between ======= and >>>>>>> is theirs. Edit the file to keep what is correct, then remove all the markers.
Steps to fix a conflict:
- Open the conflicted file in your editor
- Decide what the file should look like (often a mix of both versions)
- Delete the
<<<<<<<,=======, and>>>>>>>lines - Save the file
- Stage and commit:
git add src/main.py
git commit -m "Resolve merge conflict in GetName method"
Visual Studio users: Right-click the conflicted file in Solution Explorer → Resolve Conflicts to open the built-in merge tool.
Fast-forward vs Non-fast-forward Merges
When you merge a branch, Git uses a fast-forward if the target branch hasn't moved since you branched off — it just slides the pointer forward, no merge commit needed. If both sides have new commits, Git creates a merge commit with two parents.
Merge Requests / Pull Requests use --no-ff by default, so merging always creates a merge commit — making it clear exactly when each feature landed in main.
Most merges here happen by clicking Merge on an MR/PR, but the same thing happens locally with:
git switch main
git merge feature/your-branch # fast-forward if possible, merge commit if not
git merge --no-ff feature/your-branch # always create a merge commit
git rebase (see Staying in Sync) to bring main into your feature branch — it keeps history linear. Save plain git merge for the one-way trip of landing a finished branch into main.