This PR finishes up the support for generating commit messages using an
LLM.
We're shelling out to `git diff` to get the diff text, as it seemed more
efficient than attempting to reconstruct the diff ourselves from our
internal Git state.
https://github.com/user-attachments/assets/9bcf30a7-7a08-4f49-a753-72a5d954bddd
Release Notes:
- Git Beta: Added support for generating commit messages using a
language model.
---------
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Release Notes:
- Git Beta: Fixed a bug where discarding a hunk in the project diff view
performed two concurrent saves of the buffer.
- Git Beta: Fixed an issue where diff hunks appeared in the wrong state
after failing to write to the git index.
Closes#25976
There's a couple states that this covers:
- upon `git init`, no footer is shown at all
- after 1 commit (or when on any parentless commit), the uncommit button
is ~disabled~ hidden
- otherwise commit button is shown
Also updated the button with "meta" tooltip showing human readable
description and git command.
Release Notes:
- N/A
---------
Co-authored-by: Nate Butler <iamnbutler@gmail.com>
Attempt to fix an issue where conflicts from a cherry-pick don't get
cleared out of the git panel after being resolved.
Release Notes:
- Git Beta: Fixed resolution of conflicts from cherry-picks not being
reflected in the git panel
This PR adds toasts for reporting success and errors from remote git
operations. This PR also adds a focus handle to notifications, in
anticipation of making them keyboard accessible.
Release Notes:
- N/A
---------
Co-authored-by: julia <julia@zed.dev>
### Problem
When using HTTPS remotes, users are getting errors when trying to push
or pull via the git panel.
On macOS, Zed bundles a `git` binary that's part of
[`dugite-native`](https://github.com/desktop/dugite-native). But we
don't include the entire package. Additional binaries from
`dugite-native` are needed for pulling and pushing over HTTPS.
### Solution
Rather than bundling those additional binaries, I've changed the `push`,
`pull`, and `fetch` actions to rely on the *system-installed* `git`
binary. The downside of this is that, if the user does not have Git
installed, they wont' be able to push, pull, or fetch from within Zed.
But we believe that the vast majority of users will have Git installed.
Also, unlike `diff` and `status`, which Zed needs to call in the
background without any user interaction, `push`/`pull` and `fetch` are
explicit actions that the user takes in Zed, so there is an opportunity
to prompt them to install Git if they haven't.
### Background
There are three ways (that I know of) that users might authenticate when
pushing, pulling, or fetching over HTTPS.
1. Via a built-in [Git
`credential.helper`](https://git-scm.com/docs/gitcredentials). On macOS,
Git ships with a helper called `credential-osxkeychain` that stores
internet passwords in the OS Keychain. You can opt into this globally
with the command `git config --global credential.helper osxkeychain`,
which writes to your `~/.gitconfig`.
2. Via [`Git Credential Manager`
(GCM)](https://github.com/git-ecosystem/git-credential-manager), which
is a different `credential.helper`, [built by
GitHub](https://github.blog/security/application-security/git-credential-manager-authentication-for-everyone/),
which must be installed manually, and integrates with specific Git
hosting providers like GitHub and Azure.
3. By typing their Username and Password/Access-token interactively when
pushing/pulling/fetching.
### Testing Status
* [ ] 🚫 Interactive password auth - not yet supported, requires
https://github.com/zed-industries/zed/pull/25848
* [x] **credential-osxkeychain** - when using the built-in credential
helper, and the credentials are already stored in the keychain,
push/pull/fetch now work fine .
* [ ] **GCM** - still testing.
* Right now, I'm seeing `git-credential-manager` just hang indefinitely
when pushing from Zed, even though it works when pushing from a
terminal.
Release Notes:
- N/A
This PR updates the ui of the git panel. It removes the header from the
panel and unifies the repository, branch and commit controls in the
bottom section.
It also adds a secondary menu to the primary button giving access to a
variety of actions for managing local and remote changes:

Known issues (will be fixed in a later pr)
- Spinner showing git operation progress was removed, will be re-added
- Clicking expand with the panel editor focused will commit (due to
shared action name. Already tracked)
Before | After

(Also adds `component`, `linkme` to cargo-machete ignore as they are
used in the `IntoComponent` proc-macro and will always be incorrectly
flagged as unused)
Release Notes:
- N/A
---------
Co-authored-by: Cole Miller <m@cole-miller.net>
Co-authored-by: Cole Miller <53574922+cole-miller@users.noreply.github.com>
Co-authored-by: Cole Miller <cole@zed.dev>
This was originally a part of another PR, but I wanted to get the
refactoring in and shift focus to working on bugs.
This causes all git commands via the `Repository` entity to be
serialized, and allows us to return values other than `Result<()>`
Release Notes:
- N/A
For symlinks, return `None` from `load_committed_text` as we do from
`load_index_text` ever since #10037.
Release Notes:
- Fixed diff hunks appearing in unchanged symlinked files
Adds the non-entry specific right click menu to the panel, and the
features contained therin:
* Stage all
* Discard Tracked Changes
* Trash Untracked Files
Also changes the naming from "Changes"/"New" to better match Git's
terminology (though not convinced on this, it was awkward to describe
"Discard Changes" without a way to distinguish between the changes and
the files containing them).
Release Notes:
- N/A
`refs/heads/*` doesn't match e.g. `refs/heads/cole/branch-with-slash`
(thanks fnmatch), but `refs/heads/**/*` does. This also works for
several levels of slash.
Release Notes:
- N/A
- [x] Staging hunks
- [x] Unstaging hunks
- [x] Write a randomized test
- [x] Get test passing
- [x] Fix existing bug in diff_base_byte_range computation
- [x] Remote project support
- [ ] ~~Improve performance of
buffer_range_to_unchanged_diff_base_range~~
- [ ] ~~Bug: project diff editor scrolls to top when staging/unstaging
hunk~~ existing issue
- [ ] ~~UI~~ deferred
- [x] Tricky cases
- [x] Correctly handle acting on multiple hunks for a single file
- [x] Remove path from index when unstaging the last staged hunk, if
it's absent from HEAD, or staging the only hunk, if it's deleted in the
working copy
Release Notes:
- Add `ToggleStagedSelectedDiffHunks` action for staging and unstaging
individual diff hunks
Git Panel updates:
* Fixes commit/commit all button to work (and be disabled correctly in
merge conflict status)
* Updates keyboard shortcuts and sets focus on the button (enter now
does the same as click; tab cycles between editor and change list)
Closes #ISSUE
Release Notes:
- N/A *or* Added/Fixed/Improved ...
---------
Co-authored-by: Cole Miller <cole@zed.dev>
Rework of https://github.com/zed-industries/zed/pull/24130
Uses
1033c0b57e
`COMMIT_EDITMSG` language-related definitions (thanks @d1y )
Instead of using real `.git/COMMIT_EDITMSG` file, create a buffer
without FS representation, stored in the `Repository` and shared the
regular way via the `BufferStore`.
Adds a knowledge of what `Git Commit` language is, and uses it in the
buffers which are rendered in the git panel.
Release Notes:
- N/A
---------
Co-authored-by: Conrad Irwin <conrad@zed.dev>
Co-authored-by: d1y <chenhonzhou@gmail.com>
Co-authored-by: Smit <smit@zed.dev>
- **Base diffs on uncommitted changes**
- **Show added files in project diff view**
- **Fix git panel optimism**
Release Notes:
- Git: update diffs to be relative to HEAD instead of the index; to pave
the way for showing which hunks are staged
---------
Co-authored-by: Cole <cole@zed.dev>
This PR builds on #21258 to make it possible to use HEAD as a diff base.
The buffer store is extended to support holding multiple change sets,
and collab gains support for synchronizing the committed text of files
when any collaborator requires it.
Not implemented in this PR:
- Exposing the diff from HEAD to the user
- Decorating the diff from HEAD with information about which hunks are
staged
`test_random_multibuffer` now fails first at `SEED=13277`, similar to
the previous high-water mark, but with various bugs in the multibuffer
logic now shaken out.
Release Notes:
- N/A
---------
Co-authored-by: Max <max@zed.dev>
Co-authored-by: Ben <ben@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
https://github.com/user-attachments/assets/200b88b8-249a-4841-97cd-fda8365efd00
Now all users in the collab/ssh session can edit the commit input
collaboratively, observing each others' changes live.
A real `.git/COMMIT_EDITMSG` file is opened, which automatically enables
its syntax highlight, but its original context is never used or saved on
disk — this way we avoid stale commit messages from previous commits
that git places there.
A caveat: previous version put some effort into preserving unfinished
commit messages on repo swtiches, but this version would not do that
— instead, it will be blank on startup, and use whatever
`.git/COMMIT_EDITMSG` contents on repo switch
Release Notes:
- N/A
---------
Co-authored-by: Cole Miller <cole@zed.dev>
Follow-up of https://github.com/zed-industries/zed/pull/23869
* Retrieves user + email for collab project clients and use these when
such users commit
Same as in https://github.com/zed-industries/zed/pull/23329, "is it the
right user name and e-mail" and "how to override these" questions apply.
* If this data is unavailable, forbid committing to the remote client
* Forbid running related actions in git panel, if committing/writing is
not permitted
Release Notes:
- N/A
There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:
- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`
Not pictured here are the two other failed attempts. It's been quite a
month!
Tasks:
- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs
### issues post merge
- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue
Release Notes:
- N/A
---------
Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
- [x] Basic implementation
- [x] Disable commit buttons when committing is not possible (empty
message, no changes)
- [x] Upgrade GitSummary to efficiently figure out whether there are any
staged changes
- [x] Make CommitAll work
- [x] Surface errors with toasts
- [x] Channel shutdown
- [x] Empty commit message or no changes
- [x] Failed git operations
- [x] Fix added files no longer appearing correctly in the project panel
(GitSummary breakage)
- [x] Fix handling of commit message
Release Notes:
- N/A
---------
Co-authored-by: Nate <nate@zed.dev>
First, parse the output of `git status --porcelain=v1` into a
representation that can handle the full "grammar" and doesn't lose
information.
Second, as part of pushing this throughout the codebase, expand the use
of the existing `GitSummary` type to all the places where status
propagation is in play (i.e., anywhere we're dealing with a mix of files
and directories), and get rid of the previous `GitSummary ->
GitFileStatus` conversion.
- [x] Synchronize new representation over collab
- [x] Update zed.proto
- [x] Update DB models
- [x] Update `GitSummary` and summarization for the new `FileStatus`
- [x] Fix all tests
- [x] worktree
- [x] collab
- [x] Clean up `FILE_*` constants
- [x] New collab tests to exercise syncing of complex statuses
- [x] Run it locally and make sure it looks good
Release Notes:
- N/A
---------
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Conrad <conrad@zed.dev>
This fixes a bug that prevents unstaging added files.
I've also removed the batching/debouncing logic in the long-running task
that launches the git invocations---I added this originally but I don't
think it's really necessary.
Release Notes:
- N/A
TODO:
- [ ] Investigate incorrect hit target for `stage all` button
- [ ] Add top level context menu
- [ ] Add entry context menus
- [x] Show paths in list view
- [ ] For now, `enter` can just open the file
- [ ] 🐞: Hover deadzone in list caused by scrollbar
- [x] 🐞: Incorrect status/nothing shown when multiple worktrees are
added
---
This PR continues work on the feature flagged git panel.
Changes:
- Defines and wires up git panel actions & keybindings
- Re-scopes some actions from `git_ui` -> `git`.
- General git actions (StageAll, CommitChanges, ...) are scoped to
`git`.
- Git panel specific actions (Close, FocusCommitEditor, ...) are scoped
to `git_panel.
- Staging actions & UI are now connected to git!
- Unify more reusable git status into the GitState global over being
tied to the panel directly.
- Uses the new git status codepaths instead of filtering all workspace
entries
Release Notes:
- N/A
---------
Co-authored-by: Cole Miller <53574922+cole-miller@users.noreply.github.com>
Co-authored-by: Cole Miller <cole@zed.dev>
- [x] Rewrite worktree git handling
- [x] Fix tests
- [x] Fix `test_propagate_statuses_for_repos_under_project`
- [x] Replace `WorkDirectoryEntry` with `WorkDirectory` in
`RepositoryEntry`
- [x] Add a worktree event for capturing git status changes
- [x] Confirm that the local repositories are correctly updating the new
WorkDirectory field
- [x] Implement the git statuses query as a join when pulling entries
out of worktree
- [x] Use this new join to implement the project panel and outline
panel.
- [x] Synchronize git statuses over the wire for collab and remote dev
(use the existing `worktree_repository_statuses` table, adjust as
needed)
- [x] Only send changed statuses to collab
Release Notes:
- N/A
---------
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.com>
Co-authored-by: Nathan <nathan@zed.dev>
This adds support for [git
worktrees](https://matklad.github.io/2024/07/25/git-worktrees.html). It
fixes the errors that show up (git blame not working) and actually adds
support for detecting git changes in a `.git` folder that's outside of
our path (and not even in the ancestor chain of our root path).
(While working on this we discovered that our `.gitignore` handling is
not 100% correct. For example: we do stop processing `.gitignore` files
once we found a `.git` repository and don't go further up the ancestors,
which is correct, but then we also don't take into account the
`excludesFile` that a user might have configured, see:
https://git-scm.com/docs/gitignore)
Closes https://github.com/zed-industries/zed/issues/19842
Closes https://github.com/zed-industries/zed/issues/4670
Release Notes:
- Added support for git worktrees. Zed can now open git worktrees and
the git status in them is correctly handled.
---------
Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Bennet <bennet@zed.dev>
***Update**: after rebasing on top of
https://github.com/zed-industries/zed/pull/16915/ (that also changed how
search worked), the results are still good, but not 10x. Instead of
going from 10s to 500ms, it goes from 10s to 3s.*
This improves the performance of project-wide search by an order of
magnitude.
After digging in, @as-cii and I found that opening buffers was the
bottleneck for project-wide search (since Zed opens, parses, ... buffers
when finding them, which is something VS Code doesn't do, for example).
So this PR improves the performance of opening multiple buffers at once.
It does this by doing two things:
- It batches scan-requests in the worktree. When we search, we search
files in chunks of 64. Previously we'd handle all 64 scan requests
separately. The new code checks if the scan requests can be batched and
if so it, it does that.
- It batches `git status` calls when reloading the project entries for
the opened buffers. Instead of calling `git status` for each file, it
calls `git status` for a batch of files, and then extracts the status
for each file.
(It has to be said that I think the slow performance on `main` has been
a regression introduced over the last few months with the changes made
to project/worktree/git. I don't think it was this slow ~5 months ago.
But I also don't think it was this fast ~5 months ago.)
## Benchmarks
| Search | Before | After (without
https://github.com/zed-industries/zed/pull/16915) | After (with
https://github.com/zed-industries/zed/pull/16915)
|--------|--------|-------|------|
| `zed.dev` at `2b2a501192e78e`, searching for `<` (`4484` results) |
3.0s<br>2.9s<br>2.89s | 489ms<br>517ms<br>476ms | n/a |
| `zed.dev` at `2b2a501192e78e`, searching for `:` (`25886+` results) |
3.9s<br>3.9s<br>3.8s | 70ms<br>66ms<br>72ms | n/a |
| `zed` at `55dda0e6af`, searching for `<` (`10937+` results) |
10s<br>11s<br>12s | 500m<br>499ms<br>543ms | 3.4s<br>3.1s<br> |
(All results recorded after doing a warm-up run that would start
language servers etc.)
Release Notes:
- Performance of project-wide search has been improved by up to 10x.
---------
Co-authored-by: Antonio <antonio@zed.dev>
Previously, each git `Repository` object was held inside of a mutex.
This was needed because libgit2's Repository object is (as one would
expect) not thread safe. But now, the two longest-running git operations
that Zed performs, (`status` and `blame`) do not use libgit2 - they
invoke the `git` executable. For these operations, it's not necessary to
hold a lock on the repository.
In this PR, I've moved our mutex usage so that it only wraps the libgit2
calls, not our `git` subprocess spawns. The main user-facing impact of
this is that the UI is much more responsive when initially opening a
project with a very large git repository (e.g. `chromium`, `webkit`,
`linux`).
Release Notes:
- Improved Zed's responsiveness when initially opening a project
containing a very large git repository.
I realized that somehow, the `git` executable is able to compute `git
status` much more quickly than libgit2, so I've switched our git status
logic to use `git`. Follow-up to
https://github.com/zed-industries/zed/pull/12266.
Release Notes:
- Improved the performance of git status updated when working in large
git repositories.
This PR adds a registry for `GitHostingProvider`s.
The intent here is to help decouple these provider-specific concerns
from the lower-level `git` crate.
Similar to languages, the Git hosting providers live in the new
`git_hosting_providers` crate.
This work also lays the foundation for if we wanted to allow defining a
`GitHostingProvider` from within an extension. This could be useful if
we wanted to extend the support to work with self-hosted Git providers
(like GitHub Enterprise).
I also took the opportunity to move some of the provider-specific code
out of the `util` crate, since it had leaked into there.
Release Notes:
- N/A