-
Notifications
You must be signed in to change notification settings - Fork 273
fix(git): complete ref update after fetch for both bare and normal repositories #5144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v2
Are you sure you want to change the base?
Conversation
|
Related Documentation 1 document(s) may need updating based on files changed in this PR: flipt |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v2 #5144 +/- ##
==========================================
+ Coverage 60.53% 60.60% +0.06%
==========================================
Files 138 138
Lines 13507 13545 +38
==========================================
+ Hits 8177 8209 +32
- Misses 4641 4643 +2
- Partials 689 693 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
1b8a8d8 to
4cf2394
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a critical bug where the Fetch method was not properly persisting fetched references to refs/heads/ after pulling from remote repositories. The fix handles both bare and normal repositories correctly, ensuring that shallow fetches maintain their boundaries and all repository types properly create local branch references.
Key changes:
- Conditionally applies depth=1 only to bare repositories (not normal repos with working trees)
- Adds logic to create/update
refs/heads/references from fetched remote refs - Implements branch pruning to remove local refs when branches are deleted on remote
- Maintains shallow boundaries for depth=1 fetches by tracking shallow commit hashes
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Get all existing local branch refs | ||
| allLocalRefs, err := r.Storer.IterReferences() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get local refs: %w", err) | ||
| } | ||
|
|
||
| existingHeads := make(map[string]struct{}) | ||
| if err := allLocalRefs.ForEach(func(ref *plumbing.Reference) error { | ||
| if ref.Name().IsBranch() { | ||
| branchName := strings.TrimPrefix(ref.Name().String(), "refs/heads/") | ||
| existingHeads[branchName] = struct{}{} | ||
| } | ||
| return nil | ||
| }); err != nil { | ||
| return fmt.Errorf("failed to iterate local refs: %w", err) | ||
| } | ||
|
|
||
| // Update refs for branches that exist on remote | ||
| for name, hash := range updatedRefs { | ||
| ref := plumbing.NewHashReference(plumbing.NewBranchReferenceName(name), hash) | ||
| if err := r.Storer.SetReference(ref); err != nil { | ||
| return fmt.Errorf("failed to set reference %s: %w", name, err) | ||
| } | ||
| delete(existingHeads, name) | ||
| } | ||
|
|
||
| // Remove local refs for branches that no longer exist on remote | ||
| for branchName := range existingHeads { | ||
| refName := plumbing.NewBranchReferenceName(branchName) | ||
| // Check if this branch is one we're tracking | ||
| isTracked := false | ||
| for _, head := range heads { | ||
| if refMatch(branchName, head) { | ||
| isTracked = true | ||
| break | ||
| } | ||
| } | ||
| if isTracked { | ||
| if err := r.Storer.RemoveReference(refName); err != nil { | ||
| return fmt.Errorf("failed to remove reference %s: %w", branchName, err) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if opts.Depth == 1 { | ||
| // When performing a depth=1 fetch, maintain the shallow boundary in the object store. | ||
| // For shallow clones, we track which commits are shallow to prevent operations that | ||
| // require complete commit history from proceeding. | ||
| shallows, err := r.Storer.Shallow() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get shallows: %w", err) | ||
| } | ||
| shallows = slices.AppendSeq(shallows, maps.Values(updatedRefs)) | ||
| slices.SortFunc(shallows, func(a plumbing.Hash, b plumbing.Hash) int { | ||
| return a.Compare(b.Bytes()) | ||
| }) | ||
| if err := r.Storer.SetShallow(slices.Compact(shallows)); err != nil { | ||
| return fmt.Errorf("failed to set shallows: %w", err) | ||
| } | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new reference management logic (creating refs/heads/, pruning removed branches, and maintaining shallow boundaries) lacks test coverage. Consider adding tests that verify:
- Refs are correctly created in refs/heads/ after fetch
- Removed branches are properly pruned when they no longer exist on remote
- Shallow boundaries are maintained correctly for depth=1 fetches
- Behavior differences between bare and normal repositories
…positories The Fetch method was not persisting fetched references to refs/heads after pulling from the remote. When using depth=1 (shallow fetches), the shallow boundary wasn't maintained and refs/heads/ were never created. For normal repos with full history, updatedRefs were collected but never written to storage. - For shallow repositories: Create refs/heads/ and maintain shallow boundary - For normal repositories: Create refs/heads/ from updatedRefs - Ensure both code paths properly persist fetched references to local storage Signed-off-by: Roman Dmytrenko <[email protected]>
Signed-off-by: Roman Dmytrenko <[email protected]>
d214b61 to
b6da8ac
Compare
The Fetch method was not persisting fetched references to refs/heads after
pulling from the remote. When using depth=1 (shallow fetches), the shallow
boundary wasn't maintained and refs/heads/ were never created. For normal repos
with full history, updatedRefs were collected but never written to storage.