Lesson 4 - Capstone Part 1: Build and Publish a Repo
On this page
- Welcome to Capstone Part 1
- Stage 1: Create the Project and Initialize Git
- Stage 2: Add the Essential Files and Make a Clean Initial Commit
- Stage 3: Grow the History with a Feature Commit
- Stage 4: Tag Your First Release
- Stage 5: Create the GitHub Repo and Push Code and Tag
- Make It Your Own
- Summary
- Next Steps
- Continue Building Your Skills
Welcome to Capstone Part 1
You’ve spent eight modules learning the moves: initializing repos, staging and committing, branching, writing good messages, working with remotes, tagging releases, and keeping your history clean. Now it’s time to put it all together. Over the next two lessons you’ll build a real project from an empty folder all the way to a published, shareable repository on GitHub — exactly the way you would for your own work.
This is Part 1 of a two-part capstone. Here, you’ll create a project, give it the standard furniture every good repo has, build a small but clean commit history, tag your first release, and push everything to GitHub. In Part 2, you’ll take that published repo and practice the collaboration workflow on top of it. Our sample project is Taskline, a tiny original command-line task tracker — but you’ll get far more out of this if you follow along with your own project idea on your own GitHub account. Any small script will do; the Git workflow is identical.
By the end of this part, you will be able to:
- Initialize a new project repository and add the essential files (
.gitignore,LICENSE,README.md) - Make a clean initial commit and grow the history with a Conventional Commits-style feature commit
- Tag a release with an annotated
v1.0.0tag - Create a repository on GitHub and push both your code and your tag
Let’s build something real.
Stage 1: Create the Project and Initialize Git
Every project starts the same way: a folder and a git init. Make a directory for the project, move into it, and turn it into a Git repository.
$ mkdir taskline
$ cd taskline
$ git init
Initialized empty Git repository in /home/maya/taskline/.git/That’s it — you now have a repository with no commits yet. If your Git is older and still defaults to a master branch, set the branch name to main so it matches GitHub’s default:
$ git branch -M mainYou have an empty repo and an empty folder. Next, we give the project its essential files.
Stage 2: Add the Essential Files and Make a Clean Initial Commit
A repository isn’t just code — it’s code plus the files that make it usable, legal, and welcoming. Before the first commit, we add the standard trio (.gitignore, LICENSE, README.md) and the project itself. Here’s the layout we’re building toward:
taskline/
.gitignore
LICENSE
README.md
taskline.pyStart with .gitignore, so Git never tracks the throwaway files Python and your tools generate:
# .gitignore
__pycache__/
*.pyc
.envAdd a LICENSE (we’ll use the MIT license for the sample — short, permissive, and common for small open-source tools), a README.md that explains what the project is and how to run it, and then the actual program. The first version of Taskline is deliberately tiny — one function that adds a task to a list:
# taskline.py
def add_task(tasks, title):
tasks.append({"title": title, "done": False})
return tasksThe .gitignore + LICENSE + README trio is what makes a repo look professional
These three files do most of the work of making a repository look maintained and welcoming. .gitignore keeps junk and secrets out of your history. LICENSE tells people what they’re legally allowed to do with your code (without one, the default is “all rights reserved” — nobody can reuse it). README.md is the front page GitHub renders automatically: what the project does, how to install and run it. Make adding this trio the very first thing you do on every new project, before you write a single feature.
With the files in place, stage everything and make a clear initial commit. A good first message names the project state — this is scaffold, not a feature yet:
$ git add .
$ git commit -m "Initial commit: project scaffold"Confirm the snapshot:
$ git log --oneline
98a65c9 Initial commit: project scaffoldYour hash will differ from 98a65c9 — every commit’s ID is computed from its content, author, and time, so yours is unique. The message is what matters.
Stage 3: Grow the History with a Feature Commit
A repository with one commit isn’t much of a history. Let’s add a feature the way you would in real work: make a focused change, then commit it with a clear, conventional message. Taskline can add tasks; now let’s let it mark them complete by adding a second function to taskline.py:
def complete_task(tasks, index):
tasks[index]["done"] = True
return tasksStage and commit just this change. We’ll write the message in Conventional Commits style — a type: summary format where feat: signals a new feature (you met this convention back in the messages module):
$ git add taskline.py
$ git commit -m "feat: mark tasks complete"Now the history tells a small story — scaffold first, then a feature on top:
$ git log --oneline
174db33 feat: mark tasks complete
98a65c9 Initial commit: project scaffoldTwo commits, each a self-contained, meaningful step. That’s exactly the kind of history that makes a project easy to review and to revert if something goes wrong.
Stage 4: Tag Your First Release
Once the project does something useful and you’re happy with it, mark that point as a release. A tag is a permanent, human-friendly name for a specific commit — perfect for “this is version 1.0.0.” Use an annotated tag (-a), which stores a message, your name, and the date, just like a commit:
$ git tag -a v1.0.0 -m "First release"The tag now points at your latest commit (the feat: mark tasks complete one). Following the vMAJOR.MINOR.PATCH convention from semantic versioning, v1.0.0 says “first stable release.” Tags don’t move when you make new commits — they stay pinned to the exact snapshot you released, so anyone can return to precisely this version later.
Stage 5: Create the GitHub Repo and Push Code and Tag
Your project lives only on your machine so far. To publish it, create an empty repository on GitHub (on github.com, click New, name it taskline, and — importantly — do not let GitHub add a README, .gitignore, or license, since you already have those locally). Then connect your local repo to it as the remote named origin.
Use the SSH (or HTTPS) URL that GitHub shows you. The URL below is an example — yours will use your own username:
$ git remote add origin [email protected]:maya/taskline.gitNow push your main branch. The -u flag sets origin/main as the upstream so future pushes and pulls can be just git push and git pull:
$ git push -u origin main
To github.com:maya/taskline.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.Pushing over the network also prints a few lines of object-transfer progress (counting, compressing, and writing your objects) before the result above — that’s normal; the exact numbers depend on your project’s size.
One thing to know: git push does not send your tags automatically. Your code is on GitHub, but v1.0.0 is still local. Push the tag explicitly:
$ git push origin v1.0.0
To github.com:maya/taskline.git
* [new tag] v1.0.0 -> v1.0.0Refresh your repository on GitHub and you’ll see it all: the code, the README rendered as the front page, two commits in the history, and v1.0.0 listed under the repo’s tags and releases. You’ve taken a project from an empty folder to a published, versioned, shareable repo — the complete create-to-publish workflow in one sitting.
Make It Your Own
The best way to lock this in is to do it for real with your own idea. Pick a small script you’d actually like to share, and extend the workflow above.
Exercise 1: Add a CONTRIBUTORS file in a new commit
Repositories often credit the people who help build them. Create a CONTRIBUTORS.md listing yourself, then commit it on its own.
Hint
Create the file, then git add CONTRIBUTORS.md and git commit -m "docs: add CONTRIBUTORS file". Keep it a separate commit from your code changes — one logical change per commit keeps the history readable. Check it landed with git log --oneline.
Exercise 2: Choose and add an appropriate LICENSE
If you skipped or rushed the license for your own project, fix that now. Decide what you want to allow and add the matching license text.
Hint
For a permissive “do almost anything, just keep my copyright notice” license, MIT is the common choice; for a copyleft “improvements must stay open” license, look at GPL. GitHub’s “Add file” button offers a license picker, or copy the official text into a LICENSE file. Commit it, e.g. git commit -m "docs: add MIT license".
Exercise 3: Write a README usage section with examples
A README that shows real usage is far more inviting than one that only describes the project. Add a “Usage” section to your README.md with a short code example of how to run your program.
Hint
Use a Markdown fenced code block (three backticks) to show a command and its expected output, under a ## Usage heading. After editing, commit with something like git commit -m "docs: add usage examples to README", then push with git push (no flags needed — you set the upstream earlier).
Summary
You built and published a real repository end to end. You started with git init in a fresh folder, added the essential trio — .gitignore, LICENSE, and README.md — alongside your code, and made a clean initial commit. You grew a small, meaningful history with a Conventional Commits feat: commit, tagged the result as an annotated v1.0.0 release, then connected a GitHub remote and pushed both your branch (git push -u origin main) and your tag (git push origin v1.0.0) — remembering that tags don’t travel with a normal push.
Key Concepts
- Repo furniture —
.gitignore,LICENSE,README.mdmake a repo professional and usable; add them first. - Clean history — focused commits with clear, conventional messages (
Initial commit: ...,feat: ...). - Annotated tags —
git tag -a v1.0.0 -m "..."pins a release to an exact commit. - Publishing —
git remote add origin,git push -u origin main, thengit push origin <tag>for the tag.
Why This Matters
This is the workflow behind essentially every project you’ll ever start or join. Being able to go from an empty directory to a clean, licensed, documented, versioned, published repository — without hunting for instructions — is one of the most practical skills a developer can have. It’s how you share work, build a portfolio, and make your projects easy for others (and future you) to understand and trust. With your repo live on GitHub, you’re ready for the other half of real development: working on it together with other people.
Next Steps
Continue to Lesson 5 - Capstone Part 2: Team Collaboration
Take your published repo and practice the full collaboration workflow: branches, pull requests, and review.
Back to Module Overview
Return to the Mastery, Safety, and Capstone module overview
Continue Building Your Skills
You’ve published a complete, professional repository from scratch — furniture, history, release tag, and all. That’s a milestone worth pausing on. In Part 2, the project stops being solo: you’ll branch off, open a pull request, review changes, and merge them back, practicing the team workflow on the very repo you just built.