Skip to content

Latest commit

 

History

History
172 lines (134 loc) · 6.29 KB

README.md

File metadata and controls

172 lines (134 loc) · 6.29 KB

tmux-vcs-sync

Synchronize the underlying VCS based on tmux state.

What is this?

tmux-vcs-sync is a developer tool that I've had in some form basically since I started working. At its core, it's trying to automate some tedious bookkeeping that I would otherwise need to do for my normal development workflow. But that tedious bookkeeping is pretty easy to forget, so there's a bit of a productivity boost here, too.

My developer workflow is essentially a stacked diff workflow. Each of my work units is a small, self-contained change. If the feature I'm working on isn't done after a single, small, self-contained change, I start another based on top of the work I've already done. I find that this workflow has a ton of benefits (more incremental progress, easier to verify each individual change, changes that are less "dramatic"), but it can also be harder to verify the full effects of a series of changes when they're all separate, so it has some tradeoffs.

I found it a little difficult to keep track of all my small changes (I don't think humans are really meant to be able to remember a bunch of 160 bit hex hashes), so I tweaked my workflow a bit to make this a little easier.

  1. I started naming all of my work units.

    The names weren't always great (naming is hard), but they did help me remember what I was working on in each change.

  2. I started using a separate tmux session per work unit.

    I found this helped reduce the cost of context switching. Maybe it has something to do with each change having its own "workplace", and me seeing the last couple of commands I ran when working on the change primes my memory.

But then I found that I was switching into tmux sessions and forgetting to update the VCS to checkout the correct work unit. It feels pretty bad to have to unroll dozens of minutes worth of work because of a small oversight.

And that's where this tool comes in. I named all of my tmux sessions the same as my work units. The first iteration of this tool was some hacky bash functions combined with bash-preexec to ensure the VCS was updated before any command ran in my terminal. It has since grown beyond just some bash functions, and I thought maybe someone else would benefit if I put it out into the wild :)

Installation

This project uses mage. See that project's website for installation instructions.

$ git clone https://github.com/JeffFaer/tmux-vcs-sync
$ cd tmux-vcs-sync
$ mage install
$ cd git
$ mage install

Shell completion

You can generate shell completion with

$ mage install:completion "${SHELL:?}"

where ${SHELL:?} is one of the shells that cobra is able to generate completion for (at the time of writing: bash, fish, powershell, and zsh).

It will generate a tvs_completion.${SHELL:?} file and attempt to put it into an appropriate directory for your shell.

Usage

$ tmux-vcs-sync new work-unit-name
$ tmux-vcs-sync commit work-unit-name
$ tmux-vcs-sync rename work-unit-name
$ tmux-vcs-sync update work-unit-name
$ tmux-vcs-sync update
  • new work-unit-name: Create a new tmux session and a new work unit on the current repository's trunk.
  • commit work-unit-name: Create a new tmux session and a new work unit on top of the current work unit.
  • rename work-unit-name: Rename the current tmux session and work unit.
  • update work-unit-name: Update tmux and the underlying VCS to both point at the given work unit.
  • update: Update the repository of the current tmux session to point at the tmux session's work unit.

This information and more can be found in the tool itself:

$ tmux-vcs-sync help

tmux usage

The tool also has the capability to help you switch between tmux sessions within tmux, similar to tmux choose-tree. This functionality is available via tmux-vcs-sync display-menu. You can set up tmux to use that on a keybind with something like bind S run-shell "tmux-vcs-sync display-menu".

Tips

tmux-vcs-sync? That's a lot to type.

Yeah, I know. Naming is hard. Consider aliasing it to tvs. Or pitch me a better name that's easier to type :)

How do I make it run before terminal commands?

  1. Install bash-preexec.

  2. Add the following snippet to your .bashrc.

    if [[ -n "${TMUX}" ]]; then
      tvs_preexec() {
        if ! git ls-files --error-unmatch &>/dev/null; then
          return
        fi
        if tmux-vcs-sync update --fail-noop; then
          history -s tmux-vcs-sync update
        fi
      }
      preexec_functions+=( "tvs_preexec" )
    fi

Development

This is a multi-module project.

tmux-vcs-sync
├── . -- the git root is the module that implements the CLI tool
│   ├── cmd -- cobra commands
│   └── tmux -- lightweight tmux API
│       └── state -- implements some operations to sync tmux and VCS state
├── api -- this module is an API that can be implemented to add support for a new VCS
│   ├── exec -- lightweight wrapper around os/exec
│   └── magefiles
│       └── plugin -- A magefile library for implementations of the api
└── git -- this module is an implementation of api for git

You will probably want to set up go.work when developing locally:

$ go work init
$ go work use . api git

TODOs

  • Tests.
    • tmux/state PruneSessions
    • tmux/state MaybeFindRepository
    • cmd new.go
    • cmd rename.go
    • cmd update.go no args
    • cmd update.go with args
    • cmd update.go completion suggestions
  • Update should accept repo-qualified work unit names.
  • tmux hooks to automatically update session names when a session closes.