How to Set Up a Project on GitHub
A practical, end-to-end walkthrough for taking an ML/AI project from an empty folder to a clean, collaborative, CI-backed GitHub repository. This is the guide interviewers expect you to already know version control hygiene, branching, pull requests, and CI/CD are table stakes for ML Engineer, AI Engineer, and MLOps roles.
Why this matters in interviews: "Walk me through how you'd structure and ship a new ML project" is a common system/behavioral question. Being fluent with git, GitHub Actions, and a sane repo layout signals you can ship, not just prototype in notebooks.
Table of Contents
- Prerequisites
- Step 1: Install and Configure Git
- Step 2: Create the Repository
- Step 3: Initialize the Project Locally
- Step 4: The Essential Files
- Step 5: Connect Local to Remote
- Step 6: Branching Strategy
- Step 7: Pull Requests & Code Review
- Step 8: Protect the Main Branch
- Step 9: Continuous Integration (GitHub Actions)
- Step 10: Releases, Tags & Versioning
- Step 11: GitHub Pages (Project Docs Site)
- Secrets & Security
- Authentication: SSH vs HTTPS vs gh CLI
- Common Mistakes
- Interview Questions
Prerequisites
| Tool | Why | Check |
|---|---|---|
| Git | Version control | git --version |
| A GitHub account | Remote hosting | github.com |
GitHub CLI (gh) (optional, recommended) |
Create repos/PRs from the terminal | gh --version |
| An editor | VS Code, JetBrains, etc. | - |
Step 1: Install and Configure Git
# macOS
brew install git
# Debian/Ubuntu
sudo apt-get install git
# Windows: download from git-scm.com
# One-time identity setup (shows up in your commits)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Sensible defaults
git config --global init.defaultBranch main # default branch name
git config --global pull.rebase true # cleaner history on pull
git config --global core.autocrlf input # line-ending sanity (mac/linux)
Verify with
git config --list.
Step 2: Create the Repository
Option A: On github.com (GUI)
- Click New repository.
- Name it (
my-ml-project), add a one-line description. - Choose Public or Private.
- Tick Add a README, Add .gitignore → Python, and Choose a license (MIT/Apache-2.0 are common).
- Create repository, then clone:
git clone https://github.com/<you>/my-ml-project.git
cd my-ml-project
Option B: From the terminal with gh
gh repo create my-ml-project --public --clone --gitignore Python --license mit
cd my-ml-project
Option C: Push an existing local folder
See Step 5.
Step 3: Initialize the Project Locally
mkdir my-ml-project && cd my-ml-project
git init # creates the .git/ directory
python -m venv .venv # isolated environment
source .venv/bin/activate # Windows: .venv\Scripts\activate
See the companion guide ML/AI Project Folder Structures for the recommended directory layout to create here.
Step 4: The Essential Files
Every healthy repo has these. Skipping them is the #1 sign of an unmaintained project.
.gitignore
Stop committing junk, secrets, and large artifacts. A minimal Python/ML version:
# Python
__pycache__/
*.py[cod]
.venv/
venv/
.env
.ipynb_checkpoints/
# ML artifacts (use DVC / model registry instead of git)
*.ckpt
*.pt
*.pth
*.onnx
data/raw/
data/processed/
models/
mlruns/
wandb/
# OS / editor
.DS_Store
.idea/
.vscode/
README.md
The front door. Include: what it does, how to install, how to run, an example, and a project structure overview. (See Step 11 to turn docs into a site.)
LICENSE
No license = "all rights reserved" by default, meaning others legally cannot use it. MIT (permissive) and Apache-2.0 (permissive + patent grant) are the usual picks for open work.
requirements.txt / pyproject.toml
Pin dependencies so the project is reproducible.
pip freeze > requirements.txt # quick & dirty
# or, preferred for libraries/apps:
# define dependencies in pyproject.toml and use uv/poetry/pip-tools to lock
.env.example
Commit a template of required env vars (never the real .env):
# .env.example: copy to .env and fill in
ANTHROPIC_API_KEY=
DATABASE_URL=
CONTRIBUTING.md and CODE_OF_CONDUCT.md
For collaborative/open-source repos: set expectations for contributors.
Step 5: Connect Local to Remote
git add .
git commit -m "Initial project scaffold"
# Link to the GitHub remote you created in Step 2
git remote add origin https://github.com/<you>/my-ml-project.git
git branch -M main # rename current branch to main
git push -u origin main # -u sets the upstream so future pushes are just `git push`
git remote -vconfirms the remote URL.
Step 6: Branching Strategy
Never commit straight to main. Work on a branch, open a PR, merge after review.
GitHub Flow (simplest: recommended for most ML projects)
main ──●──────────────●────────────● (always deployable)
\ / \ /
●──●──●────● ●──●──●────●
feature/x fix/y
git switch -c feature/add-training-pipeline # create + switch (modern syntax)
# ...work, then...
git add .
git commit -m "feat: add training pipeline with early stopping"
git push -u origin feature/add-training-pipeline
Branch naming conventions
| Prefix | Use for |
|---|---|
feature/ |
New functionality |
fix/ |
Bug fixes |
experiment/ |
ML experiments (experiment/lr-sweep) |
docs/ |
Documentation only |
chore/ |
Tooling, deps, CI |
Conventional Commits
A widely-used commit message format that enables auto-changelogs and semantic versioning:
feat: add SHAP-based feature attribution
fix: correct off-by-one in sequence padding
docs: expand README quickstart
chore: bump torch to 2.4
refactor: extract dataloader into module
Format: <type>(<optional scope>): <description>.
Step 7: Pull Requests & Code Review
A Pull Request (PR) proposes merging your branch into main and is where
review, CI, and discussion happen.
# With the gh CLI
gh pr create --title "Add training pipeline" --body "Implements early stopping and checkpointing."
# Or push and click the link GitHub prints / open a PR in the web UI.
A good PR:
- Is small and focused (one logical change: easier to review, faster to merge).
- Has a clear title + description (what, why, how to test).
- Links the issue it closes:
Closes #42in the body auto-closes the issue on merge. - Passes CI (tests, lint) before requesting review.
PR templates: add .github/pull_request_template.md to standardize:
## What
<!-- What does this PR do? -->
## Why
<!-- Why is it needed? -->
## How to test
<!-- Steps / commands -->
## Checklist
- [ ] Tests added/updated
- [ ] Docs updated
- [ ] CI passing
Step 8: Protect the Main Branch
In Settings → Branches → Add branch protection rule for main:
- Require a pull request before merging
- Require approvals (1+)
- Require status checks to pass (your CI)
- Require branches to be up to date before merging
- (Optional) Require signed commits / linear history
This guarantees nothing untested or unreviewed reaches main.
Step 9: Continuous Integration (GitHub Actions)
CI runs automatically on every push/PR. Create .github/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest ruff
- name: Lint
run: ruff check .
- name: Run tests
run: pytest -q
For a deeper treatment (matrices, caching, Docker builds, deployment), see the GitHub Actions guide.
Pre-commit hooks catch issues before they hit CI. Add .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.0
hooks:
- id: ruff
- id: ruff-format
pip install pre-commit && pre-commit install
Step 10: Releases, Tags & Versioning
Use Semantic Versioning (MAJOR.MINOR.PATCH):
- MAJOR: breaking changes
- MINOR: new, backward-compatible features
- PATCH: backward-compatible bug fixes
git tag -a v1.0.0 -m "First stable release"
git push origin v1.0.0
Then Releases → Draft a new release on GitHub (or gh release create v1.0.0 --generate-notes)
to attach changelogs and artifacts.
Step 11: GitHub Pages (Project Docs Site)
Turn README.md/docs/ into a hosted website for free.
- Settings → Pages.
- Source: Deploy from a branch →
main→/ (root)or/docs. - Save. Your site appears at
https://<you>.github.io/<repo>/.
This very repository is published with GitHub Pages:
index.htmlat the root renders the markdown guides into a browsable site. A.nojekyllfile disables Jekyll processing so files are served as-is.
For richer docs, use MkDocs (mkdocs-material) or Sphinx with a Pages
deploy workflow.
Secrets & Security
- Never commit secrets (API keys, tokens, passwords). Use
.env(git-ignored) locally and GitHub Actions Secrets (Settings → Secrets and variables → Actions) in CI: reference as${{ secrets.ANTHROPIC_API_KEY }}. - If you leak a secret, rotate it immediately: git history is permanent. Removing it from the latest commit is not enough; revoke and reissue the key.
- Enable Dependabot (
Settings → Code security) for automated dependency vulnerability alerts and PRs. - Enable secret scanning and push protection to block accidental commits of credentials.
Authentication: SSH vs HTTPS vs gh CLI
| Method | Setup | Best for |
|---|---|---|
| HTTPS + token | Generate a Personal Access Token (PAT), use as password | Simple, works everywhere |
| SSH keys | ssh-keygen → add public key to GitHub |
No password prompts, dev machines |
gh auth login |
One command, browser flow | Easiest; manages credentials for you |
# SSH key (one-time)
ssh-keygen -t ed25519 -C "you@example.com"
cat ~/.ssh/id_ed25519.pub # paste into GitHub → Settings → SSH keys
git remote set-url origin git@github.com:<you>/my-ml-project.git
Common Mistakes
| Mistake | Fix |
|---|---|
Committing data/, models/, .venv/ |
Add to .gitignore; use DVC / a model registry for large artifacts |
| Committing secrets | .env git-ignored + Actions Secrets; rotate if leaked |
| One giant PR | Split into small, focused PRs |
Working directly on main |
Use feature branches + branch protection |
| No README/LICENSE | Add both: they signal a real, usable project |
Vague commit messages ("fixed stuff") |
Use Conventional Commits |
| No CI | Add a GitHub Actions workflow (Step 9) |
Interview Questions
- Walk me through how you'd set up a new ML project repo. → Init, venv,
.gitignore, README/LICENSE, dependency pinning, branch protection, CI. git mergevsgit rebase? → Merge preserves history with a merge commit; rebase replays commits for a linear history. Don't rebase shared/public branches.- How do you keep large model files / datasets out of git? →
.gitignore+ DVC / Git LFS / a model registry (MLflow, S3): git is for code, not binaries. - What goes in CI for an ML repo? → Lint, unit tests, data/schema validation, maybe a tiny training smoke test and model-eval gate.
- How do you handle secrets across local dev and CI? →
.env(git-ignored) locally, GitHub Actions Secrets in CI, never hardcoded. - What is a protected branch and why use it? → A branch that requires PRs,
reviews, and passing checks before merge: prevents unreviewed/broken code on
main. - Explain trunk-based vs GitHub Flow vs Git Flow. → Trunk-based: short-lived
branches off
main, frequent integration. GitHub Flow: branch → PR → merge. Git Flow: long-liveddevelop/releasebranches (heavier; less common for ML).