Closing the Learn Git and GitHub series: GitHub Actions for automated CI and CD, Semantic Versioning v1.2.3, annotated tags and GitHub Releases with GitHub CLI, plus a recap of all 21 episodes from the first phase to production.

In episode 19 we automated local quality with Git hooks. Episode 20 is the final episode, and we close by automating the entire lifecycle: from push, test, build, to release. Three components form the core: GitHub Actions for CI/CD, Semantic Versioning and Git Tags for versioning, and GitHub Releases for distribution — all controllable from the terminal via GitHub CLI.
The journey will feel complete after this: you started with git init in episode 0 and now you operate a production release pipeline end-to-end from a single YAML file inside the repository. Git version 2.4x (2026) and GitHub as a collaboration platform have become the foundation of your work — this episode brings it all together.
GitHub Actions runs automated jobs based on events in the repository — a push, a pull request, or a schedule. Workflows are defined as YAML files in .github/workflows/, committed like ordinary code.
name: CI
on:
push:
branches: [main, staging]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Checkout kode
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.2
- name: Install dependensi
run: bun install --frozen-lockfile
- name: Lint dan build
run: |
bun run lint
bun run build
- name: Deploy preview untuk staging
if: github.ref == 'refs/heads/staging'
run: echo "Deploy preview untuk ${{ github.ref }}"
- name: Upload artifact build
uses: actions/upload-artifact@v4
with:
name: build
path: out/This workflow triggers automatically on pushes to main or staging, and when a PR targets main. Each jobs runs on a runner, and steps execute in sequence. Contextual expressions like github.ref or github.event_name are read by the runner when the step executes — their values are never written directly in the file. Secrets stored on GitHub can also be read by steps using the same expressions; make sure sensitive values are never printed in logs.
Tip
One proven pattern for this series' projects: CI validates (lint, test, build) and writes to Git; CD reads from Git and deploys. Separate the two into different workflows so a build failure never overwrites a production environment.
Good versioning lets users know the impact of a release just from its number. Semantic Versioning (SemVer) answers this with the v1.2.3 format.
| Component | Increases when |
|---|---|
| MAJOR | There is a change that breaks compatibility |
| MINOR | There is a new feature that remains backward compatible |
| PATCH | There is a bug fix without new features |
For pre-releases, SemVer allows suffixes like 1.2.3-rc.1 — a pattern that fits the staging branch with an rc prerelease according to this repository's release flow. The key: conventional commits (episode 4) provide the automatic input — feat: bumps MINOR, fix: bumps PATCH, and a breaking change bumps MAJOR.
A tag marks a specific point in history. There are two types:
git tag -a v1.0.0 -m "Release v1.0.0"List tags with git tag -n. Tags are not pushed automatically:
git push origin v1.0.0
git push origin --tagsWarning
A tag that has been pushed and used by others must not be changed. Deleting and replacing the same tag can confuse release consumers and break the audit trail. Create a new tag — do not rewrite the old one.
A GitHub Release is a wrapper around a tag: it holds release notes and binary assets. The fastest way is through gh:
gh release create v1.0.0 --generate-notes
gh release create v1.0.0 ./dist/*.zip --title "v1.0.0" --notes "Rilis stabil pertama"--generate-notes composes a changelog automatically from the conventional commits between tags. Manage subsequent releases with gh release list and gh release view v1.0.0. In the UI, a Release page can include source code zips, binary assets, and release notes — used by other teams to download a specific version.
The journey from episode 0 to 20 is divided into six phases. Each phase builds the foundation for the next:
| Phase | Episodes | Focus |
|---|---|---|
| 1. Prerequisites & Fundamentals | 0-2 | Environment setup, VCS history, Git architecture |
| 2. Basic Local Operations | 3-5 | Init & tracking, commit & log, diff & inspection |
| 3. Branch, Merge & Remote | 6-9 | Branching, merge & conflicts, GitHub remote, collaboration |
| 4. Workflows & GitHub Features | 10-13 | Team workflows, PR & code review, issues, security |
| 5. Advanced Concepts | 14-17 | Undoing changes, stash & clean, interactive rebase, navigation |
| 6. Modern Ecosystem & Production | 18-20 | Submodule & subtree, hooks, GitHub automation |
Here is the complete flow combining everything you have learned:
git switch -c) and write conventional commit messages.gh pr create (episode 11), and wait for the CI status checks to turn green.git switch -c feat/login-page
git add . && git commit -m "feat: tambah halaman login"
git push -u origin feat/login-page
gh pr create --fill
gh pr merge --squash
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
gh release create v1.2.3 --generate-notesNote
Automation lightens the human load, not replaces human judgment. Lint, test, and build can run on machines; but deciding whether a change deserves a release, whether a breaking change is really necessary, and how to write clear release notes — that is still your job.
This episode closes the series with the three core components of the automation ecosystem: GitHub Actions for CI/CD from a YAML file inside the repository, Semantic Versioning v1.2.3 with annotated tags and git push origin --tags, and GitHub Releases published via gh release create — plus a recap of all 21 episodes in six phases and an end-to-end production checklist.
The points to take with you:
.github/workflows/ci.yml, triggered on pushes and PRs.v1.2.3 guides version numbers; conventional commits feed the changelog automatically.git tag -a) store release metadata; push explicitly with git push origin v1.0.0.gh release create publishes a Release with notes and assets from a tag.From episode 0 to 20, you have completed a full journey: preparing skills and environment, understanding Git's architecture and how it works, mastering commits, branching, merging, and conflicts, collaborating through remotes, PRs, and code review, securing the repository with branch protection, reorganizing and rescuing history, managing composite repositories, automating local quality, and operating a production release pipeline. Git is no longer just a command — it is a way of thinking about change that can be traced, undone, and automated. Congratulations, you now understand Git and GitHub thoroughly — and more importantly, you have a foundation to keep learning. See you in the next series!