Module 2: Git from Scratch for Automators

3. Staging and commits: photos of your workflow

Description

By the end of this lesson you will be able to take your workflow's first photo and the ones that follow: you'll know exactly what a commit is —an immutable photo of your project, with a note, author, date, and a unique ID— you'll understand why saving in Git is two steps and not one (the staging area that showed up in lesson 2), and you'll handle the four commands of the daily cycle: git add to stage, git commit to save, git status to know where you are, and git log to read the history. You'll also learn to write good commit notes for a workflow, the kind that on Cumbre's bad Tuesday make the difference between knowing what happened and guessing.

This matters because the commit is the unit of everything. Every line of that git log you saw in lesson 1 is a commit; every diff you're going to read in lesson 4 compares two commits; every branch in lesson 5 is a line of commits; every rollback in lesson 7 goes back to a commit. If you master how to make and read a commit, you master Git's backbone. Everything else is a variation on this.

Connection to the module: in lesson 2 you left your order-triage.json as an "untracked" file —Git could see it but wasn't keeping its history. This lesson resolves that loose end: you're going to bring it into the history with your first commit, and then you're going to make a second commit on top of a change, to see the whole cycle repeat. With two commits you already have a real history, which is exactly what lesson 4 needs to be able to compare. Everything that follows in the module rests on knowing how to make clean commits, so here too we go slowly.

What a commit actually is

Let's define it well, because it's the word you're going to use most from here on.

A commit is a photo of your entire project at a given moment, saved permanently in the history. "Photo" is the right word and it's worth taking it seriously: it doesn't just save what changed, it saves the project's complete state at that instant, so you can go back to exactly that when you want. Every commit carries four things attached:

  • The content: the state of your files at that moment.
  • A note (the message): a sentence you write explaining what changed and why. It's the photo's label.
  • The author and the date: who took it and when. Git fills these in on its own, using the user.name and user.email you configured in lesson 2.
  • A unique ID (the hash): a code identifying that photo and no other, like c08b4a2. Git generates it; you don't choose it.

The key word, the one worth underlining, is immutable. Once you take the photo, that photo never changes. You can take new photos on top of it, you can go back to an old one, but Tuesday's 9:12 photo is forever Tuesday's 9:12 photo. That permanence is the foundation of trust in Git: when git log tells you a workflow looked a certain way at a certain commit, there's no possible ambiguity. The photo is the photo.

Think of it like a video game's save system, the kind where you can create a save point before a hard part. Each point saves the game's complete state —your position, your health, your inventory— with its name and time. If something goes wrong later, you load an earlier point and go back to exactly how everything was. A commit is a save point for your workflow. And like in the video game, the discipline of saving at the right moments, with clear names, is what saves you when things get hard.

Why saving is two steps: the staging area

Here comes what surprises people coming from other tools the most. In Dropbox or Google Docs, saving is a single act: you hit save and you're done. In Git, taking a photo is two steps: first you stage what's going into the photo (git add), and then you take the photo (git commit). That intermediate step is the staging area you met in lesson 2, and a lot of people find it a pointless detour until they understand what it's for.

Go back to the group-photo image. At a party there are twenty people moving around the room —that's your working tree, everything you changed. When you're about to take a photo, the whole room doesn't show up in the frame: you choose who to call over. "You five, the birthday people, stand here." That selection is git add: you're putting exactly what you want to show up into the frame. And only once the right people are in place do you press the shutter: that's git commit.

Why would Git let you choose instead of always photographing everything? Because in a real project, your changes almost never all tell the same story. Imagine that in order-triage you adjusted the CRM's timeout and, while you were at it, also renamed a node so it read better. Those are two independent changes. The staging area lets you make two separate photos —one "Widen CRM lookup timeout" and another "Rename classifier node for clarity"— even though both changes sit in your folder at the same time. Each photo tells a single story, and a history of photos each telling a single story is a history that reads well. One where every photo mixes five different changes is a useless history.

At first this feels like an extra step, and that's normal. Over time it becomes an advantage you won't want to let go of: it's the difference between an organized album and a drawer of jumbled photos. For now, hold on to the mechanics: stage, then save, add then commit.

The daily cycle: status, add, commit, log

These four commands are 80% of your work with Git. You're going to run them dozens of times a day. Let's see them in action on order-triage, from start to finish.

Worked example: your first commit

