Tokenova Learn

Office-Ready Git · provided by Tokenova

Git team templates

Ready-to-copy templates and conventions that teams use every day. Rename them when you copy them into a real repository.

You get the same files in the samples folder of the lab kit.

Open the interactive course

python-data.gitignore

Keeps secrets, data files, notebook checkpoints and Python junk out of Git. Copy it to .gitignore in a repository.

# .gitignore for a Python + Jupyter + data project (Acme Analytics template)
# One pattern per line. "folder/" means a whole folder, "*" matches any text,
# and a line starting with "!" brings a file back. Check a rule with:
#   git check-ignore -v <path>

# --- Secrets: passwords, tokens and keys never go into Git -------------------
.env
.env.*
!.env.example
*.pem
*.key
secrets/

# --- Data: raw and generated data lives in the warehouse, not in Git ---------
data/*.csv
data/*.xlsx
*.parquet
*.feather
*.pkl

# --- Jupyter: autosave copies (clear notebook outputs before committing) -----
.ipynb_checkpoints/

# --- Python leftovers ----------------------------------------------------------
__pycache__/
*.py[cod]
.venv/
venv/
*.egg-info/
build/
dist/
.pytest_cache/
.coverage
htmlcov/

# --- Editor settings (delete this line if your team shares .vscode/) ---------
.vscode/
.idea/

# --- Operating-system junk ------------------------------------------------------
Thumbs.db
desktop.ini
.DS_Store

gitattributes.txt

Stops Windows/Mac line-ending noise; marks binary files. Copy it to .gitattributes in a repository.

# Sample .gitattributes for a Python + data team.
# To use it, copy this file into the root of a repository and name it .gitattributes
# (it is stored here as gitattributes.txt so it doesn't affect this folder).
#
# Why: Windows uses CRLF line endings, macOS/Linux use LF. Without rules, the same
# file can look "completely changed" just because someone on another OS saved it.

# Let Git normalise line endings for every text file:
# stored as LF in the repository, converted for your OS on checkout.
* text=auto

# Scripts that must keep specific endings on every OS.
*.sh    text eol=lf
*.ps1   text eol=crlf
*.bat   text eol=crlf
*.cmd   text eol=crlf

# Source and config files (explicitly text).
*.py    text diff=python
*.sql   text
*.md    text
*.yml   text
*.yaml  text
*.json  text
*.csv   text

# Notebooks are JSON text. If you install nbstripout, it adds a filter line for *.ipynb here.
*.ipynb text

# Binary files: never convert, never try to merge line by line.
*.png   binary
*.jpg   binary
*.pdf   binary
*.xlsx  binary
*.parquet binary

# Large files tracked with Git LFS (only after running: git lfs install / git lfs track).
# *.parquet filter=lfs diff=lfs merge=lfs -text

dot-github/pull_request_template.md

Pre-fills every new PR description. Copy it to .github/pull_request_template.md in a repository.

## What does this change?
<!-- One or two sentences. What will be different after this is merged? -->

## Why?
<!-- The problem it solves. Link the issue: "Closes #12" closes it automatically when this PR is merged. -->
Closes #

## How did you test it?
<!-- The commands you ran and what you checked by hand. -->
- [ ] `python -m unittest` passes locally
- [ ] Tried it on a sample file:

## Anything reviewers should look at closely?
<!-- Risky parts, open questions, or decisions you'd like a second opinion on. -->

## Checklist
- [ ] The branch is up to date with `main`
- [ ] No secrets, passwords, or real data files in the diff
- [ ] Notebook outputs cleared (if you changed a notebook)

dot-github/ISSUE_TEMPLATE/bug_report.md

Bug report and feature request forms. Copy it to .github/ISSUE_TEMPLATE/ in a repository.

---
name: Bug report
about: Something is wrong or broken
title: "Bug: "
labels: bug
---

## What happened?
<!-- What you saw. Paste the exact error message if there is one. -->

## What did you expect?

## How to reproduce it
1.
2.
3.

## Where
- Branch or version (for example `main` or `v1.2.0`):
- File or step in the pipeline:

## Anything else?
<!-- Screenshots, sample input (never real customer data or passwords). -->

dot-github/ISSUE_TEMPLATE/feature_request.md

Bug report and feature request forms. Copy it to .github/ISSUE_TEMPLATE/ in a repository.

---
name: Feature request
about: Suggest an improvement
title: "Feature: "
labels: enhancement
---

## The problem
<!-- What is hard or slow today? Who is affected? -->

## What you'd like
<!-- The outcome you want, not necessarily how to build it. -->

## How we'll know it's done
- [ ]
- [ ]

## Alternatives you considered

dot-github/workflows/python-ci.yml

Runs the tests on every push and pull request (GitHub Actions). Copy it to .github/workflows/ci.yml in a repository.

# Continuous integration for a small Python project.
# Copy this file to .github/workflows/ci.yml in a repository (the folder name matters).
# GitHub runs it on every push to main and on every pull request, and shows the
# result as a check (green tick or red cross) on the pull request.

name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      # 1. Get a copy of the repository onto the runner (a fresh Linux machine).
      - uses: actions/checkout@v6

      # 2. Install the same Python version you use on your laptop.
      - uses: actions/setup-python@v5
        with:
          python-version: "3.10"

      # 3. Fail fast if any file has a syntax error.
      - name: Check syntax
        run: python -m compileall -q .

      # 4. Run the unit tests. A failing test turns the check red.
      - name: Run tests
        run: python -m unittest discover -s tests -t . -v

dot-github/CODEOWNERS

Requests reviews from the right people automatically. Copy it to .github/CODEOWNERS in a repository.

# CODEOWNERS: who must review changes to which files.
# Copy to .github/CODEOWNERS. When a pull request touches a matching file,
# GitHub automatically requests a review from the listed people or teams.
# With branch protection's "Require review from Code Owners" turned on,
# their approval is required before merging.
#
# Format: <file pattern>  <@user or @org/team> ...
# The LAST matching line wins, so put general rules first and specific ones after.

# Everything: the team lead reviews by default.
*                       @sam-chen

# Pipeline logic: the data engineers.
transform.py            @acme/data-engineering
extract.py              @acme/data-engineering

# CI and repository settings: the platform team.
/.github/               @acme/platform

# Notebooks: anyone on the analytics team can review.
/notebooks/             @acme/analytics

commit-messages.md

How to write messages your team will thank you for.

# Commit messages that help your team

A commit message is a note to the person who reads the history later. Often that person is you, six months from now, trying to find out why something changed.

## The shape

```
Cap discounts at 100 percent            <- subject: what the commit does, max ~50 characters

Discounts above 100% produced negative   <- body (optional): why, in plain sentences.
invoice totals for Fabrikam Medical.     <- Wrap at ~72 characters.
The cap matches the rule in the
billing policy.

Closes #14                               <- links (optional): issues, tickets
```

- **Subject in the imperative**, as if giving an order: "Add", "Fix", "Remove", "Rename". A good test: *"If applied, this commit will ___"*.
- **Start with a capital letter, no full stop at the end.**
- **Explain why in the body** when it isn't obvious. The diff already shows *what* changed.
- **One idea per commit.** A fix and a reformat are two commits.

## Good vs. not so good

| Not so good | Better |
|---|---|
| `fix` | `Fix rounding of tax on invoice totals` |
| `changes` | `Add supplier filter to the monthly report` |
| `WIP` | `Add CSV export for supplier totals (tests pending)` |
| `updated transform.py` | `Cap discounts at 100 percent` |
| `Fixed the bug Sam found yesterday` | `Handle empty invoice files in read_invoices` |
| `asdfgh` | *(anything that says what changed)* |

## Conventional Commits (if your team uses them)

Some teams add a type prefix so tools can build changelogs automatically:

```
feat: add supplier filter to the report
fix: cap discounts at 100 percent
docs: explain how to run the tests
refactor: move tax logic into its own function
test: cover negative quantities in line_total
chore: update CI to Python 3.12
```

Check your team's `CONTRIBUTING.md`, or look at `git log --oneline` on `main`, and copy the style you see.

## Writing longer messages from PowerShell

`git commit -m "subject"` is fine for one line. For a subject **and** a body, run `git commit` with no `-m`. Git opens your editor (VS Code, once you set `core.editor` on Day 1). Write the message, save, and close the tab.

Or pass `-m` twice. Each `-m` becomes its own paragraph:

```powershell
git commit -m "Cap discounts at 100 percent" -m "Discounts above 100% produced negative totals."
```

pr-description.md

Pull request descriptions that get fast reviews.

# Pull request descriptions reviewers love

A pull request (PR) asks your team to accept a change. A good description makes review fast, because reviewers know what to look for and how you checked it.

## A good example

> **Title:** Cap discounts at 100 percent
>
> **What does this change?**
> `apply_discount` now caps the percentage at 100, so an invoice total can never go below zero.
>
> **Why?**
> Fabrikam Medical's September file had a 150% discount line (a data-entry error upstream). It produced a negative total, which broke the monthly report. Closes #14.
>
> **How did you test it?**
> - Added `test_discount_is_capped` (fails before the fix, passes after)
> - `python -m unittest` passes locally
> - Re-ran the report on the September sample: totals are all ≥ 0
>
> **Anything to look at closely?**
> Should we also *log* discounts over 100%, so the upstream team hears about bad data? Happy to do that in a follow-up PR.

## A not-so-good example

> **Title:** fixes
>
> fixed the discount thing

The reviewer has to reverse-engineer everything from the diff, and nobody can link it to the issue later.

## Tips

- **Keep PRs small.** Under ~300 changed lines gets a faster, better review. Split big work into a series of PRs.
- **Title = what it does**, like a commit subject.
- **Link the issue** with a closing keyword: `Closes #14`, `Fixes #14` or `Resolves #14`. The issue closes automatically when the PR merges into the default branch.
- **Open a Draft PR** early if you'd like feedback before it's finished.
- **Review your own diff first** on the *Files changed* tab. You'll catch leftover debug prints, and anything you didn't mean to include.
- **Say how you tested it.** "Tests pass" is good. "Tests pass, and I ran it on last month's file" is better.

code-review-comments.md

Giving and receiving review kindly and clearly.

# Code review comments: giving and receiving

Code review is how a team shares knowledge and catches mistakes. It's about the code, never the person.

## Label your comments so the author knows what's required

| Prefix | Meaning | Example |
|---|---|---|
| **blocking:** | Must change before merge | *blocking: this reads `.env` from the repo root. Can we use an environment variable instead, so the password never sits in the repo?* |
| **suggestion:** | Worth considering, the author decides | *suggestion: `sum(line_total(q, p) for q, p in lines)` might read more clearly than the loop.* |
| **question:** | You want to understand | *question: why do we round before applying tax rather than after?* |
| **nit:** | Tiny style point, optional | *nit: typo in the docstring, "percantage".* |
| **praise:** | Something done well | *praise: nice test name, it reads like a sentence.* |

## Kind and specific beats short and sharp

| Instead of | Try |
|---|---|
| "This is wrong." | "I think this returns a negative total when `percent` > 100. Could we cap it, or raise an error?" |
| "Why would you do it this way?" | "What made you choose a loop here? I wondered if `sum()` would be simpler." |
| "Fix the naming." | "nit: `calc2` → `apply_discount` would say what it does." |

## GitHub's "suggested change"

On the **Files changed** tab, add a comment on a line and insert a suggestion. The author can apply it with one click (**Commit suggestion**), and it becomes a real commit on the PR branch. Great for typos and small fixes.

~~~markdown
```suggestion
    """Take a percentage discount off an amount (capped at 100%)."""
```
~~~

## When you finish a review, choose one
- **Comment**: general feedback, no decision yet.
- **Approve**: good to merge (after any small fixes you mentioned).
- **Request changes**: at least one blocking issue.

## Receiving review
- Say thanks, and assume good intent.
- Reply to every comment: "Done in a1b2c3d", or explain why not.
- Push fixes as **new commits** on the same branch. The PR updates itself.
- Don't take it personally. Even very senior people get change requests.
- If a thread goes back and forth more than twice, have a quick call instead.

branch-naming.md

Naming conventions and when to branch.

# Branch naming

A branch name tells your teammates what the work is and why it exists, before they open anything.

## A common convention

```
<type>/<issue-number>-<short-description>
```

| Type | Use for | Example |
|---|---|---|
| `feature/` | New functionality | `feature/7-supplier-filter` |
| `fix/` or `bugfix/` | A bug that isn't urgent | `fix/14-discount-cap` |
| `hotfix/` | An urgent fix for something already released | `hotfix/1.2.1` |
| `docs/` | Documentation only | `docs/contributing-tips` |
| `refactor/` | Restructuring without changing behaviour | `refactor/split-transform-module` |
| `chore/` | Tooling, CI, dependencies | `chore/ci-python-3-12` |
| `release/` | Preparing a release (Git Flow teams) | `release/1.3.0` |
| `<name>/` | Personal or experimental work (some teams) | `alex/try-polars` |

## Rules of thumb
- **lowercase-with-hyphens**: no spaces, no capitals (they cause trouble on case-insensitive Windows).
- **Short but specific**: `feature/7-supplier-filter`, not `feature/stuff` or `feature/the-new-supplier-filter-that-sam-asked-for-in-standup`.
- **Include the issue or ticket number** if your team uses them (`INV-231`, `#7`). Tools can then link the branch to the ticket.
- **One branch per piece of work.** Delete it after it's merged (GitHub offers a **Delete branch** button right after merging).
- **Never work directly on `main`.** Branch first, even for one-line fixes.

## Creating one

```powershell
git switch main
git pull
git switch -c feature/7-supplier-filter
```

Always branch from an **up-to-date** `main`, so you start from the latest code.