This repository was archived by the owner on Jun 5, 2025. It is now read-only.
Git extension improvements #3502
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary of the pull request
This brings several improvements to the Git extension:
Detailed description of the pull request / Additional comments
For the perf increase, I learned that
LibGit2Sharp.CommitEnumeratoris not reusable, even though the object it wraps, libgit2'sgit_revwalkis documented that "for maximum performance, this revision walker should be reused for different walks". Measurements confirmed that most of the time was being spent in libgit2'sprepare_walk()where it traverses, sorts, and caches the commit graph in thegit_revwalk. After this step, walking the commits in the revwalk proceed quickly, which is used for finding a file's latest commit.To work around this, we grab the whole commit graph up front and cache the list of
LibGit2Sharp.Commitobjects to walk later. When it's time to fetch this cached list, we first check to see ifHEADhas changed, and retrieve a new list of commits.For improved file status, instead of calling
ToStringon LibGit2Sharp's enum values, we now simplify and turn these strings into more intuitive values, like "Modified", "Staged", "Untracked".For improved repo status, we now obtain the whole-repo status and condense that into a compact string representation we see in other tools.
<branch name> <branch status> | <file counts>Where:
<branch name>is either"Branch: <name>"or"Detached: <sha>"<branch status>if the branch is tracking a remote shows either↑ <ahead # commits>↓ <behind # commits>↓ <behind # commits> ↑ <ahead # commits>≡(when up-to-date)<file counts>is"+<#added> ~<#numstaged> -<#removed> | <#untracked> ~<modified> -<missing>""!<#conflicted>"To fix race conditions, I moved the
LibGit2Sharp.Repositoryobject into a newRepositoryWrapperclass that will manage access to the Repository objects to eliminate concurrent access.Validation steps performed
Built extension and browsed the PowerToys repo, refreshing the view while checking out branches back and forth to cause contention on fetching status and commits. Not only does this run much faster than before, but the infrequent instances where the extension would sometimes hang or crash have disappeared.
PR checklist