Skip to content

Add git multiple worktree support #396

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

beornf
Copy link

@beornf beornf commented Oct 19, 2021

This PR adds support for managing multiple worktrees. It is designed to be fully compatible with the git worktree add, git worktree remove and git worktree list commands.

Fixes #41, #285, #394.

@@ -805,6 +809,197 @@ func (r *Repository) resolveToCommitHash(h plumbing.Hash) (plumbing.Hash, error)
}
}

func (r *Repository) Worktrees() ([]*Worktree, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write comments on all the methods? Include the all Worktree explaining which of the worktrees will be opened in case of multiple ones?

Copy link
Author

@beornf beornf Oct 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the discovered working trees will be opened in case of multiple ones. i.e. git worktree list

@mark2185
Copy link

mark2185 commented Apr 7, 2022

Hey, I know worktrees aren't a priority, but are there plans to review this in the near future?

@povsister
Copy link

Emm.. looks like this implementation does not support memoryFS.
Any ideas on patching this ?

Copy link
Member

@pjbgf pjbgf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the implementation could be pushed into the storer, making it more extensible. That should also resolve issues of having the force a given filesystem type.


// CreateWorktree creates a linked working tree at the given path.
// Specify the branch for working tree files with CheckoutOptions.
func (r *Repository) CreateWorktree(path string, opts *CheckoutOptions) (*Worktree, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A WorktreeOptions which contained a CheckoutOptions would make this more extensible.

return nil, ErrWorktreeNotExists
}

_, err = os.Stat(filepath.Join(dot.Root(), "gitdir"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gitdir could be a constant.

}

common := fs.Filesystem()
pattern := filepath.Join(common.Root(), "worktrees", "*")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worktrees could be a constant.

Comment on lines +814 to +821
type fsBased interface {
Filesystem() billy.Filesystem
}

fs, isFSBased := r.Storer.(fsBased)
if !isFSBased {
return nil, ErrRepositoryNotFileBased
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you encounter any specific problem trying to support in memory storer?

Comment on lines +889 to +892
wt := osfs.New(path)
dot := osfs.New(filepath.Join(common.Root(), "worktrees", name))
repositoryFs := dotgit.NewRepositoryFilesystem(dot, common)
s := filesystem.NewStorage(repositoryFs, cache.NewObjectLRUDefault())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add this as a new abstraction (e.g. storer.WorktreeStorer) within the Storer interface. It would be up to the storage to handle the implementation details.

Comment on lines +925 to +934
fs, isFSBased := worktree.Repository().Storer.(fsBased)
if !isFSBased {
return ErrRepositoryNotFileBased
}

if err = util.RemoveAll(worktree.Filesystem, ""); err != nil {
return err
}

return util.RemoveAll(fs.Filesystem(), "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above on the storer.WorktreeStorer.

@github-actions github-actions bot added the stale Issues/PRs that are marked for closure due to inactivity label Apr 12, 2024
@github-actions github-actions bot closed this May 17, 2024
@beornf
Copy link
Author

beornf commented May 17, 2024

This PR isn't stale. I'll look into the implementation at a future date.

@pjbgf pjbgf reopened this May 17, 2024
@pjbgf pjbgf added no-autoclose Issues/PRs to be ignored by stale bot and removed stale Issues/PRs that are marked for closure due to inactivity labels May 17, 2024
@dekimsey
Copy link

This work is really cool to see, when working with git repositories programmatically the ability to generate/play/destroy worktrees is super useful! I hope this is still something that's moving forward. It would be a great addition to the project.

Thank you kindly for the effort here! +1

@clseibold
Copy link

@beornf I was wondering if you planned on picking this back up and continuing it anytime soon.

@beornf
Copy link
Author

beornf commented Feb 24, 2025

@clseibold I don't have the bandwidth to pick this up this year. If you are able to help rewrite this PR to use a storer.WorktreeStorer interface and add an implementation for memoryFS, it would allow this work to move forward sooner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-autoclose Issues/PRs to be ignored by stale bot
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Checkout multiple branches
7 participants