This package is used for bundling related git-worktrees from multiple repositories together. It’s a bit of an opinionated workflow on how to manage and organize your projects. It helps switch quickly between feature-related projects and ensure you’re on the branch related to that feature. When you’re done with your changes, you can use the projects in the workspace and know which ones were modified to simplify the process of getting the changes merged in together.
Additionally, git metadata (the .git
directory) is shared between all projects. You can stash,
pop, and pull changes in from the same repository in other workspaces thanks to the power of
git-worktrees.
Term | Description |
---|---|
Bare | A bare repository used as a source to create a project’s git-worktree. |
Project | A git-worktree checked out from a bare stored in a workspace. |
Workspace | A collection of project’s created from bare’s. |
Prefix | An string used to generated a default branch name for new projects. |
The main workspace directory contains workspaces which each contains a collection of projects:
treebundel-workspace-root (default: "~/workspaces/") | L workspace1 | L project-one (branch: "feature/workspace1") | L project-two (branch: "feature/workspace1") | L project-three (branch: "feature/workspace1") | L workspace2 L project-one (branch: "feature/workspace2") L project-two (branch: "feature/workspace2") L project-three (branch: "feature/workspace2")
This package is available on MELPA.
(use-package treebundel
:ensure t)
Or you can install from source. Straight example:
(straight-use-package '(treebundel :type git :host github :repo "purplg/treebundel"))
;; -- Configuration goes here --
The main commands for using treebundel.
- treebundel-open
- Open a project in a workspace.
- treebundel-open-project
- Open other project within current workspace. If you’re already in a workspace, prompt to open a different project within that workspace.
- treebundel-add-project
- Add a project to a workspace. Will prompt you for a bare repository to add to your workspace.
- treebundel-remove-project
- Remove a project from a workspace. The project must not have any uncommitted changes for it to be removed.
- treebundel-delete-workspace
- Delete a workspace. Any projects within the workspace are checked to see if they’re clean, and if so, all projects and the workspace itself are deleted. Anything committed is still saved in the respective projects’ bare repository.
Assuming default configuration, the following steps will create a bare clone of the provided repo
URL to ~/workspaces/.bare/<repo-name>.git
, then create and open a worktree for a new branch called
feature/<workspace-name>
.
- Interactively call
treebundel-add-project
. - Enter name for the new (or existing) workspace.
- Select
[ clone ]
. - Enter the URL to clone for the repository to be added to the workspace.
- Specify the name of the branch to checkout. By default, it’ll pre-fill with <treebundel-branch-prefix>/<workspace-name>. You can also select an existing branch.
- Specify the project name which will be the name of the worktree is created in.
You should then be prompted with your project-switch-project
prompt to begin editing.
Whenever you need a different repository, you can call treebundel-open-project
to open and adjacent
project in your current workspace or treebundel-open
to open a project in a different workspace.
- treebundel-workspace-root
- Default:
“~/workspaces/”
The most important variable you probably want to configure is
treebundel-workspace-root
. This configures where all of the treebundel workspaces are going to be located on your file system. - treebundel-project-open-function
- Default:
#'project-switch-project
This is the function called when a project is opened. You could also just make this
find-file
to just open the file instantly or any other function that takes a file path. - treebundel-fetch-on-add
- Default:
nil
Set to nil to disable the automatic
git fetch
when adding a project. When disabled, you may not be able to see new branches on remote without manually do a git fetch. You can interactively call the(treebundel-fetch-bare)
command to manually update a repository. - treebundel-bare-dir
- Default:
(file-name-concat treebundel-workspace-root “.bare”)
This is the directory that bare repository get cloned to. The intent is for this to be mostly transparent, hence the
.
prefix to make it hidden by default. - treebundel-branch-prefix
- Default:
“feature/”
A string used to generate a default branch name created with treebundel. By default, it’s
feature/
such that when you add a new project to a workspace, the new branch is namefeature/<workspace-name>
. You don’t have to use this name, it’s just pre-populated for convience. You can use dir-locals to set workspace-specific prefixes although this, unfortunately, prevents you from using dir-locals in your project since dir-locals only looks as the closest file.
treebundel-before-workspace-open-functions
treebundel-before-project-open-functions
treebundel-after-project-open-hook
treebundel-after-workspace-open-hook
These hooks are called before or after a project or workspace is
opened. treebundel-before-workspace-open-functions
receives the name
of the workspace to be opened as a single argument and
treebundel-before-project-open-functions
receives the workspace and
project name opened.
See the Project Tabs example to see an example on how to use
treebundel-before-project-open-functions
to create a new tab for every
project.
This snippets can extend the usefulness of treebundel.
To create a new tab for every project opened with treebundel:
(add-hook 'treebundel-before-project-open-functions
(lambda (workspace project)
(tab-bar-select-tab-by-name
(format "%s/%s" workspace-name project-name))))
This snippet will open a file within a projects
directory in your org-directory
an org file with the name of your workspace.
(defun my/open-project-notes ()
(interactive)
(if-let ((workspace (or (treebundel-current-workspace)
(treebundel-read-workspace))))
(find-file-other-window
;; e.g. ~/.org/projects/some-feature.org
(file-name-concat org-directory
"projects"
(file-name-with-extension workspace "org")))
(user-error "Not in a workspace")))
MIT