Git and GitHubgit 2.54 · GitHub · macOS, Linux or Windows
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson →

Merging a branch

git merge brings the commits of another branch into the branch you are standing on, and leaves the other branch untouched.

Last updated: 12 Oct, 2026 · git 2.54

An experiment that worked has to come back. Merging is how: you stand on the branch that should receive the work, name the branch that has it, and Git joins the two lines of history. There are two ways it can end, and the output tells you which one happened.

Merging a branch into main with git merge · from the Git and GitHub series · 9:38 to 10:27

Syntax: switch to the receiving branch first, then name the branch to bring in.

bash
git switch main            # the branch that receives the work
git merge chunk-800        # the branch whose commits come in
git merge --no-edit <name> # keep Git's prepared message, open no editor
The two ways a merge can end. On the left, a fast-forward: main had no commits of its own, so Git moves the name main forward to the branch's newest commit and the history stays a straight line. On the right, a merge commit: both branches had new commits, so Git makes one more commit whose two parents are the newest commit of each branch, and the two lines join.

A merge that moves the name forward

When the branch you are on has made no commits since the split, the work in front of it is a straight continuation. The repository below is a throwaway one in a temporary folder, and every example on this page starts from it.

ExampleThe throwaway repository, with one commit on main
mkdir ask-docs && cd ask-docs && git init -q -b main
export GIT_AUTHOR_DATE="2026-10-12T10:00:00+00:00" GIT_COMMITTER_DATE="2026-10-12T10:00:00+00:00"
printf 'You are a support assistant.\n' > prompt.txt
printf 'chunk_size = 500\n' > loader.py
git add . && git commit -q -m "Add the prompt and the loader"
git log --oneline

One commit, one branch. The experiment branches off here, so this commit is the point the two lines of history have in common.

A branch one commit ahead of main

ExampleThe experiment has a commit; main has none of its own
git switch -q -c shorter-prompt
printf 'Answer in two sentences.\n' > prompt.txt
git commit -q -am "Ask for two sentence answers"
git switch main
git branch -v

git branch -v shows the experiment on a newer commit and main still on the first one. main has nothing of its own in the way, which is the condition for what happens next.

Running the merge

ExampleA fast-forward merge
git merge shorter-prompt
git log --oneline --graph --decorate
  • Updating 54f17c3..b0f4528 names the commit the branch moved from and the one it moved to.
  • Fast-forward is Git saying no merge commit was needed.
  • prompt.txt | 2 +- and the summary under it count what changed, the same as a commit would print.
  • The graph is one straight line, and (HEAD -> main, shorter-prompt) shows both names now on the newest commit.

A merge that makes a commit

When both branches have commits of their own, there is nothing to fast-forward to. Git joins them with a new commit that has two parents, and that commit is the merge.

ExampleBoth branches with a commit of their own
git switch -q -c chunk-800
printf 'chunk_size = 800\n' > loader.py
git commit -q -am "Raise the chunk size to 800"
git switch -q main
printf 'You are a support assistant. Answer from the documents.\n' > prompt.txt
git commit -q -am "Tell the model to answer from the documents"
git branch -v

Both names are on different commits, and neither is reachable from the other. There is no name to move forward, so Git has to join the two lines instead.

Joining the two lines

ExampleA merge commit, and the graph that comes with it
git merge --no-edit chunk-800
git log --oneline --graph --decorate
  • Merge made by the 'ort' strategy names the method Git used to put the two sides together. It is the default and you do not have to choose it.
  • The graph forks and joins. The two lines leave the first commit and meet again at the merge commit at the top.
  • --no-edit keeps the message Git prepared, Merge branch 'chunk-800'. Without it, Git opens your editor with that message so you can add a line about why the experiment was kept.

What makes a merge commit a merge commit

ExampleThe two parents of the commit Git made
git log -1 --format='%h has parents %p'

Every other commit has one parent. This one has two, one from each branch, and that is what records in the history that two lines came back together here.

Who the merge commit belongs to

A merge commit is a commit like any other and carries the name and email from your configuration:

ini
[user]
	name = Reader
	email = reader@example.com

That matters when a team reads the history later: the merge is attributed to whoever ran git merge, not to the person who wrote the commits that came in.

Tidying up after a merge

A merged branch has nothing left in it that main does not have, so the name can go. Keeping dead experiment names makes git branch useless within a month.

ExampleDeleting a branch that has been merged
git branch -d chunk-800
git branch
  • Deleted branch chunk-800 (was ...) removes the name and prints the commit it pointed at, in case you want it back.
  • git branch now lists main on its own. On an unmerged branch Git refuses and asks for -D, which does lose the commits.

The commits the deleted name was pointing at

ExampleThe work is still in the history
git log --oneline

The commit from the experiment is still in the log, because deleting a branch deletes a name and not commits. The work came into main with the merge, and the label had nothing left to say.

Fast-forward compared with a merge commit

Fast-forwardMerge commit
Happens whenthe receiving branch has no new commitsboth branches have new commits
New commit madenoyes, with two parents
The history lookslike one straight linelike a fork that joins
Messagenone to writeGit prepares one, you can edit it
Force the other onegit merge --no-ff makes a commit anywaygit merge --ff-only refuses unless it can fast-forward

Teams argue about which is tidier. A fast-forward keeps the log readable; a merge commit records that a branch existed and when it came in. --no-ff is what projects use when they want every feature branch visible in the history.

Where you merge

  • An experiment that worked. Switch to main, merge the branch, delete the name.
  • Keeping a long branch up to date. Merge main into your branch now and then, so the differences stay small and the final merge is easy.
  • Accepting someone's work. A pull request on GitHub runs this same merge on their server, which the GitHub part covers.
Watch out. The merge runs into the branch you are standing on. git merge main while you are on your experiment brings main into the experiment, which is the opposite of what you probably wanted. Run git branch --show-current first, and read the first line of git log --oneline --graph after.
Try it yourself
  • Run the fast-forward example again with git merge --no-ff shorter-prompt and compare the two graphs.
  • Try git branch -d on a branch whose commits are not merged. Read what Git says and decide whether -D is what you want.
  • After a merge commit, run git show HEAD and notice that a merge commit's own diff is usually empty.

Little by little, you're building something great.