Stand inside cumbre-automations (remember lesson 2's reflex: run pwd to confirm) with your order-triage.json in it.

Step 1 — Ask for the status. You always start by looking at where you are:

git status

What to expect. The same report from the end of lesson 2: your file shows up as "untracked."

On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	order-triage.json

nothing added to commit but untracked files present (use "git add" to track)

Notice Git suggests, in parentheses, the exact next command: git add. Let's follow it.

Step 2 — Stage the file (put it in the frame).

git add order-triage.json

What to expect. The silence of success: nothing. But underneath, something important happened, and git status confirms it:

git status
On branch main

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   order-triage.json

Read the change carefully, because it's the visual signal confirming that staging worked. Before it said "Untracked files"; now it says "Changes to be committed," and your file shows up marked as "new file." Translated: order-triage.json is already in the frame, waiting for the shutter. If you could see your terminal's colors, you'd notice it went from red (unstaged) to green (staged). That state change is your confirmation.

Step 3 — Take the photo (make the commit).

git commit -m "Add order-triage workflow"

Let's break the command down: git commit is "take the photo"; -m means "the message goes right here" (from message); and between quotes is the photo's note, in English like all the ecosystem's code and identifiers. Without -m, Git would open a text editor for you to write the note there —and that's where people who left Vim as their editor get stuck not knowing how to exit; with -m, you write the note on the same line and avoid that window.

What to expect. Now Git does answer, with a summary of the photo it just took:

[main (root-commit) c08b4a2] Add order-triage workflow
 1 file changed, 128 insertions(+)
 create mode 100644 order-triage.json

Read it piece by piece:

  • [main ...]: the photo was saved on the main branch.
  • (root-commit): this is the repository's first commit, the history's root. This label only shows up once in a repo's life, on the first photo.
  • c08b4a2: this photo's unique ID. Yours is going to be different —Git calculates it from the content, the date, and the author, so it's impossible for it to match mine.
  • 1 file changed, 128 insertions(+): one file went in, with 128 new lines. The line count depends on how big your order-triage.json is; yours will be different.

You did it: your workflow has its first photo in the history. That file that was "untracked" in lesson 2 now lives in Git's history, forever, with your name and today's date.

Step 4 — Confirm the status and read the history.

git status
On branch main
nothing to commit, working tree clean

"working tree clean" is one of Git's most reassuring phrases: it means there's no loose change, that everything in your folder is already saved in the history. When git status says this, you're "caught up": you can shut down the machine without losing anything.

Now, the command to read the photos you've taken:

git log

What to expect. The complete history, with all the details of each commit:

commit c08b4a2f1e9d3b7a5c2081f4e6d9a0b3c7e12345 (HEAD -> main)
Author: Ana Torres <ana.torres@cumbre.example>
Date:   Tue Jul 14 09:12:33 2026 -0600

    Add order-triage workflow

Here you see the full photo: the long ID (those seven characters from the summary, c08b4a2, are the beginning of this long code), the author with the name and email you configured, the exact date and time, and your note. There's a new label worth understanding: HEAD -> main. HEAD is a simple concept with an intimidating name: it's, literally, "where you're standing right now in the history." It's the arrow that says "I'm here." Right now HEAD points to main, and main points to your single commit. When in lesson 5 you jump between branches, what moves is HEAD. For now, read it as "I'm standing on this photo."

To exit git log when the list is long and fills the whole screen, press the q key (for quit). It's a classic stumble to get stuck there not knowing how to get back to the command line; the key is q.

The second commit: the cycle repeats

A single commit isn't a history; it's a photo. Let's go for the second one, to see the whole cycle over a real change.

Step 5 — Change something in the workflow. In n8n, open order-triage, go into the HTTP Request node that queries the CRM, and raise its wait time —the timeout— from 5 to 15 seconds, because the CRM sometimes takes a while. Save, export the workflow again, and replace your order-triage.json with the new version. (It doesn't matter if you can't reproduce the exact change on your instance; what matters is that the file changes.)

Step 6 — See what Git sees.

git status

What to expect. Now the file shows up as modified, not new:

On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working tree)
	modified:   order-triage.json

no changes added to commit but "modified:" present (use "git add" to track)

"Changes not staged for commit" and "modified" tell you Git noticed the file changed relative to the last photo, but that change isn't in the frame yet. Notice the second suggestion in parentheses: git restore <file> would discard the change and put the file back to how it was in the last commit. It's your safety net —if you regret a change before saving it, that's the way out— but use it with care, because discarding is discarding.

Step 7 — Stage, review, and save.

git add order-triage.json
git status

After the add, git status goes back to saying "Changes to be committed" with your file in green, marked this time as modified instead of new file. Now the photo:

git commit -m "Widen CRM lookup timeout to 15 seconds"

What to expect:

