Commits

Git works around the idea of a commit. You can think of it like a “save file” for the entire project, but it includes more than just the content but also its location in the folder. So if you move a chapter from //src/chapters/ to //src/removed/, a commit is used to describe that change.

Each commit has a parent and child commit. These are basically just changes based on each other. So you make a change, commit it, make another change, commit it on top of the first one, make another change, and commit on the second, and just repeat until the project is done.

These can be seen with the git log command.

commit 9ca4e62bc6268f4d2f03380faef7412daecdb99c
Author: D. Moonfire <d.moonfire@moonfire.us>
Date:   Tue Jul 15 23:58:38 2025 -0500

    chore: bumping version

commit 2660c94962d6f707f3bcf24aaeda4da97880494c (knot)
Author: D. Moonfire <d.moonfire@moonfire.us>
Date:   Sat Jul 12 21:15:11 2025 -0500

    fix: edited 54-61

commit c919ef7157a8af1f4a94a860a3ba3cffd783fc74
Author: D. Moonfire <d.moonfire@moonfire.us>
Date:   Sat Jul 12 15:27:58 2025 -0500

    fix: edit 34-55

commit 7052e17dd72aab1e84bb98c6eec7f4f60f4ca4a0
Author: D. Moonfire <d.moonfire@moonfire.us>
Date:   Sat Jul 12 00:39:51 2025 -0500

    fix: editing 34-45

Some Git tools and forges will give a graphical representation, if you want.

A Git commit graph of Allegro

Message

Every commit has a message associated with it. This describes the changes made in the change. This is mandatory there is no real restrictions on the contents.

While you could easily just put “made a change”, putting more details into make it easier when you are trying to find what or why you made a change.

The general format of a Git commit message is:

  • A one-line summary of the change
  • A blank line
  • Optionally more details about the change

For my day-to-day writing, I use a simple format which is just a one-line summary, no blank lines, or additional details.

$ git log --oneline
chore: bumping version
fix: edited 54-61
fix: edit 34-55
fix: editing 34-45
feat: working on the 38-46 block
refactor: inserting a new forty
fix: working on thirty-eight and thirty-nine
chore: removing some binaries
fix: working on thirty-eight
chore: bumping version
chore: bumping version
fix: editing some chapters
feat: redrafted thirty-eight

There is no requirement that the message start with “chore:” or “feat:” nor does it have to be in lowercase. All of my stories are versioned automatically and I use conventional commits to automatically calculate the version number for the legal page based on my commits. That would be an “advanced” topic, but one that I find useful because I like having a clear indicator if I'm looking at an “old” version of the file (also also prevents the “final3-I-really-mean-it.pdf”).

Staging

Git has a concept of staging, which I found useful in rare situations but otherwise I completely ignore it when writing. This means to create a commit, you use the git commit -a command which means “commit everything you know about”.

git commit -a

If you don't provide a message with the -m "message", Git will open up an editor and ask for the message. If you include the message, it looks like this:

git commit -am "fix: edited 54-61"

Which, if you can't tell, looks almost exactly like the messages in the log.

There are two things that -a doesn't do is remove deleted files or add new ones. This includes renaming since a rename is just a “delete old file and create a new file”. This is one of the few cases where you need to stage a change to commit.

To include all everything, you use the git add -A . command.

$ git add -A .
$ git commit -a

Some of the UI clients will do this for you, but I'm used to typing it that I don't think about it. Likewise, you could also use Just and create a target in your //Justfile:

commit MESSAGE:
    git add -A .
    git commit -am $MESSAGE

Which would then allow you to type just commit "message" and it does all the right things.

Status

As you make changes to the project, the git status command will give you information of what changed since your last commit.

$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   src/git.md
	modified:   src/index.md
	modified:   src/markdown.md
	modified:   src/source-control.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	src/markup.md

no changes added to commit (use "git add" and/or "git commit -a")

When to Commit

Commits have two really useful aspects for writing.

One, it is a log of your writing process. If you don't commit, then Git can't manage it. If you do more frequent comments, you can track your progression which also allows you to go back more precisely.

Two, commits are the units of merging. If you do more frequent commits, you are less likely to have a conflict. This is useful when integrating feedback from readers and editors, but also saving your changes at the end of the day. When you push code up to the forge, the push happens at the commit level.

🛈 If it hasn't been committed, then Git can't manage it.

From the above log, you might be able to infer that I commit after I draft every chapter and also after a block of edits. I'll also do a commit after integrating feedback from the writing group, when doing a round of sweeping changes (such as renaming a character or looking for a specific echoed grammar pattern).

Commit like you are voting in Chicago, early and often.

Identification

For the most part, Git creates an automatic identifier for every commit. This is a long list of hex numbers like 9ca4e62bc6268f4d2f03380faef7412daecdb99c (from above) but Git will shorten it to the first eight characters (9ca4e62b). This identifier is cumbersome and rarely needed by an author, but it is possible to give it a more useful name by using branches or tags that point to a specific commit.

Comparison

Since a commit contains all the changes made from the previous one, it is possible to show the changes made from commit to commit with text files (but not binary files).

$ git diff
diff --git a/chapters/chapter-060.md b/chapters/chapter-060.md
index e69eddc..904f561 100644
--- a/chapters/chapter-060.md
+++ b/chapters/chapter-060.md
@@ -243,7 +243,7 @@ Hitting the ground with one shoulder, Linsan kicked back and flipped back onto h

 A sob rose up. "Brook?"

-Brook looked up, her hair smoking. She looked at them and then glared. "_Safe Adventures, Our Departed Loves_."
+Brook looked up, her hair smoking. She looked at them and then glared. "_Safe Adventures_. The song you just played."

 It was a ballad, a song with plenty of opportunity to build up power but there were desperately few places where the song could be used to attack.

While the Git GUIs will show different elements, the above from the CLi is called a “patch” format that shows lines that were changed with the old version starting with a - and the new version starting with a +. So, in the above example, I changed the sentence from:

Brook looked up, her hair smoking. She looked at them and then glared. “Safe Adventures, Our Departed Loves.”

... to:

Brook looked up, her hair smoking. She looked at them and then glared. “Safe Adventures. The song you just played.”