Branches and Merging#
Learning Objectives#
Learn the concept of branches and how they are used to manage different lines of development
Master the command to create new branches and switch between them
Understand the purpose of tags and how to use them to mark specific points in the repository history
Practice making commits on different branches and understand how these affect branch history
Learn the process of merging branches, including fast-forward merged and handling diverged histories
Understand how to resolve conflicts that arise during a merge manually
We’ve seen the mechanisms for commits in some detail.
You should feel confident creating a chain of annotated commits (snapshots) and seeing that history with git log
.
We’ve also seen how we can use a SHA (secure hash algorithm) to get a copy of the files from any commit in the history.
The we’re going to look at an important topic in git, branching, and the closely related concept of merging.
Branches#
So far we have mostly been working with a single branch called main
.
In this case, main
is a reference which points to the most recent commit.
Any time a new commit is added to the end of this chain, main
is updated to this new commit.
Git is keeping track of main
in a file .git/refs/head/main
:
cat .git/refs/heads/main
Creating Branches#
We can create new branches, giving us the flexibility to work progressively on new features. This approach enables multiple people to work on the same repository, as we shall see later.
To create a branch called feature-branch
at the current commit, use
git branch feature-branch
Running git branch
by itself should now show both main
and feature-branch
.
If we change to our new branch
git switch feature-branch
then any new commits will advance the head of feature-branch
, leaving main
untouched.
To change back to the default branch, we can use
git switch main
Creating Commits on Branches#
If a branch is checked out (HEAD
points at the branch), the branch reference is updated when we add commits.
This is demonstrated in the following example.
If we consider two commits:
a1a
with tagv1
and branchmain
; and2f7
with tagv2
and currently checked-out branchfeature
:
HEAD
main feature
v1 v2
| |
a1a -> 2f7
The HEAD
is following feature
and currently at 2f7
.
If we create a new commit now (say 83c
):
83c
will be a child of2f7
,the
HEAD
andfeature
references will both be updated to83c
,but the tag
v2
(andv1
and the branchmain
) be remain unchanged.
main HEAD
v1 v2 feature
| | |
a1a -> 2f7 -> 83c
If we were to move to the main
branch (with git switch main
) and add a new commit, our history would diverge.
This happens frequently when collaborating on a repository.
Merging#
Returning to branches, a typical way of working on code is to use a branch (appropriately named) to develop a single feature. Once we’re happy that the feature meets our requirements, we move the work back on to the main branch. We will now look at how to combine changes from different branches, a process known as merging.
Simple Merge - Fast-Forward#
The simplest case is where main
has not been updated and we want to just apply the changes from our feature branch.
Here the reference to main
can simple be moved to the tip of feature-branch
(referred to as a fast-forward).
One approach (which overlaps with the following methods) is to change to the main branch
git switch main
then fast-forward with
git merge feature-branch
Merging with Diverged Histories#
In the case that changes have been made to main
, the same syntax will combine changes from both branches.
git merge feature-branch
The merge will conclude automatically if the changes were on different lines. If the changes overlapped between the two branches, we must manually resolve the conflicts.
Exercise#
Practice making branches, adding commits to each branch then merging the branches. Try making changes in different files, in the same file but different lines, and in the same file and the same lines.
Remember to check git status
often!