Skip to main content

How to Keep MLflow Files Out of Git with .gitignore

· 8 min read
Jagdish Kumawat
Founder @ Dewiride

MLflow sometimes writes its own files into your project: an mlflow.db database when your code runs without a tracking URI, an mlruns folder for the files those runs log, and an mlartifacts folder if you start a tracking server there. None of them belong in Git. This guide shows how they appear, adds three lines to .gitignore, and proves that Git ignores them.

Syntax​

A .gitignore file lists one pattern per line. The rules come from Git's documentation:

Syntax
# a comment
<name>
<folder>/
*.<extension>
!<pattern>
LineWhat it matches
# ...Nothing: "A line starting with # serves as a comment"
<name>Every file or folder with that name, in the .gitignore's folder or any folder below it
<folder>/Only folders: with a slash at the end, "the pattern will only match directories"
*.<extension>Any name that ends that way. In Git's words, * "matches anything except a slash"
!<pattern>Brings back something an earlier line excluded. It can't bring back a file whose folder is excluded

Prerequisites​

The project here, mlflow-demo, holds a few MLflow scripts, and everything in it is committed.

Step 1: See How MLflow Files Get Into a Project​

This script logs a run but never says where to send it:

log_without_uri.py
import mlflow

with mlflow.start_run() as run:
mlflow.log_param("color", "blue")

print("Logged run", run.info.run_id)
print("It went to:", mlflow.get_tracking_uri())
Terminal
uv run python log_without_uri.py
Output
2026/11/13 17:06:34 INFO mlflow.store.db.utils: Creating initial MLflow database tables...
2026/11/13 17:06:34 INFO mlflow.store.db.utils: Updating database tables
Logged run b3072508b3af4707a001b40d46cf6f12
It went to: sqlite:////Users/you/source/mlflow-demo/mlflow.db

With no tracking URI set, MLflow 3.18 created a database, mlflow.db, in the folder the script ran from. How to Set the MLflow Tracking URI in Python explains why. Git noticed the new file at once:

Terminal
git status --short
Output
?? mlflow.db

?? means untracked: a new file Git doesn't know about yet. A run that logs a file adds a folder too:

log_artifact_without_uri.py
import mlflow

with mlflow.start_run() as run:
mlflow.log_text("Trained on the California Housing data.", "notes/about.txt")

print("Artifacts went to:", run.info.artifact_uri)
Terminal
uv run python log_artifact_without_uri.py
git status --short --untracked-files=all
Output
Artifacts went to: /Users/you/source/mlflow-demo/mlruns/0/5ccedcc4224b438bb4e5fff34dcb96ab/artifacts
?? mlflow.db
?? mlruns/0/5ccedcc4224b438bb4e5fff34dcb96ab/artifacts/notes/about.txt

The text file went into mlruns/0/<run ID>/artifacts, inside the project. --untracked-files=all makes Git list each file inside new folders, not just the folder; Git's documentation describes it as "Also show individual files in untracked directories." One git add . would now commit MLflow's data along with your code.

Step 2: Add the MLflow Lines to .gitignore​

Open .gitignore in the project's top folder and add these lines at the end:

.gitignore (add at the end)
# MLflow: local tracking database and artifact folders
mlflow.db
mlruns/
mlartifacts/
  • mlflow.db: the database MLflow creates when no tracking URI is set.
  • mlruns/: where those runs keep their files.
  • mlartifacts/: a tracking server's file store, in case you ever start a server inside the project.
  • The / at the end makes a line match folders only. Git's documentation: "If there is a separator at the end of the pattern then the pattern will only match directories".

mlflow-demo's whole .gitignore now reads:

.gitignore
.venv/

# MLflow: local tracking database and artifact folders
mlflow.db
mlruns/
mlartifacts/

Yours may have more lines, such as the ones uv init creates. That's fine: order doesn't matter here.

Step 3: Check That Git Ignores Them​

git check-ignore -v says which .gitignore line matches each path you give it:

Terminal
git check-ignore -v mlflow.db mlruns/0/5ccedcc4224b438bb4e5fff34dcb96ab/artifacts/notes/about.txt
Output
.gitignore:4:mlflow.db mlflow.db
.gitignore:5:mlruns/ mlruns/0/5ccedcc4224b438bb4e5fff34dcb96ab/artifacts/notes/about.txt

Each line reads file:line number:pattern, then the path it matched: line 4, mlflow.db, ignores the database, and line 5, mlruns/, ignores the text file inside the folder. Your line numbers depend on your .gitignore. A path that no line matches prints nothing.

Now ask Git what's left:

Terminal
git status --short --untracked-files=all
Output
M .gitignore

A macOS-style terminal window: git status lists mlflow.db and a file inside mlruns as untracked, git check-ignore -v shows .gitignore lines 4 and 5 matching them, and a second git status shows only the modified .gitignore.

The MLflow files are gone from the list. The only change is .gitignore itself, marked M for modified.

Step 4: Commit the .gitignore​

Terminal
git add .gitignore
git commit -m "Keep MLflow files out of Git"

Then check which commit last changed .gitignore:

Terminal
git log --oneline -1 -- .gitignore
Output
08ee202 Keep MLflow files out of Git

--oneline prints each commit's short ID and message, -1 only the newest, and -- .gitignore only commits that changed that file. From now on, every clone of the repository ignores MLflow's files too, because .gitignore travels with the code.

Common Mistakes​

MistakeWhat happensDo this instead
Adding the lines after mlflow.db was already committedGit keeps tracking it; .gitignore doesn't affect tracked filesStop tracking it with git rm --cached mlflow.db, then commit
Ignoring *.dbEvery database file in the project is ignored, including ones you meant to commitName mlflow.db exactly
Committing mlflow.db to share runs with a teammateEach run changes the database, so commits and merges fill up with itShare runs through a tracking server instead

Troubleshooting​

SymptomLikely causeFix
mlflow.db still shows in git statusIt was committed before the line was addedgit rm --cached mlflow.db, then commit
git check-ignore -v prints nothing for a pathNo line matches it, often because of a typoCheck the spelling in .gitignore
A new mlflow.db keeps appearing in the projectYour code runs without a tracking URISet it: How to Set the MLflow Tracking URI in Python

FAQ​

What does git rm --cached do to my file?​

It removes the file from Git's index, so Git stops tracking it, and leaves the file on disk. Git's documentation: "To stop tracking a file that is currently tracked, use git rm --cached to remove the file from the index."

Should my tracking server's folder be in Git?​

No. Keep the server in a folder outside your projects, as How to Start an MLflow Tracking Server on Your Computer does, and keep its mlflow.db and mlartifacts out of every repository.

Where do MLflow's files go when I use a server?​

Into the server's folder, not your project's: How to See Where MLflow Stores Runs and Artifacts.

Conclusion​

A script with no tracking URI created mlflow.db and mlruns/ inside the project, and Git listed both as untracked. Three lines in .gitignore, mlflow.db, mlruns/ and mlartifacts/, fixed it: git check-ignore -v showed the matching lines, and git status was left with only the .gitignore change to commit.

Additional Resources​

  • gitignore — the pattern rules, and why tracked files aren't affected.
  • git check-ignore — finding the line that ignores a path.
  • git status — --untracked-files and the short format.