add knowledge
This commit is contained in:
@@ -1,12 +1,61 @@
|
|||||||
# devops-guide
|
# DevOps Guide
|
||||||
|
|
||||||
>DevOps is a set of practices that integrates software development and operations to deliver changes faster, more reliably, and with continuous feedback.
|
> DevOps is the practice of reducing friction between writing code and running it reliably in production — giving you **reproducibility**, **fast feedback**, and **confidence at scale**.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
---------
|
---
|
||||||
|
|
||||||
## Getting started
|
## Problem → Tool Category
|
||||||
|
|
||||||
- install cli tooling: https://git.roxautomation.com/sjev/cli-tools
|
| Problem | Tool Category |
|
||||||
- python cli template: https://git.roxautomation.com/sjev/python-cli-template
|
|---|---|
|
||||||
|
| Code gets lost, no change history | [Version Control](docs/version-control.md) |
|
||||||
|
| "Works on my machine" | [Containerization](docs/containerization.md) |
|
||||||
|
| Dependency conflicts between projects | [Package Management](docs/package-management.md) |
|
||||||
|
| Style drift, bugs slip through review | [Linting & Formatting](docs/linting-formatting.md) |
|
||||||
|
| Type errors discovered at runtime | [Type Checking](docs/type-checking.md) |
|
||||||
|
| Regressions go undetected | [Testing](docs/testing.md) |
|
||||||
|
| Manual, repetitive dev commands | [Task Automation](docs/task-automation.md) |
|
||||||
|
| Nobody knows how to run the project | [Documentation](docs/documentation.md) |
|
||||||
|
| Slow, manual deployments | [CI/CD](docs/ci-cd.md) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tool Matrix by Language
|
||||||
|
|
||||||
|
### Language-Agnostic
|
||||||
|
|
||||||
|
| Category | Tool(s) |
|
||||||
|
|---|---|
|
||||||
|
| Version control | Git + GitHub / GitLab / Gitea |
|
||||||
|
| Containerization | Docker |
|
||||||
|
| CI/CD platform | GitHub Actions, GitLab CI, Gitea Actions, Jenkins |
|
||||||
|
|
||||||
|
### Language-Specific
|
||||||
|
|
||||||
|
| Category | Python | JavaScript | Go | C++ |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| **Package management** | uv, pip, poetry | npm, pnpm, yarn | go mod | conan, vcpkg, cmake |
|
||||||
|
| **Linting / formatting** | ruff, pylint, flake8 | eslint, prettier, biome | golangci-lint, gofmt | clang-tidy, clang-format |
|
||||||
|
| **Type checking** | mypy, pyright | tsc, flow | built-in | built-in + clang-tidy |
|
||||||
|
| **Testing** | pytest, hypothesis | vitest, jest, mocha | testing (stdlib), testify | googletest, catch2 |
|
||||||
|
| **Task automation** | invoke, make, tox | npm scripts, turbo, nx | make, mage, task | cmake, make, ninja |
|
||||||
|
| **Docs** | mkdocs-material, sphinx | VitePress, Docusaurus | pkgsite, godoc | doxygen, sphinx |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Minimal "Good Enough" Stack
|
||||||
|
|
||||||
|
If you strip it to essentials:
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|---|---|
|
||||||
|
| `git` + GitHub | History + collaboration |
|
||||||
|
| `uv` | Env + dependencies |
|
||||||
|
| `ruff` + `mypy` | Correctness |
|
||||||
|
| `pytest` | Confidence |
|
||||||
|
| `invoke` | Dev UX |
|
||||||
|
| Docker | Reproducibility |
|
||||||
|
|
||||||
|
Add a tool only when you feel the pain it fixes.
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# CI/CD
|
||||||
|
|
||||||
|
Automatically run tests, linting, and deployment on every push — catch problems before they reach users.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
| Platform | Trigger | Self-hosted runner |
|
||||||
|
|---|---|---|
|
||||||
|
| GitHub Actions | push, PR, schedule | yes |
|
||||||
|
| GitLab CI | push, MR, schedule | yes |
|
||||||
|
| Gitea Actions | push, PR | yes |
|
||||||
|
| Jenkins | any (webhook/poll) | yes |
|
||||||
|
|
||||||
|
CI/CD is a platform-level choice, not a language one. The pipeline calls your existing `invoke`/`make` tasks.
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
- **CI (Continuous Integration)** — run tests on every commit; fail fast
|
||||||
|
- **CD (Continuous Delivery/Deployment)** — automatically ship passing builds
|
||||||
|
- **Pipeline as code** — the config lives in the repo (`*.yml`), versioned alongside the code
|
||||||
|
- **Local CI first** — Docker-based local runs before pushing; remote CI is the final net, not the primary feedback loop
|
||||||
|
|
||||||
|
## GitHub Actions — Minimal Python Pipeline
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/ci.yml
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
- run: pip install uv && uv pip install --system -e ".[dev]"
|
||||||
|
- run: ruff check .
|
||||||
|
- run: mypy .
|
||||||
|
- run: pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## GitLab CI — Equivalent
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .gitlab-ci.yml
|
||||||
|
image: python:3.12-slim
|
||||||
|
|
||||||
|
test:
|
||||||
|
script:
|
||||||
|
- pip install uv && uv pip install -e ".[dev]"
|
||||||
|
- ruff check .
|
||||||
|
- mypy .
|
||||||
|
- pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Keep pipelines fast — slow CI gets ignored
|
||||||
|
- Cache dependency installs (e.g. `actions/cache` on `~/.cache/uv`)
|
||||||
|
- Use matrix builds to test across Python/Node versions when it matters
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Containerization
|
||||||
|
|
||||||
|
Package your app and its environment together so it runs identically on every machine — dev, CI, and production.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
**Docker** is the standard. Everything else (Podman, containerd) is compatible with Docker images.
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
- **Image** — a snapshot of your app + OS + dependencies
|
||||||
|
- **Container** — a running instance of an image
|
||||||
|
- **Dockerfile** — the recipe for building an image
|
||||||
|
- **Local CI pattern** — run your test suite inside a container before pushing; catches environment drift before it reaches remote CI
|
||||||
|
|
||||||
|
## Minimal Dockerfile (Python)
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM python:3.12-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY pyproject.toml .
|
||||||
|
RUN pip install uv && uv pip install --system -e ".[dev]"
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
CMD ["python", "-m", "mypackage"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# build
|
||||||
|
docker build -t myapp .
|
||||||
|
|
||||||
|
# run
|
||||||
|
docker run --rm myapp
|
||||||
|
|
||||||
|
# local CI — run tests inside the container
|
||||||
|
docker run --rm myapp pytest
|
||||||
|
|
||||||
|
# interactive shell for debugging
|
||||||
|
docker run --rm -it myapp bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Use `.dockerignore` to exclude `__pycache__`, `.git`, `.venv`, `*.pyc`
|
||||||
|
- Pin the base image tag (`python:3.12-slim`, not `python:latest`)
|
||||||
|
- Layer ordering matters: copy dependency files before source so the install layer is cached
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Documentation
|
||||||
|
|
||||||
|
Make it easy to understand, run, and contribute to your project — for future you and for teammates.
|
||||||
|
|
||||||
|
## Tools by Language
|
||||||
|
|
||||||
|
| Language | Recommended | Alternatives |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | `mkdocs` + Material | sphinx, pdoc |
|
||||||
|
| JavaScript/TS | VitePress | Docusaurus, JSDoc |
|
||||||
|
| Go | `pkgsite`, `godoc` | (built-in tooling is strong) |
|
||||||
|
| C++ | Doxygen | sphinx, mkdocs |
|
||||||
|
|
||||||
|
## Python — MkDocs + Material
|
||||||
|
|
||||||
|
Fast setup, Markdown-based, deploys to GitHub Pages in one command.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv add --dev mkdocs-material
|
||||||
|
mkdocs new .
|
||||||
|
mkdocs serve # live preview at localhost:8000
|
||||||
|
mkdocs build # generate static site
|
||||||
|
mkdocs gh-deploy # push to GitHub Pages
|
||||||
|
```
|
||||||
|
|
||||||
|
`mkdocs.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
site_name: My Project
|
||||||
|
theme:
|
||||||
|
name: material
|
||||||
|
nav:
|
||||||
|
- Home: index.md
|
||||||
|
- API Reference: api.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## What to Document
|
||||||
|
|
||||||
|
Minimum viable docs for any project:
|
||||||
|
|
||||||
|
1. **What it does** — one paragraph
|
||||||
|
2. **How to install** — exact commands, no assumptions
|
||||||
|
3. **How to run** — quickstart example
|
||||||
|
4. **How to develop** — how to run tests, linting, CI locally
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Docs live in the repo — version them alongside the code
|
||||||
|
- A README is documentation; don't skip it even for internal projects
|
||||||
|
- Generate API docs from docstrings (`pdoc`, `pkgsite`) rather than writing them twice
|
||||||
|
- Often skipped, always regretted — write docs when the code is fresh
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# Linting & Formatting
|
||||||
|
|
||||||
|
Catch bugs and style issues automatically — before review, before CI, ideally before saving.
|
||||||
|
|
||||||
|
## Tools by Language
|
||||||
|
|
||||||
|
| Language | Recommended | Alternatives |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | `ruff` | flake8 + isort + black |
|
||||||
|
| JavaScript/TS | `biome` | eslint + prettier |
|
||||||
|
| Go | `gofmt`, `golangci-lint` | staticcheck |
|
||||||
|
| C++ | `clang-tidy`, `clang-format` | cppcheck |
|
||||||
|
|
||||||
|
## Python — `ruff`
|
||||||
|
|
||||||
|
Replaces flake8, isort, and black in one tool. Extremely fast.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ruff check . # lint
|
||||||
|
ruff check --fix . # lint + auto-fix
|
||||||
|
ruff format . # format (replaces black)
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure in `pyproject.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 100
|
||||||
|
target-version = "py312"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["E", "F", "I", "UP"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## JavaScript — `biome`
|
||||||
|
|
||||||
|
Single tool for lint + format, no config needed to start.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
biome check . # lint + format check
|
||||||
|
biome check --write . # auto-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
## Go
|
||||||
|
|
||||||
|
`gofmt` is part of the toolchain — just run it.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gofmt -w .
|
||||||
|
golangci-lint run # broader lint suite
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Run on save in your editor (not just in CI)
|
||||||
|
- Auto-fix on commit via a pre-commit hook or `invoke lint --fix`
|
||||||
|
- Format is non-negotiable; lint violations should be treated as errors in CI
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# Package Management
|
||||||
|
|
||||||
|
Declare dependencies explicitly, resolve them reproducibly, and isolate environments so projects don't interfere.
|
||||||
|
|
||||||
|
## Tools by Language
|
||||||
|
|
||||||
|
| Language | Recommended | Alternatives |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | `uv` | pip, poetry, pipenv |
|
||||||
|
| JavaScript | `pnpm` | npm, yarn |
|
||||||
|
| Go | `go mod` | (built-in, no alternative needed) |
|
||||||
|
| C++ | `conan`, `vcpkg` | cmake FetchContent |
|
||||||
|
|
||||||
|
## Python — `uv`
|
||||||
|
|
||||||
|
Fast resolver with lock files. Drop-in for pip + venv.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# create venv and install
|
||||||
|
uv venv
|
||||||
|
uv pip install -e ".[dev]"
|
||||||
|
|
||||||
|
# add a dependency (updates pyproject.toml + lockfile)
|
||||||
|
uv add requests
|
||||||
|
|
||||||
|
# sync from lock file (reproducible installs)
|
||||||
|
uv sync
|
||||||
|
```
|
||||||
|
|
||||||
|
`pyproject.toml` is the single source of truth for dependencies and tool config (PEP 517/518).
|
||||||
|
|
||||||
|
## JavaScript — `pnpm`
|
||||||
|
|
||||||
|
Faster and more disk-efficient than npm; compatible with npm ecosystem.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install # install from lockfile
|
||||||
|
pnpm add lodash # add dependency
|
||||||
|
pnpm dlx create-vite # run one-off tool
|
||||||
|
```
|
||||||
|
|
||||||
|
## Go — `go mod`
|
||||||
|
|
||||||
|
Built into the toolchain; no extra install needed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod init github.com/you/myproject
|
||||||
|
go get github.com/some/package@v1.2.3
|
||||||
|
go mod tidy # remove unused deps
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Principles
|
||||||
|
|
||||||
|
- Always commit the lock file (`uv.lock`, `pnpm-lock.yaml`, `go.sum`)
|
||||||
|
- Pin to a specific version in production; use ranges only in libraries
|
||||||
|
- Separate dev dependencies from runtime dependencies
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# Task Automation
|
||||||
|
|
||||||
|
One entry point for all dev workflows — so you don't have to remember long commands or teach them to teammates.
|
||||||
|
|
||||||
|
## Tools by Language
|
||||||
|
|
||||||
|
| Language | Recommended | Alternatives |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | `invoke` | make, tox |
|
||||||
|
| JavaScript/TS | `npm scripts`, `turbo` | nx |
|
||||||
|
| Go | `make`, `task` | mage |
|
||||||
|
| C++ | `cmake`, `make` | ninja |
|
||||||
|
|
||||||
|
## Python — `invoke`
|
||||||
|
|
||||||
|
Define tasks in `tasks.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from invoke import task
|
||||||
|
|
||||||
|
@task
|
||||||
|
def lint(c):
|
||||||
|
c.run("ruff check . && mypy .")
|
||||||
|
|
||||||
|
@task
|
||||||
|
def test(c):
|
||||||
|
c.run("pytest")
|
||||||
|
|
||||||
|
@task
|
||||||
|
def ci(c, lint=True, test=True):
|
||||||
|
if lint:
|
||||||
|
lint(c)
|
||||||
|
if test:
|
||||||
|
test(c)
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
invoke lint
|
||||||
|
invoke test
|
||||||
|
invoke ci
|
||||||
|
```
|
||||||
|
|
||||||
|
## Make (universal fallback)
|
||||||
|
|
||||||
|
Works everywhere, no install needed.
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
.PHONY: lint test ci
|
||||||
|
|
||||||
|
lint:
|
||||||
|
ruff check . && mypy .
|
||||||
|
|
||||||
|
test:
|
||||||
|
pytest
|
||||||
|
|
||||||
|
ci: lint test
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make ci
|
||||||
|
```
|
||||||
|
|
||||||
|
## JavaScript — npm scripts
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"lint": "biome check .",
|
||||||
|
"test": "vitest run",
|
||||||
|
"ci": "npm run lint && npm run test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run ci
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Keep task names consistent across projects (`lint`, `test`, `ci`, `build`)
|
||||||
|
- Tasks should call your other tools — they're orchestration, not implementation
|
||||||
|
- `make` is the lowest common denominator; use it when portability matters
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Testing
|
||||||
|
|
||||||
|
Verify behavior automatically so you can change code with confidence.
|
||||||
|
|
||||||
|
## Tools by Language
|
||||||
|
|
||||||
|
| Language | Recommended | Alternatives |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | `pytest` | unittest, hypothesis |
|
||||||
|
| JavaScript/TS | `vitest` | jest, mocha |
|
||||||
|
| Go | `testing` (stdlib) | testify |
|
||||||
|
| C++ | `googletest` | catch2, doctest |
|
||||||
|
|
||||||
|
## Python — `pytest`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pytest # run all tests
|
||||||
|
pytest -x # stop on first failure
|
||||||
|
pytest -k "test_login" # run matching tests
|
||||||
|
pytest --cov=src # with coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
Minimal test:
|
||||||
|
|
||||||
|
```python
|
||||||
|
def add(a: int, b: int) -> int:
|
||||||
|
return a + b
|
||||||
|
|
||||||
|
def test_add():
|
||||||
|
assert add(2, 3) == 5
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure in `pyproject.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
testpaths = ["tests"]
|
||||||
|
addopts = "-ra -q"
|
||||||
|
```
|
||||||
|
|
||||||
|
## JavaScript — `vitest`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vitest run # run once
|
||||||
|
vitest # watch mode
|
||||||
|
vitest --coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
## Go
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go test ./... # run all tests
|
||||||
|
go test -race ./... # with race detector
|
||||||
|
go test -cover ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Principles
|
||||||
|
|
||||||
|
- Test behavior, not implementation — tests that break on refactors aren't useful
|
||||||
|
- Fast tests get run; slow tests get skipped
|
||||||
|
- Don't mock more than necessary — integration tests catch what unit tests miss
|
||||||
|
- Add a test when you fix a bug; the bug was a missing test
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# Type Checking
|
||||||
|
|
||||||
|
Catch type mismatches at analysis time, not at runtime. Especially valuable in large codebases and across refactors.
|
||||||
|
|
||||||
|
## Tools by Language
|
||||||
|
|
||||||
|
| Language | Tool | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Python | `mypy`, `pyright` | not built-in; add type hints manually |
|
||||||
|
| JavaScript/TS | `tsc`, `flow` | TypeScript is the dominant choice |
|
||||||
|
| Go | built-in | the compiler enforces types |
|
||||||
|
| C++ | built-in + `clang-tidy` | compiler + static analysis |
|
||||||
|
|
||||||
|
## Python — `mypy`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mypy src/
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure in `pyproject.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.mypy]
|
||||||
|
python_version = "3.12"
|
||||||
|
strict = true
|
||||||
|
ignore_missing_imports = true
|
||||||
|
```
|
||||||
|
|
||||||
|
Start with `strict = false` and tighten incrementally. Add `# type: ignore` sparingly — only where third-party stubs are missing.
|
||||||
|
|
||||||
|
## TypeScript — `tsc`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tsc --noEmit # type-check without emitting JS
|
||||||
|
```
|
||||||
|
|
||||||
|
`tsconfig.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"target": "ES2022"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Type checking and linting are separate concerns — run both
|
||||||
|
- In Python, annotate function signatures first; body annotations add less value
|
||||||
|
- `pyright` (Pylance) gives faster feedback in VS Code; `mypy` is CI-standard
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Version Control
|
||||||
|
|
||||||
|
Track every change to your code, collaborate without stepping on each other, and roll back anything.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
**Git** is the universal standard. Pair it with a hosting platform for collaboration and access control.
|
||||||
|
|
||||||
|
| Platform | Self-hosted | Cloud |
|
||||||
|
|---|---|---|
|
||||||
|
| GitHub | — | github.com |
|
||||||
|
| GitLab | yes | gitlab.com |
|
||||||
|
| Gitea | yes | — |
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
- **Commit often** — small, atomic commits are easier to review and revert
|
||||||
|
- **Branch per feature** — keeps main stable and deployable at all times
|
||||||
|
- **Merge/rebase before pushing** — resolve conflicts locally, not in CI
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git init
|
||||||
|
git add .
|
||||||
|
git commit -m "initial commit"
|
||||||
|
|
||||||
|
# branch workflow
|
||||||
|
git checkout -b feature/my-thing
|
||||||
|
# ... make changes ...
|
||||||
|
git add -p # stage interactively
|
||||||
|
git commit -m "feat: describe the change"
|
||||||
|
git push origin feature/my-thing
|
||||||
|
```
|
||||||
|
|
||||||
|
## Minimal Config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --global user.name "Your Name"
|
||||||
|
git config --global user.email "you@example.com"
|
||||||
|
git config --global init.defaultBranch main
|
||||||
|
git config --global pull.rebase true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Helpful tools
|
||||||
|
|
||||||
|
- `lazygit`
|
||||||
|
- VSCode Git Graph extension
|
||||||
Reference in New Issue
Block a user