Find a file
Lukas Geiger 2408640e5f
git: Avoid unnecessary git repo rescans when unrelated git files change (#59318)
# Objective

Zed triggers many git rescans whenever an outside git command modifies
files inside `.git` dir. This becomes especially problematic when
working on large repos or doing remote development on machines with slow
filesystems.

## Solution

Events for object writes, hook files, lock files, and the reflogs of
HEAD/branches/remote-tracking branches carry no git changes that Zed
cares about beyond what the ref or events already cover. So changes to
these files shouldn't trigger a full git rescan.

## Testing

I extended the existing unittests to add the additionally ignored
directories and lock files.
I also manually verified the changes by viewing the zed git debug logs
that get generated when running `git gc` on a freshly gc'ed repo.
Previously Zed triggered **7 worktree updates**, with these changes it
was reduced to **a single worktree update** which is due to
`.git/packed-refs` which we can't ignore.

**main:**

```
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:52+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }

2026-06-13T13:56:53+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:53+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }

2026-06-13T13:56:54+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }

2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }

2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }

2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }

2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:56+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
```

**This PR:**

```
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] fetched remotes
2026-06-15T01:19:51+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] load merge details
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }```


## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Reduced number of git operations when repository state changes outside of zed
2026-06-16 14:13:38 +00:00
.agents/skills Add zed-cherry-pick agent skill (#57833) 2026-05-27 19:46:15 +00:00
.cargo livekit: Use our build of libwebrtc.a (#51433) 2026-03-16 10:47:36 +01:00
.cloudflare Staged docs releases (#50136) 2026-04-30 11:10:14 +00:00
.config Increase timeout for test_random_blocks (#50724) 2026-03-04 12:25:12 -05:00
.factory Add humanizer skill for AI writing pattern detection (#50021) 2026-02-24 14:58:52 -06:00
.github Add member to community champions list (#59386) 2026-06-15 21:26:16 +00:00
.zed agent: Remove old edit file tool (#55612) 2026-05-04 09:54:39 +00:00
assets language_models: Add Anthropic-compatible provider support in settings (#50381) 2026-06-12 03:00:42 +00:00
ci Move Nightly release to gh-workflow (#41349) 2025-10-28 13:57:23 -06:00
crates git: Avoid unnecessary git repo rescans when unrelated git files change (#59318) 2026-06-16 14:13:38 +00:00
docs git_ui: Add View File action to Git Panel (#59383) 2026-06-16 03:57:51 +00:00
extensions glsl: Bump to v0.2.4 (#58704) 2026-06-05 23:12:31 +00:00
legal Document provider safety retention for designated Zed-hosted models (#58967) 2026-06-09 21:54:48 +00:00
nix agent: Sanboxing on linux (#58355) 2026-06-16 12:18:29 +00:00
script PR board: Stop touching archived items (#59428) 2026-06-16 13:05:26 +00:00
tooling agent: Sanboxing on linux (#58355) 2026-06-16 12:18:29 +00:00
.git-blame-ignore-revs Add PR 50413 to .git-blame-ignore-revs (#50421) 2026-03-01 00:50:33 +01:00
.gitattributes windows: Make sure zed.sh using the correct line ending (#37650) 2025-09-05 16:25:55 +00:00
.gitignore gpui: Accesskit support (#56065) 2026-05-27 18:17:59 +00:00
.mailmap Update .mailmap (#47413) 2026-01-22 23:57:26 +05:30
.prettierrc ci: Add check for formatting default.json (#30034) 2025-05-06 18:55:26 +00:00
.rules Update AI rules to reflect that AsyncApp updates are now infallible (#54818) 2026-04-24 19:04:32 +00:00
AGENTS.md ai: Symlink an AGENTS.md file to .rules (#45939) 2026-01-19 15:29:42 +01:00
Cargo.lock Remove gpui's dependency on async-process (#59358) 2026-06-16 13:47:55 +00:00
Cargo.toml http_proxy: Add the allowlisting proxy server (#59223) 2026-06-15 21:17:52 +00:00
CLAUDE.md Initial .rules file for agent with symlinks for other rules file paths (#29014) 2025-04-17 23:41:23 +00:00
clippy.toml Revert "Revert scheduler update (#46659)" (#46671) 2026-01-14 07:19:13 +00:00
CODE_OF_CONDUCT.md
compose.yml Remove Postgres and stripe-mock from Docker Compose (#48313) 2026-02-04 03:42:58 +00:00
CONTRIBUTING.md Include icon guidelines in PR templates and contribution docs (#58855) 2026-06-08 17:42:34 +00:00
debug.plist
default.nix nix: Use flake-parts, partitions, and treefmt-nix (#45321) 2026-02-02 14:26:42 +00:00
Dockerfile-collab Bump Rust version to 1.94 (#51086) 2026-03-30 09:06:59 +00:00
Dockerfile-collab.dockerignore
Dockerfile-cross.dockerignore
Dockerfile-distros Removal of mold/wild scripts and mentions in docs (#53078) 2026-04-08 21:20:02 +03:00
Dockerfile-distros.dockerignore
flake.lock Rust 1.95 (#55104) 2026-04-29 10:27:47 +00:00
flake.nix ci: Remove garnix substitutor (#58033) 2026-05-29 05:56:42 +00:00
GEMINI.md Add missing GEMINI.md rule file for gemini-cli (#38885) 2025-10-02 09:47:29 -04:00
LICENSE-APACHE
LICENSE-GPL
livekit.yaml
lychee.toml ci: Check for broken links (#30844) 2025-06-06 09:39:35 +00:00
Procfile Update instructions for local collaboration (#35689) 2025-08-06 11:10:28 -07:00
Procfile.all Add agent thread sharing (#46140) 2026-01-06 12:49:51 -08:00
Procfile.web Remove PostgREST (#41299) 2025-10-27 13:27:59 -04:00
README.md Relicense Zed source code under GPL (#57948) 2026-05-28 20:19:17 +00:00
renovate.json Remove workspace-hack (#40216) 2025-10-17 18:58:14 +00:00
REVIEWERS.conl Remove past reviewer (#51767) 2026-03-17 16:34:35 +00:00
rust-toolchain.toml Rust 1.95 (#55104) 2026-04-29 10:27:47 +00:00
rustfmt.toml nix: Use flake-parts, partitions, and treefmt-nix (#45321) 2026-02-02 14:26:42 +00:00
sandbox-bubblewrap-next-steps.md agent: Sanboxing on linux (#58355) 2026-06-16 12:18:29 +00:00
shell.nix nix: Use flake-parts, partitions, and treefmt-nix (#45321) 2026-02-02 14:26:42 +00:00
typos.toml markdown: Merman (#57644) 2026-05-27 16:27:18 +00:00

Zed

Zed CI

Welcome to Zed, a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.


Installation

On macOS, Linux, and Windows you can download Zed directly or install Zed via your local package manager (macOS/Linux/Windows).

Other platforms are not yet available:

Developing Zed

Contributing

See CONTRIBUTING.md for ways you can contribute to Zed.

Also... we're hiring! Check out our jobs page for open roles.

Licensing

Zed source code is licensed primarily under GPL-3.0-or-later, with Apache-2.0 components where marked.

License information for third party dependencies must be correctly provided for CI to pass.

We use cargo-about to automatically comply with open source licenses. If CI is failing, check the following:

  • Is it showing a no license specified error for a crate you've created? If so, add publish = false under [package] in your crate's Cargo.toml.
  • Is the error failed to satisfy license requirements for a dependency? If so, first determine what license the project has and whether this system is sufficient to comply with this license's requirements. If you're unsure, ask a lawyer. Once you've verified that this system is acceptable add the license's SPDX identifier to the accepted array in script/licenses/zed-licenses.toml.
  • Is cargo-about unable to find the license for a dependency? If so, add a clarification field at the end of script/licenses/zed-licenses.toml, as specified in the cargo-about book.

Sponsorship

Zed is developed by Zed Industries, Inc., a for-profit company.

If youd like to financially support the project, you can do so via GitHub Sponsors. Sponsorships go directly to Zed Industries and are used as general company revenue. There are no perks or entitlements associated with sponsorship.