Version control is not optional for professional data science. Without Git, every “working version” of your notebook is filename_v2_final_FINAL_v3.ipynb. Git tracks every change, lets you experiment safely on branches, collaborate without conflict, and roll back to any previous state instantly. This guide covers Git and GitHub specifically for the data science workflow — notebooks, models, data, and automated pipelines.
Git Fundamentals
# Initial setup (once per machine)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global core.editor "code --wait" # VS Code as editor
# Create a new repository
mkdir ml-project && cd ml-project
git init
# Clone an existing repository
git clone https://github.com/username/repo.git
cd repo
# The three areas: Working Directory → Staging Area → Repository
git status # see what has changed
git add filename.py # stage a specific file
git add . # stage all changes
git commit -m "Add churn model training script"
git commit -am "Quick fix" # stage tracked files + commit in one step
# View history
git log --oneline --graph --all # compact visual history
git log -p filename.py # changes to a specific file
# Undo things
git restore filename.py # discard working directory changes
git restore --staged filename.py # unstage a file
git reset HEAD~1 # undo last commit, keep changes staged
git revert abc1234 # create new commit that undoes abc1234 (safe for shared branches)
Branching Workflow
# Never work directly on main — use feature branches
git switch -c feature/churn-model # create + switch to new branch
git switch main # go back to main
git switch feature/churn-model # switch to existing branch
# Make changes, commit
git add train.py features.py
git commit -m "feat: add gradient boosting churn model"
git commit -m "test: add unit tests for feature engineering"
# Push branch to GitHub
git push -u origin feature/churn-model
# Merge into main (after PR review)
git switch main
git merge feature/churn-model
git push origin main
# Delete branch after merging
git branch -d feature/churn-model
git push origin --delete feature/churn-model
# Rebase (cleaner history than merge for personal branches)
git switch feature/churn-model
git rebase main # replay your commits on top of latest main
# Stash (save work in progress without committing)
git stash # save current changes
git stash pop # restore saved changes
git stash list # see all stashes
.gitignore for Data Science
# .gitignore — never commit these
# Data files (use DVC for large data)
data/raw/
data/processed/
*.csv
*.parquet
*.h5
*.hdf5
# Models (use DVC or model registry)
models/*.pkl
models/*.joblib
*.pt
*.pth
*.onnx
# Jupyter artifacts
.ipynb_checkpoints/
*.ipynb~
# Python
__pycache__/
*.pyc
*.pyo
.env
venv/
.venv/
*.egg-info/
dist/
# Secrets (NEVER commit these)
.env
secrets.yaml
*credentials*
*api_key*
# OS files
.DS_Store
Thumbs.db
# IDE
.vscode/settings.json
.idea/
Data Version Control (DVC)
pip install dvc dvc-s3 # or dvc-gdrive, dvc-azure
# Initialise DVC in a Git repo
dvc init
git commit -m "chore: initialise DVC"
# Track large data files with DVC (not Git)
dvc add data/raw/customers.csv
git add data/raw/customers.csv.dvc .gitignore
git commit -m "data: add raw customer dataset"
# Store data remotely (S3, GCS, Azure, SSH, local)
dvc remote add -d myremote s3://my-bucket/dvc-store
git commit -m "chore: configure DVC remote"
dvc push # upload data to remote
# Pull data on another machine
git clone https://github.com/org/ml-project.git
dvc pull # download data
# Pipeline — track transformations reproducibly
# dvc.yaml
stages:
prepare:
cmd: python src/prepare.py
deps:
- data/raw/customers.csv
- src/prepare.py
outs:
- data/processed/features.parquet
train:
cmd: python src/train.py
deps:
- data/processed/features.parquet
- src/train.py
outs:
- models/churn_model.pkl
metrics:
- metrics/scores.json
dvc repro # run only stages that have changed
dvc dag # visualise the pipeline
GitHub Actions for ML CI/CD
# .github/workflows/ml-pipeline.yml
name: ML Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test-and-train:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest tests/ -v --tb=short
- name: Lint with ruff
run: ruff check src/
- name: Train and evaluate model
run: python src/train.py
env:
MLFLOW_TRACKING_URI: ${{ secrets.MLFLOW_URI }}
- name: Check model performance
run: |
python -c "
import json
with open('metrics/scores.json') as f:
scores = json.load(f)
assert scores['auc'] > 0.85, f'AUC too low: {scores["auc"]}'
assert scores['f1'] > 0.75, f'F1 too low: {scores["f1"]}'
print(f'✅ Model passed: AUC={scores["auc"]:.3f}, F1={scores["f1"]:.3f}')
"
Commit Message Best Practices
# Format: :
# Types: feat, fix, data, model, refactor, test, docs, chore
feat: add SHAP explainability to churn model
fix: correct date parsing in feature pipeline
data: add Q2 2026 customer transactions dataset
model: tune XGBoost hyperparameters via Optuna
refactor: extract feature engineering into reusable module
test: add integration tests for prediction API
docs: update README with new model performance metrics
chore: upgrade scikit-learn to 1.5.0
# One line is enough for small commits
# For larger changes, add a blank line then a body:
feat: add ensemble model combining XGBoost and LightGBM
Stacks XGBoost and LightGBM predictions using logistic regression
meta-learner. Test AUC improved from 0.91 to 0.94 on holdout set.
Closes #42
Conclusion
The data science Git workflow is: always branch from main, commit small and often with descriptive messages, never commit secrets or large data files, use DVC for data and model versioning, and automate testing with GitHub Actions. Teams that adopt this workflow spend less time on “what changed and why did it break” and more time on building better models. Start small — even committing your notebooks properly to Git is a significant improvement over most teams’ current workflow.



