git: Fix git info exclude action for worktrees (#63967)

# Objective

- This PR fixes #63760. According to git docs "Patterns read from
$GIT_DIR/info/exclude".

## Solution

- We were reading the directory's absolute path instead of reading the
absolute path to the repository's common .git directory.


## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] 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)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed "Add to .git/info/exclude" not working when used from a
secondary git worktree

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
Matei OpreaandSmit Barmase authored and GitHub committed 2026-09-18 10:24:51 +00:00
1 parent 94c997e06f
commit 6b95ac3d33
2 files changed
+87 -1

No files matched your search

+1 -1
View File
@@ -8413,7 +8413,7 @@ impl Repository {
is_dir: bool,
) -> oneshot::Receiver<Result<()>> {
let id = self.id;
let repository_dir = self.snapshot.repository_dir_abs_path.clone();
let repository_dir = self.snapshot.common_dir_abs_path.clone();
let path_display = repo_path.as_ref().display(PathStyle::Unix);
let path = repo_path.as_unix_str().to_owned();
let file_path_str = if is_dir {
@@ -3702,6 +3702,92 @@ async fn test_add_path_to_git_info_exclude_in_remote_repository(
);
}
#[gpui::test]
async fn test_add_path_to_git_info_exclude_in_remote_linked_worktree(
cx: &mut TestAppContext,
server_cx: &mut TestAppContext,
) {
let fs = FakeFs::new(server_cx.executor());
fs.insert_tree(
"/project",
json!({
".git": {
"HEAD": "ref: refs/heads/main",
"config": "[core]\n\tbare = false\n",
"info": {
"exclude": "existing\n",
},
"worktrees": {
"linked": {
"HEAD": "ref: refs/heads/linked",
"commondir": "../..",
"gitdir": "/worktree/.git",
},
},
},
}),
)
.await;
fs.insert_tree(
"/worktree",
json!({
".git": "gitdir: ../project/.git/worktrees/linked\n",
"logs": {
"app.log": "",
},
"tmp.txt": "",
}),
)
.await;
let repository_dir = Path::new("/project/.git/worktrees/linked");
fs.set_branch_name(repository_dir, Some("linked"));
fs.set_head_for_repo(repository_dir, &[], "head-sha");
let (project, _headless) = init_test(&fs, cx, server_cx).await;
project
.update(cx, |project, cx| {
project.find_or_create_worktree(Path::new("/worktree"), true, cx)
})
.await
.expect("should open remote linked worktree");
cx.run_until_parked();
let repository = project.read_with(cx, |project, cx| {
project
.active_repository(cx)
.expect("remote linked worktree should have an active repository")
});
for (path, is_dir) in [("tmp.txt", false), ("logs", true), ("tmp.txt", false)] {
let repo_path = RepoPath::new(path).expect("path should be a valid repo path");
cx.update(|cx| {
repository.update(cx, |repository, _| {
repository.add_path_to_git_info_exclude(&repo_path, is_dir)
})
})
.await
.expect("add to info/exclude request should complete")
.expect("add to info/exclude should succeed for remote linked worktree");
}
server_cx.run_until_parked();
cx.run_until_parked();
assert_eq!(
fs.load(Path::new("/project/.git/info/exclude"))
.await
.expect("shared info/exclude should be readable"),
"existing\ntmp.txt\nlogs/\n"
);
assert!(
fs.metadata(&repository_dir.join("info/exclude"))
.await
.expect("worktree-specific info/exclude metadata should be readable")
.is_none(),
"the action should not create a worktree-specific info/exclude"
);
}
#[gpui::test]
async fn test_remote_git_diffs(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
let text_2 = "