Branches

Git was also written around the idea of branches. You are (almost) always working on a branch with the default or first one being called main or master. The master was the original name, but it has racist connotations so there is a noticeable push to use main instead. Therefore, I will use main.

Branches also work like tags in that they point to a specific commit. However, the main difference is when you are on a branch and make a commit, the commit is added after the current one and the branch is moved to the new commit. That way, the branch name is always the latest commit of that branch.

The general purpose of a branch is to work on something to the side, make multiple commits, and then if you are happy, pull the results back into the main branch. At the same time, you can switch back to the main branch to make other changes and Git will “automatically” merge the result together when you put the two back together (with some caveats).

A commit graph showing multiple branches to make changes that are merged back into the master branch

The above screenshot is from an older project (hence the use of master) but it shows some of the cases where I used branches. The top one when when I gave my novel to a reader and it took me a few commits to integrate the suggested changes. While that was happening, I continued to edit and expand the novel from other feedback.

The bottom one (the yellow) was me working on two things at the same time. I was working on the project logo and cover page, which I thought would take a few commits but didn't. At the same time (really, a different computer), I was adding teasers and summaries to all the chapters. These were two very distinct things, but they were overlapping so I used branches to keep them separate until I was happy with the results.

Creating Branches

There are two ways to create a branch from the current commit. The first creates a branch but does not switch to the branch.

$ git branch new-branch-name

To create and switch to the branch, you use the checkout command with the -b to say “create a branch”.

$ git checkout -b new-branch-name

Current Branch

You can only work on a single branch at a time. The easiest way to see the current branch is the git branch command with no additional parameters.

$ git branch
  draft
* main
  sent-to-bob

To switch to the new branch, use the checkout command.

$ git checkout sent-to-bob
$ git branch
  draft
  main
* sent-to-bob

To remember the branch, I use a shell prompt called Starship on both Linux and Windows to tell me both the current version of the novel and it's branch.

dmoonfire@hunip:git-for-authors main*​​ ⇡v0.0.7
2025-08-09T15:45:00> git branch
  draft
* main
  sent-to-bob

dmoonfire@hunip:git-for-authors main*​​ ⇡v0.0.7
2025-08-09T15:45:04>

Forges and Remote Branches

All forges allow you to also push up branch to the remote repository, but that is not done automatically. However, this becomes really helpful because you can use the forge's web UI to look at the branches, see them on the commit graphs, or pull them down to a different machine.

When you first try to push a remote branch to the server, it will give you a message.

$ git checkout sent-to-bob
$ git push
fatal: The current branch sent-to-bob has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin sent-to-bob

To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.

This is because there is no remote branch already there and it doesn't know how to automatically create the branch (git config --global p ush.autoSetupRemote true). I don't like using that because I occasionally make typos, but to push a branch is just add the remote name and the branch. I also add the -u (--set-upstream) so it doesn't ask me again.

$ git push -u origin sent-to-bob
Enumerating objects: 22, done.
Counting objects: 100% (22/22), done.
Delta compression using up to 16 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (13/13), 1.62 KiB | 1.62 MiB/s, done.
Total 13 (delta 11), reused 0 (delta 0), pack-reused 0 (from 0)
remote:
remote: Create a new pull request for 'sent-to-bob':
remote:   https://src.mfgames.com/dmoonfire/some-novel/compare/main...sent-to-bob
remote:
To ssh://src.mfgames.com/dmoonfire/some-novel.git
 * [new branch]      sent-to-bob -> sent-to-bob
branch 'sent-to-bob' set up to track 'origin/sent-to-bob'.

After that, git push will work on that branch.

Readers and Editors

Probably the main reason I use branches is to handle readers and editors. I create a branch when I give the project over to a reader. When they finish days, weeks, or even months later, I can go back to the novel at the point I gave it to them, integrate changes without having to remember what I've done in the meantime, and then pull that branch into the main when I'm done. Pulling into main is when I'll get a list of conflicts where I changed the same paragraph in two different branches but that is a considerably smaller amount of work.

If I don't do that, I find myself looking at the notes they made on the page but the paragraph might have drastically changed in the meantime because I responded to another reader who responded faster and I may have already come up with the perfect answer or the new one might be better than what I did previously.

In terms of the CLI, it looks like this. When I sent a piece, I create the branch but don't switch to it.

$ git branch sent-to-bob

Then I can keep on making changes to main while I wait. Then, when Bob finally responds, I switch to their branch which changes the entire project back to the point I sent it to Bob.

$ git checkout sent-to-bob

Then I make changes and commit the results as I go through the feedback. Sometimes I can do it in a single commit but with some of the more detail-oriented feedback, it can take me days to finish integrating.

When I'm done, I pull the changes I've been making to the main branch into the sent-to-bob branch.

$ git merge main

If I made any changes to main that conflicted with the change in sent-to-bob, Git will then tell me I need to resolve them. I do that which can take another few commits to resolve. Then I do a quick reading/editing pass to smooth things off.

Once I'm ready and am happy with the results, I pull the change back into main.

$ git checkout main
$ git merge sent-to-bob

And now the main branch has everything I've done while waiting for Bob and also all the changes I made from Bob's feedback. I do a final push and then delete the branch (git push origin :sent-to-bob which basically means "push nothing to the remote repository to delete it).

$ git push
$ git push origin :sent-to-bob

As a note, git push is the same as git push origin $NAME_OF_BRANCH where $NAME_OF_BRANCH is the current branch.

Refactoring

The bulk of my writing has been commissioned work. That involves a lot of back and forth and sometimes the commissioner will ask me to rewrite a block of chapters because it doesn't work out for them. In those cases, I don't want to lose my old work until they are happy so I create a branch (rewrite-10-to-15), make the changes until they are happy, and then pull it back into main.

The reason I use a branch is because more than once, the commissioner has gone “wait, I've been thinking and what you wrote the first time was pretty good”. In those cases, I can just ignore the branch, or go back to the main branch and make more minor tweaks that works instead.

A lot of Git is about not losing your work. Branches really help in these situations.