Skip to content

Exploit git-worktrees to create inter-related project workspaces.

License

Notifications You must be signed in to change notification settings

purplg/treebundel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

treebundel

https://melpa.org/packages/treebundel-badge.svg

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.

Contents

Terminology

TermDescription
BareA bare repository used as a source to create a project’s git-worktree.
ProjectA git-worktree checked out from a bare stored in a workspace.
WorkspaceA collection of project’s created from bare’s.
PrefixAn 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")

Installation

This package is available on MELPA.

use-package

(use-package treebundel
  :ensure t)

straight.el

Or you can install from source. Straight example:

(straight-use-package '(treebundel :type git :host github :repo "purplg/treebundel"))
;; -- Configuration goes here --

Usage

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>.

  1. Interactively call treebundel-add-project.
  2. Enter name for the new (or existing) workspace.
  3. Select [ clone ].
  4. Enter the URL to clone for the repository to be added to the workspace.
  5. 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.
  6. 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.

Configuration

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 name feature/<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.

Hooks

  • 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.

Nifty snippets

This snippets can extend the usefulness of treebundel.

Project Tabs

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))))

Workspace Notes

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")))

License

MIT

About

Exploit git-worktrees to create inter-related project workspaces.

Resources

License

Stars

Watchers

Forks

Packages