Branches and merges

Reading · 6 min · Module 5, lesson 3 of 636 min left in this module

Module 5 · Git essentialsLesson 3 of 6

Goal: Branch, merge, and tell a fast-forward from a merge commit and a conflict.

3:43 · captions and chapters · narrated with an AI-generated voice
Transcript

Narration uses an AI-generated voice.

[00:00] Where we're going

By the end of this video, you'll know the three things a merge can do. A fast-forward. A merge commit. And a conflict, where Git asks you to decide.

[00:10] Make a branch

A branch is just a name that points at a commit. Here, main points at the latest one. Make a branch, and you get a second name on that same commit. Nothing is copied. Commit on the branch, and its name moves forward with you. Main stays where it was.

Here it is in a real repository. One command creates the branch and moves you onto it. Then you edit, add and commit as usual. This commit adds a file called b. Now switch back to main. The file b is gone, because your files change to match the branch you're on.

[00:48] Fast-forward

To merge, go to the branch you're bringing work into, and name the branch to bring in. What happens next depends on main. Here, nothing happened on main while you worked. So Git just slides the main name forward, to your last commit. That's a fast-forward. No new commit is made.

[01:08] Merge commit

Now suppose main moves on too. You make another branch, and commit a file called c on it. Meanwhile, main gets its own commit, which edits a. Now both sides have commits the other lacks, so main can't just slide forward. Git combines them, and records a new commit with two parents, one from each side. Here we accept its default message.

[01:35] Read a merge

To see it, ask for the log as a graph, and read it from the bottom up. The lines split where the branch started. Each side has its own commit. And they join again at the merge commit. Below that, the fast-forward left a single straight line.

[01:54] A conflict

Git merges changes to different files, or different parts of a file, on its own. But if both branches changed the same lines, it can't know which you want. So it stops. Here, two branches both change line one of greeting dot js. Merge them, and Git reports a conflict. That isn't an error, and nothing is lost. Git has written both versions into the file, between markers, and waits for you to choose.

[02:24] Resolve it

So you choose. Keep one side, or combine them, and delete the markers. Then add the file, to tell Git the conflict is resolved, and commit. That makes the merge commit, just like before. The next lesson walks you through one yourself.

[02:42] Keep branches short

One habit keeps all of this easy. The longer a branch lives, the further main moves on, and the more lines both sides touch. A branch merged the same day rarely conflicts. One left for a month almost always does. So keep branches small, and merge them often.

[03:04] Recap

To recap. If main hasn't moved, the merge is a fast-forward, and the name just slides along. If both sides moved, Git makes a merge commit with two parents. And if both changed the same lines, it stops, and you choose.

Here's a question. You branch from main, make two commits, and nobody touches main. What does the merge do? A fast-forward. Main just moves to your last commit. Next, you'll branch, commit and resolve a conflict yourself. I'll see you there.

Key idea

A branch is a name that points at a commit and moves forward as you commit on it. You branch to work on one change without disturbing main, then merge to bring that work back. Most merges are automatic; a conflict is Git asking you to decide.

Make a branch

git switch -c add-due-dates   # create a branch and move onto it
# edit, git add, git commit as usual
git switch main               # back to main; your files change to match it

Branches are cheap: making one copies nothing. Use one per change, and give it a name that says what the change is.

Merge it back

From the branch you want to bring work into, name the branch to bring in:

git switch main
git merge add-due-dates

What Git does next depends on what happened to main while you worked.

Nothing happened on main: a fast-forward. Your branch is just main plus some commits, so Git slides the main name forward to your last commit. No new commit is made.

Updating 24acd58..ec4c514
Fast-forward

Main moved on too: a merge commit. Both sides have commits the other lacks. Git combines them and records a new commit with two parents, one from each side. It opens your editor for the message; git merge --no-edit add-due-dates accepts the default message instead. Landed in Vim? Type :wq and press Enter.

Merge made by the 'ort' strategy.

Read a merge

git log --oneline --graph
*   1ad8e56 Merge branch 'add-c'
|\
| * fc8cd16 Add c
* | 39011c8 Edit a
|/
* ec4c514 Add b

Read it bottom up. The lines split where the branch started, each side has its own commits, and they join at the merge commit. A fast-forward leaves a single straight line.

When both sides change the same lines

Git merges changes to different files, or different parts of one file, on its own. If both branches changed the same lines, it can't know which you want, so it stops:

CONFLICT (content): Merge conflict in greeting.js
Automatic merge failed; fix conflicts and then commit the result.

A conflict isn't an error, and nothing is lost. Git has written both versions into the file, between markers, and waits for you to choose. The next lesson walks through one.

Keep branches short

The longer a branch lives, the further main moves away from it, and the more lines both sides touch. A branch merged the same day rarely conflicts; one left for a month almost always does. Small branches, merged often, keep merges boring.

Rebase, and what happens to a branch after a merge

Rebase is the other way to combine branches: it replays your commits on top of the latest main, so the history stays one straight line. It rewrites your commits, so only rebase a branch nobody else has built on. Module 7 shows how hosted repositories offer merge, squash or rebase as a button.

After a merge the branch has done its job. git branch -d add-due-dates deletes the name; the commits stay in main's history.

Check yourself

You branch from main, make two commits, and nobody touches main. What does git merge do?
Two branches both edit line 1 of greeting.js, differently. What happens when you merge?