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.
-
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.
-
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?
-
Install bash-preexec.
-
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.