# Upgrading to Projectile 3.1

Projectile 3.1 is a feature release and, unlike 3.0, it removes nothing and breaks no public API - every command and option from 3.0 still works. Most setups need no changes at all.

What this page covers is the short list of behavior changes: a few defaults that flipped and a couple of places where existing behavior was made more correct. If something in Projectile started behaving differently after the upgrade, you’ll most likely find it (and how to restore the old behavior) here.

Tip | For the full list of what’s new, see the changelog. This page is only the "what changed under me" part.

## `.projectile` glob patterns now follow gitignore rules

This is the change most likely to affect an existing configuration, so it’s first.

If your `.projectile` file uses glob ignore/unignore entries - the ones without a leading slash, like `-tmp`, `-*.log` or `-build` - the way they match changed. Matching is now modeled on `.gitignore` and is identical under the `native` and `hybrid` indexing methods (previously `native` used a loose string-suffix match and `hybrid` ignored these patterns entirely).

Concretely:

- A pattern without a slash matches the file name or any directory segment at any depth. `-build` now ignores a `build` directory or file anywhere, but no longer matches `mybuild` (the old suffix match did).

- A pattern with a slash is anchored at the project root. Prefix it with `**/` to match at any depth.

- A trailing slash restricts the match to directories (and their contents).

- `` stops at a `/`; use `*` to cross directory boundaries.

Two consequences worth checking:

- If you relied on the old loose suffix match (e.g. `-build` catching `mybuild`), spell it out now (`-mybuild`, or a `*` glob).

- Under `hybrid` indexing your glob patterns are now actually applied, so files you thought were being ignored (but weren’t) will disappear from the listing. That’s the fix, but it can look like files "went missing" - they’re just finally being ignored as intended.

The `alien` method still ignores `.projectile` entirely by design and warns once per project when a non-empty `.projectile` is present. Switch to `hybrid` (or `native`) if you want the rules applied.

## Project detection is now case-sensitive about marker files

Root and project-type detection now match marker files exactly, even on case-insensitive filesystems (macOS, Windows). Previously a marker like `Makefile` would also match a file named `makefile` on those systems but not on Linux.

In practice this only surfaces if a project’s marker file is spelled with different casing than Projectile expects. Two related fixes came with it: the `gnumake` type now looks for GNU make’s actual `GNUmakefile` (it previously had a typo’d `GNUMakefile`), and the `make` type recognizes a lowercase `makefile` in addition to `Makefile`. If a project stopped being detected, check the exact casing of its marker file and, if needed, register a type for it (see the Projects page).

## Automatic project discovery is on by default

`projectile-auto-discover` now defaults to `t` (the option was renamed to `projectile-auto-discover-projects` in 3.4; the old name still works). It has no effect unless you’ve also set `projectile-project-search-path`, so nothing changes out of the box - but if you had set a search path and deliberately left auto-discovery off, you’ll now get it.

The historical reason it was off - discovery re-walking the search path on every project switch - is gone: the scan now runs once per session, on the first project-switch command. Remote (TRAMP) search-path entries are skipped so an unreachable host can’t stall a switch.

To keep the old behavior:

    (setq projectile-auto-discover-projects nil)

## `projectile-find-file` orders by frecency

`projectile-find-file` (and `projectile-find-file-dwim`) now put the files you visit most often and most recently at the top of the completion list, learning from your visits over time. This is on by default.

The ordering is applied as completion metadata, so it composes with whatever completion UI you use. If you prefer the previous order (whatever your indexing method and `projectile-sort-order` produce):

    (setq projectile-enable-frecency nil)

## User errors no longer enter the debugger

Conditions that are really user errors - no project found, an optional package not installed, no other file to toggle to, and so on - now signal `user-error` instead of `error`. With `debug-on-error` enabled they no longer pop the debugger for these expected situations.

If you have code that wraps a Projectile command in `condition-case` and only handles `error`, catch `user-error` too (or use `t`):

    (condition-case nil
        (projectile-find-file)
      (user-error (message "no project"))
      (error (message "something else went wrong")))

## `projectile-find-other-file` matches the extension boundary exactly

`projectile-find-other-file` no longer treats the dot before a file’s extension as a wildcard when finding the "other" files, so `foo.el` will not match an unrelated name like `fooXel`. If you saw spurious matches before, they’re gone.

## Removed internal functions

`projectile-check-pattern-p` and `projectile-ignored-rel-p` were removed - they were the old `.projectile` pattern matchers, superseded by the compiled gitignore-style matcher. They were never part of the documented API; this only matters if some third-party code called them directly.