Flex Engineers
5 min read

Building Our Own Git & GitHub Actions Reference, Instead of Trusting Search Results

GitCI/CDGitHub ActionsDevOpsTechnical MentoringCode Review

The problem with "just Google it"

Every engineer has a Git command they look up every single time. For one of ours, it used to be git rebase -i HEAD~N — knowing what it did wasn't the issue, it was never trusting the syntax under pressure, mid-merge-conflict, with a client deploy waiting. Searching for it meant sifting through Stack Overflow answers from a decade ago, half of them contradicting each other about --onto versus plain rebase, none of them mentioning what happens if you're mid-cherry-pick when you run it.

So instead of re-searching the same fifteen commands every few months, our team built a shared reference repo: a structured, versioned set of Git and GitHub Actions notes every engineer at Flex Engineers can trust, because each line was written after being tested, not copied.

What's actually in here

This isn't a tutorial dump. It's organized the way our engineers actually think about Git, in the order problems show up on a real project:

SectionCovers
Configuration & Aliasesuser.email, user.name, custom aliases like git config --global alias.st status
Branching & Switchingcheckout vs. the newer switch — and why the team now defaults to switch
Merging, Rebasing & Cherry-Picking--squash, --no-ff, -i HEAD~N, and reverting merge commits with -m 1
Undoing ChangesThe full reset --soft / reset --hard / restore --staged decision tree
Stashingpush -m, pop [index], drop [index] — because stash-by-index is where people get burned
TagsLightweight vs. annotated, and why the team defaults to annotated for anything shipped
Remotes & ForksUpstream syncing, tracking branches, deleting remote branches cleanly

Each command carries a one-line comment explaining why you'd reach for it, not just what it does — the difference between git reset HEAD~1 and git reset --hard HEAD~1 is one flag and an entire afternoon of lost client work, so the comment says so.

Iterating on the format itself

There are two versions of the core cheatsheet in this repo (git_commands_cheatsheet.md and git_commands.markdown), and that's not clutter — it's a visible record of format experiments the team ran before settling. The first pass put explanatory comments inline after each command:

git reset --hard HEAD~1  # Undoes the last commit and discards changes in the working directory

The second pass separated the command from its explanation onto its own line:

git reset --hard HEAD~1
# Undoes the last commit and discards changes in the working directory

That second format reads better as documentation but is worse for quick copy-paste during actual work, since you have to grab two lines instead of one. We kept both because they serve different moments — one for skimming, one for pasting straight into a terminal.

The GitHub Actions half

The workflows/ directory is a parallel track: thirteen standalone GitHub Actions workflow files, each isolating exactly one CI/CD concept so any engineer on the team can understand it without wading through a real pipeline's noise.

A few worth calling out:

Matrix builds, with include/exclude overrides — the part most tutorials skip:

strategy:
  matrix:
    node-version: [12, 14, 16]
    operating-system: [ubuntu-latest, windows-latest]
    include:
      - node-version: 18
        operating-system: ubuntu-latest
    exclude:
      - node-version: 12
        operating-system: windows-latest

Container jobs with service dependencies — running tests inside a node:16 container against a live mongo service container, which is the pattern that actually mirrors a production integration-test setup rather than mocking the database:

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: node:16
    services:
      mongodb:
        image: mongo
        env:
          MONGO_INITDB_ROOT_USERNAME: root
          MONGO_INITDB_ROOT_password: example

Reusable workflows (Resuse.yml, ResueWithInputs.yml, ResueInputsSecrets.yml, ResuseReturns.yml) — a deliberate progression from a bare reusable workflow, to one that accepts inputs, to one that also threads secrets through, to one that returns outputs back to the caller. Reusable workflows are one of the least-documented parts of GitHub Actions in practice — the official docs cover the mechanics, but not the incremental path of "how do you add one more capability without breaking the last thing you built." Splitting it into four files was the only way the team found to actually retain the differences across projects.

Other files isolate secrets handling, conditional job execution, continue-on-error, artifact upload/download, and running the same job with and without Docker — each one small enough to read top to bottom in under a minute, which is the whole point.

Why maintain this instead of bookmarking a cheat sheet site

A generic cheat sheet tells you git rebase -i HEAD~N exists. It doesn't tell you what happens if you're already mid-rebase when a conflict hits, or which of the team's branches actually needs --no-ff versus a fast-forward merge. Those are decisions specific to how we work and what's bitten someone before. Writing our own reference — and being willing to maintain two competing formats of the same content until one clearly wins — forces the team to actually understand each command well enough to explain it, rather than pattern-matching a syntax half-remembered, and it's the resource we point every new engineer to during onboarding.

The PDF exports (Git.pdf, Git Actions.pdf, git-cheatsheet.pdf, actions-cheatsheet.pdf) exist for the same reason people print out flight boarding passes even though the app works fine: offline access during a bad wifi day at a client site is worth the redundancy.

Takeaway

This repo isn't flashy, and it's not meant to be a portfolio centerpiece — it's evidence of a habit we build into the team: when a tool or workflow does something we'll need again, we don't just solve it once and forget it, we write it down in a form precise enough to trust the next time, and we're willing to revise the format until it actually holds up under real use. That same instinct — document decisions, keep the reasoning visible, iterate on structure rather than settling for the first draft — is the same one we bring to production codebases, just aimed at code instead of commands.