[main 3e5d720] Widen CRM lookup timeout to 15 seconds
 1 file changed, 1 insertion(+), 1 deletion(-)

Notice the differences from the first commit. It no longer says root-commit —it's not the first photo. And the change summary is now 1 insertion(+), 1 deletion(-): one line changed, which in Git's counting shows up as one old line removed and one new one added. (In a real n8n JSON, a timeout change can touch more than one line; the exact count depends on your file. Lesson 4 explains why these numbers are sometimes bigger than you'd expect.)

Step 8 — Read the summarized history. Now that you have two photos, it's worth seeing the compact view:

git log --oneline

What to expect. One line per commit, with the short ID and the note:

3e5d720 (HEAD -> main) Widen CRM lookup timeout to 15 seconds
c08b4a2 Add order-triage workflow

That --oneline is how you're going to read the history 90% of the time: fast, panoramic, one photo per line. It's exactly the format of the block you saw in lesson 1. And now you know how to produce it: every line is a git add followed by a git commit with a good note. It reads from top (newest) to bottom (oldest), and HEAD -> main marks where you're standing.

How to write a good commit note

The commands are the easy part. The skill that really separates a professional history from a useless one is writing good commit notes. It's worth learning it well, because a history with bad notes is almost as useless as having no history.

Remember Cumbre's bad Tuesday from lesson 1. When the wholesale orders stopped routing, what saved the team with Git was being able to read git log and understand what had happened that day. That only works if the notes say something. Compare these two histories of the same work:

A useless history:

a91c3f8 changes
7b2e105 fix
3e5d720 update
c08b4a2 wip

A history that works:

a91c3f8 Add wholesale category to the order classifier
7b2e105 Point CRM lookup at the staging URL
3e5d720 Widen CRM lookup timeout to 15 seconds
c08b4a2 Add order-triage workflow

Both represent the same work. In the first one, when something breaks, you have no idea what each commit touches —"fix" of what, "update" of what. In the second, every note tells you exactly what changed, and you can go straight to the suspicious commit. The difference between the two is ten seconds of thought at save time. Ten seconds that pay off multiplied on incident day.

There's a simple formula, one that's the whole industry's convention, and you're going to apply it always:

1. Start with an imperative verb, in English, describing what the change does. Add, Fix, Update, Remove, Rename, Widen. The note completes an: "If I apply this commit, it's going to..." → "...Add the wholesale category." Add wholesale category to the order classifier, not added or adding. It's a convention, and conventions make reading easier because everyone writes the same way.

2. Be specific about the workflow. Not Fix bug, but Fix CRM lookup returning empty for wholesale customers. Not Update node, but Rename classifier node for clarity. The note has to answer, without opening the diff, "which part of which workflow did this touch?"

3. Keep the first line short —a common rule is not to go past about fifty characters. If you need to explain why in more detail (not just what), you can leave a blank line and write a paragraph below it. That's what you do the commit without -m for, letting Git open the editor; the first line is the title and the rest is the body. For a workflow's lifecycle, most of the time a good first line is enough.

A practical guide to the content: the note describes the what and, when it isn't obvious, the why; the diff already shows the how. Widen CRM lookup timeout to 15 seconds says the what; if the reason weren't obvious, a body could add "the CRM intermittently takes up to 12s under load." Never waste the note describing the mechanics line by line: that's what lesson 4's git diff is for.

What NOT to photograph: a first look at .gitignore

There's a side of the staging area worth knowing from day one: just as you choose what goes into the photo, sometimes you need to tell Git that certain files must never go in. That's what a special file called .gitignore is for.

A .gitignore is a text file, living at your repository's root, where you list the files and folders Git should completely ignore: it won't even show them as "untracked," and it won't let you add them by accident. It's the list of "this never shows up in any photo."

Why would you want to ignore something? For two main reasons in the world of workflows. First, files that generate themselves and add no history: temporary logs, caches, system folders your editor or operating system creates (macOS's classic .DS_Store). Second, and much more important, secrets: API keys, tokens, passwords, credential files. A workflow might need a CRM key to run, but that key must never enter Git's history —if it does, it stays recorded forever and anyone with access to the repository can see it.

A basic .gitignore for cumbre-automations might look like this:

# Operating system and editor files
.DS_Store
.vscode/

# Secrets: never version credentials
.env
credentials.json
*.key

Each line is a pattern of what gets ignored. .env ignores a file with that name; *.key ignores any file ending in .key (the asterisk means "whatever"); .vscode/ ignores an entire folder.

I'll stop here on purpose, because properly separating credentials from workflows is a topic that deserves its own place, and it has one: it's a whole lesson in Module 3. For now hold on to the idea and the habit: before your first git add, think about whether there's any secret nearby that shouldn't enter the history, and if there is, create a .gitignore that excludes it. It's one of those precautions that cost a minute and avoid a serious problem. Module 3 formalizes it; this early mention is so you don't make the mistake right now, in your first commits.

Common mistakes

Doing git add . blindly (practical). What happens: instead of adding the file by name, git add . gets used (the dot means "everything in this folder") out of habit or speed, and files that shouldn't be there sneak into the photo —a temporary log, an editor folder, or worse, a credentials file. Why it happens: git add . is convenient and a lot of tutorials use it without warning about the risk. How to spot it: after a git add ., run git status and read the whole "Changes to be committed" list before committing; if something you don't recognize or didn't want shows up, this is it. How to fix it: at first, add files by name (git add order-triage.json), which forces you to know what you're saving. When you do use git add ., have a .gitignore protecting the secrets first, and always check git status before shooting. The staging area exists precisely to review; don't skip the review.

Editing and thinking it's already saved, without committing (practical). What happens: you change order-triage.json, do git add, and consider the work saved —but you never ran git commit. The change stayed in the staging area, not in the history. Why it happens: the two steps are easy to confuse at first; "add" sounds like you already saved. How to spot it: git status tells you plainly: if there's something under "Changes to be committed" and git log doesn't show that change, it's staged but not saved. How to fix it: remember the photo is taken with commit, not with add. add puts people in the frame; commit presses the shutter. There's no photo until the shutter fires.

Vague commit notes (conceptual). What happens: commits get saved with messages like fix, changes, wip, or update, and months later —or on incident day— the history says nothing useful. Why it happens: at save time, the change is fresh in your head and the note feels unnecessary; the problem is that in three weeks you're not going to remember what "fix" was. How to spot it: read your own git log --oneline and ask yourself if, without opening each commit, you know what it touched. If not, your notes are vague. How to fix it: apply the formula —imperative verb, in English, specific about the workflow. Fix CRM lookup returning empty for wholesale customers costs twenty extra seconds compared to fix and is worth its weight in gold the day something breaks. The commit is a message to your future self and to your team; write it thinking of them.

Cramming too many changes into a single commit (conceptual). What happens: you work all afternoon touching five different things in the workflow and at the end save everything in one commit called Update order-triage. Why it happens: it's more comfortable to save everything together at the end than to take photos along the way. How to spot it: if your commit note needs the word "and" several times to describe what you did ("added the category and changed the timeout and renamed a node"), it's several commits disguised as one. How to fix it: use the staging area to separate them —git add only one change's worth, commit it, then the next one— or adopt the habit of saving more often, every time you finish one thing. One commit per idea. The day you need to revert only one of those changes (lesson 7), you're going to be glad you didn't pile them up.

Committing a secret without noticing (practical and serious). What happens: a credentials file or a .env with an API key was in the folder, snuck into a git add ., and got saved into the history. Why it happens: secrets often live right next to workflows and are easy to include carelessly. How to spot it: review the "Changes to be committed" list before every commit looking for names like .env, credentials, key, token, password. How to fix it: the best fix is preventing it with a .gitignore from the first commit, as we saw. If it already snuck in, getting it out of the history isn't as simple as deleting the file —once photographed, it stays in the earlier photos— and it's a topic Module 3 handles seriously. The golden rule: when in doubt, don't commit until you're sure there are no secrets in the frame.

Exercises

Exercise 1 — The complete cycle, from memory. Without looking back at the worked example, write in order the four commands you'd use to: check your repository's status, stage a modified file called order-triage.json, save it with the note "Fix classifier ignoring the priority channel," and then confirm the commit made it into the history. Then actually run them (first making any change to the file) and verify they work.

See solution
git status
git add order-triage.json
git commit -m "Fix classifier ignoring the priority channel"
git log --oneline

The initial git status isn't required for it to work, but it's the right habit: always look before you act. The final git log --oneline confirms your commit shows up at the very top, with HEAD -> main next to it.

Why it works: this is the cycle you're going to repeat thousands of times. Internalizing the order —look, stage, save, confirm— makes Git stop feeling like a list of loose commands and turns it into a rhythm. The note also follows the formula: imperative verb in English (Fix) and specific about the workflow (what it fixes and where).

Exercise 2 — Judge the notes. For each of these commit notes, say whether it's good or bad and, if bad, rewrite it. The context is that in each case the order-triage workflow was touched.

(a) update (b) Add retry logic to the CRM lookup node (c) arreglé el bug (d) Rename "Classify" node to "Classify Order" for clarity (e) changes to webhook and classifier and http node

See solution

(a) Bad. Doesn't say what got updated. Rewrite, depending on what changed: Update classifier categories to include wholesale.

(b) Good. Imperative verb in English (Add), specific about which node and what got added to it. Nothing to change.

(c) Bad, for two reasons: it's vague ("the bug," which one?) and it's not written in English, when the ecosystem's convention is to write notes in English like all the code. Rewrite: Fix CRM lookup timing out on large orders.

(d) Good. Imperative verb, specific, and even explains the why (for clarity). A model to follow.

(e) Bad. The word "and" showing up three times is the giveaway: these are three different changes piled into one commit. The fix isn't rewriting the note, it's having made three commits: Update webhook path to /order-triage, Add wholesale category to the classifier, Widen CRM lookup timeout to 15 seconds.

Why it works: judging other people's notes sharpens the judgment for writing your own. The three signs of a bad note —vagueness, the wrong language, and several changes crammed into one— are the ones you're going to learn to hunt in your own history before it gets messy.

Exercise 3 — Predict the state. Starting from a repository with a clean working tree (nothing to commit, working tree clean), predict what git status will report after each of these three sequences, separately. Then verify it.

(a) You modify order-triage.json and do nothing else. (b) You modify order-triage.json and run git add order-triage.json. (c) You modify order-triage.json, run git add order-triage.json, and then modify order-triage.json again without running git add a second time.

See solution

(a) git status reports the file under "Changes not staged for commit" as modified. The change is in the working tree, unstaged.

(b) git status reports the file under "Changes to be committed" as modified. The change is staged, ready for the commit.

(c) This is the interesting one: git status reports the file in both lists at once. One part —what you staged with add— shows up under "Changes to be committed"; the new part —what you modified after the add— shows up under "Changes not staged for commit." It's the same file mentioned twice, because Git captured the version from the moment of the add into the frame, and your later edit hasn't gone in yet.

Why it works: case (c) reveals what the staging area really does. It doesn't "mark the file" as ready; it photographs its content at the instant of the add. If you change it afterward, that new change is invisible to the commit until you do another add. Understanding this saves you from a subtle mistake: doing add, continuing to edit, and believing the commit includes your latest edits when it actually saved the version from a moment ago. When in doubt, git add again right before the commit.

Summary and next step

In this lesson you took order-triage's first photo and the ones that followed. You understood what a commit is: an immutable photo of the project, with a note, author, date, and a unique ID, like a video game save point you can always go back to. You saw why saving is two steps —the staging area that lets you choose what goes into each photo, so every commit tells a single story— and you handled the complete daily cycle: git status to look, git add to stage, git commit -m to save, and git log (with its --oneline version) to read the history. You met HEAD as "where you're standing" and working tree clean as "you're caught up." You learned to write good commit notes with the formula —imperative verb in English, specific about the workflow— and why those notes are what save the day on incident day. And you saw, as a first precaution, .gitignore so secrets never enter the history, a topic Module 3 develops further.

Before moving on to lesson 4 you should be able to: make a commit from start to finish without looking at the guide; read a git status and say which zone each change is in; read a git log --oneline and explain what each part is; and judge whether a commit note is good or bad.

Now you have two photos in the history: Add order-triage workflow and Widen CRM lookup timeout to 15 seconds. And with two photos comes a natural question you couldn't answer until now: what exactly changed between one and the other? In lesson 2 you raised a timeout from 5 to 15 seconds, but the history only tells you "something" changed in the file. Lesson 4 is what lets you see the change from the inside, line by line, with git diff. And there you're going to run head-on into n8n JSON's uncomfortable reality: its format produces noisy diffs, full of noise that changed nothing real, and you're going to learn to find the real change in the middle of that noise. That lesson is the module's hinge: it's where Git stops being theory and becomes the tool that really lets you understand a workflow's evolution.

Resources

  • Recording Changes to the Repository — Git Docs — the official book's chapter covering add, commit, status, and the complete cycle. This lesson's central reference.
  • git commit — Git Docs — the command's reference page, with the -m option and the others. Useful for when you want to write messages with a body, not just a title.
  • git add — Git Docs — the staging command's reference, including what git add . does, which is worth using carefully.
  • How to Write a Git Commit Message — cbea.ms — the reference article on commit notes, with the rules for the imperative verb and the short title. Written for developers, but its rules apply equally to a workflow.
  • gitignore — Git Docs — the reference for .gitignore patterns, for when in Module 3 you take it further with credentials.