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
..
2026-06-16 12:18:29 +00:00
2026-06-01 04:40:13 +00:00
2026-06-09 20:13:13 +00:00
2026-05-15 12:01:31 +00:00
2026-06-16 13:06:20 +00:00
2026-06-08 08:48:09 +00:00
2026-06-15 22:06:33 +00:00
2026-06-08 14:57:47 +00:00
2026-06-16 13:06:20 +00:00
2026-06-11 21:28:12 +00:00
2026-06-16 13:06:20 +00:00
2026-06-08 09:37:00 +00:00
2026-06-05 16:49:42 +00:00
2026-06-08 14:48:37 +00:00
2026-05-01 22:33:54 +00:00
2026-06-07 16:55:18 +00:00
2026-06-02 13:29:23 +00:00
2026-06-10 09:26:50 +00:00
2026-06-01 04:40:13 +00:00
2026-06-09 20:13:13 +00:00
2026-06-15 22:16:38 +00:00
2026-05-29 15:58:02 +00:00
2026-06-08 09:37:00 +00:00
2026-06-13 13:16:01 +00:00
2026-02-25 08:12:04 +01:00
2026-06-09 19:12:34 +00:00
2026-06-14 16:42:12 +00:00
2026-06-16 13:06:20 +00:00
2026-06-04 22:52:29 +00:00
2026-06-15 22:16:38 +00:00
2026-06-12 12:54:29 +00:00
2026-06-05 10:32:57 +00:00
2026-06-07 16:55:18 +00:00
2026-06-05 10:32:57 +00:00
2026-05-29 07:06:57 +00:00
2026-06-15 03:26:51 +00:00
2026-05-19 17:45:07 +00:00
2026-06-04 22:52:29 +00:00
2026-05-28 15:00:31 +00:00
2026-06-07 16:55:18 +00:00
2026-05-04 06:30:47 +00:00
2026-04-02 17:06:57 -03:00
2026-05-15 11:12:41 +00:00
2026-06-15 10:55:39 +00:00
2026-04-29 10:27:47 +00:00
2026-04-24 10:29:51 +00:00
2026-05-13 23:35:10 +00:00
2026-06-08 15:46:15 +00:00
2026-06-02 13:29:23 +00:00
2026-06-15 07:04:03 +00:00
2026-06-05 11:17:44 +00:00
2026-04-30 11:10:14 +00:00
2026-06-09 12:06:49 +00:00
2026-06-16 13:06:20 +00:00
2026-06-09 15:52:27 +00:00
2026-06-04 18:22:46 +00:00
2026-06-04 22:52:29 +00:00
2026-06-09 20:13:13 +00:00
2026-06-15 11:06:16 +00:00
2026-06-05 19:24:28 +00:00
2026-05-08 10:36:03 +00:00
2026-04-07 12:28:19 -03:00
2026-02-28 21:47:30 -05:00
2026-06-03 13:18:45 +00:00
2026-02-19 18:57:49 +01:00
2026-02-28 22:42:19 -05:00
2026-06-08 19:47:30 +00:00
2026-06-04 11:01:48 +00:00
2026-06-07 16:39:58 +00:00
2026-06-07 16:39:58 +00:00
2026-06-15 11:26:28 +00:00
2026-06-10 10:02:53 +00:00
2026-04-18 06:34:19 +00:00
2026-05-04 06:30:47 +00:00
2026-06-15 03:31:50 +00:00
2026-06-15 10:05:36 +00:00
2026-02-19 18:57:49 +01:00
2026-06-12 12:27:28 +00:00
2026-06-12 12:27:28 +00:00
2026-06-16 14:13:38 +00:00
2026-06-15 08:48:19 +00:00
2026-06-16 13:06:20 +00:00
2026-05-26 13:41:28 +00:00
2026-06-16 13:06:20 +00:00
2026-06-12 14:08:25 +00:00
2026-06-16 13:47:55 +00:00
2026-06-16 13:47:55 +00:00
2026-06-11 21:28:12 +00:00
2026-03-24 11:05:12 +00:00
2026-04-24 08:58:26 +00:00
2026-06-16 13:47:55 +00:00
2026-06-16 13:47:55 +00:00
2026-06-02 12:03:05 +00:00
2026-06-08 23:09:47 +00:00
2026-06-16 13:47:55 +00:00
2026-06-09 03:12:17 +00:00
2026-06-16 13:47:55 +00:00
2026-06-15 22:40:16 +00:00
2026-06-12 03:00:42 +00:00
2026-06-08 21:24:44 +00:00
2026-04-22 22:22:10 +00:00
2026-06-12 12:27:28 +00:00
2026-06-08 14:48:37 +00:00
2026-05-05 22:41:13 +00:00
2026-04-29 10:27:47 +00:00
2026-06-08 15:46:15 +00:00
2026-06-15 11:03:26 +00:00
2026-06-02 13:59:39 +00:00
2026-04-02 12:52:42 +00:00
2026-06-16 13:06:20 +00:00
2026-06-16 13:06:20 +00:00
2026-06-16 13:06:20 +00:00
2026-06-16 13:06:20 +00:00
2026-03-25 12:07:34 -06:00
2026-05-08 10:36:03 +00:00
2026-06-10 09:28:16 +00:00
2026-06-16 13:47:55 +00:00
2026-05-08 10:36:03 +00:00
2026-06-15 22:16:38 +00:00
2026-06-02 13:29:23 +00:00
2026-06-08 21:24:36 +00:00
2026-06-14 12:11:15 +00:00
2026-06-05 11:17:44 +00:00
2026-06-16 12:11:02 +00:00
2026-05-04 22:51:56 +00:00
2026-06-02 12:03:05 +00:00
2026-06-02 13:29:23 +00:00
2026-06-15 11:03:26 +00:00
2026-02-20 13:36:04 +00:00
2026-05-27 04:39:26 +00:00
2026-05-29 07:06:57 +00:00
2026-05-14 21:03:56 +00:00
2026-06-02 13:29:23 +00:00
2026-06-08 14:48:37 +00:00
2026-06-16 13:06:20 +00:00
2026-05-21 03:59:50 +00:00
2026-06-04 11:18:14 +00:00
2026-06-06 20:28:26 +00:00
2026-06-15 11:03:26 +00:00
2026-06-15 11:03:26 +00:00
2026-05-12 15:52:52 +00:00
2026-05-14 16:30:08 +00:00
2026-06-02 08:43:52 +00:00
2026-06-10 12:02:29 +00:00
2026-06-13 05:21:05 +00:00
2026-06-16 13:59:32 +00:00
2026-05-05 22:41:13 +00:00
2026-06-16 09:48:24 +00:00
2026-05-05 22:41:13 +00:00
2026-06-05 19:46:05 +00:00
2026-06-12 12:54:29 +00:00
2026-06-15 09:02:10 +00:00
2026-05-15 21:17:43 +00:00
2026-06-08 09:37:00 +00:00
2026-04-16 16:36:09 -07:00
2026-06-02 12:03:05 +00:00
2026-06-12 14:57:52 +00:00
2026-05-08 21:03:40 +00:00
2026-05-27 10:31:53 +00:00
2026-06-05 10:32:57 +00:00
2026-06-16 12:18:29 +00:00
2026-06-08 15:44:17 +00:00
2026-03-27 14:41:25 +01:00
2026-06-05 19:46:05 +00:00
2026-03-18 12:05:57 -07:00
2026-06-15 14:22:47 +00:00
2026-06-15 22:06:33 +00:00
2026-03-25 12:07:34 -06:00
2026-04-02 00:44:53 +00:00
2026-06-16 03:07:45 +00:00
2026-05-05 16:25:56 +00:00
2026-06-15 21:19:16 +00:00
2026-04-29 10:27:47 +00:00
2026-05-05 22:41:13 +00:00
2026-04-24 10:29:51 +00:00
2026-05-27 19:33:04 +00:00
2026-05-27 10:31:53 +00:00
2026-03-29 14:43:05 +00:00
2026-03-31 08:06:37 -06:00
2026-05-04 06:30:47 +00:00
2026-06-11 03:23:40 +00:00
2026-06-09 22:46:22 +00:00
2026-06-01 17:04:14 +00:00
2026-06-09 12:52:06 +00:00
2026-06-12 12:27:28 +00:00
2026-06-09 20:13:13 +00:00
2026-06-08 14:59:39 +00:00
2026-03-27 14:41:25 +01:00
2026-03-27 14:41:25 +01:00
2026-06-03 13:56:42 +00:00
2026-05-21 22:16:01 +00:00
2026-05-28 19:43:30 +00:00
2026-06-10 12:02:29 +00:00
2026-05-08 10:36:03 +00:00
2026-06-11 21:28:12 +00:00
2026-06-08 14:57:47 +00:00
2026-05-29 07:06:57 +00:00
2026-06-08 14:59:39 +00:00
2026-06-16 13:47:55 +00:00
2026-06-15 14:22:47 +00:00
2026-03-19 12:53:26 -04:00
2026-05-27 10:31:53 +00:00
2026-06-09 12:06:49 +00:00
2026-03-27 14:41:25 +01:00
2026-05-01 22:33:54 +00:00
2026-06-15 14:22:47 +00:00
2026-06-16 14:13:38 +00:00
2026-02-19 18:57:49 +01:00
2026-05-29 16:28:27 +00:00
2026-06-16 12:18:29 +00:00
2026-06-10 12:02:29 +00:00
2026-04-02 17:06:57 -03:00
2026-04-02 17:06:57 -03:00
2026-06-08 22:43:48 +00:00
2026-03-03 08:37:58 +00:00
2026-05-28 20:19:17 +00:00
2026-05-28 20:19:17 +00:00