Improve git worktree session workflow

This commit is contained in:
2026-08-10 12:42:53 +01:00
parent c97c9cb027
commit 56b5bdb5ac
6 changed files with 67 additions and 4 deletions

View File

@@ -2,8 +2,14 @@
session_name=$(tmux display-message -p '#S') session_name=$(tmux display-message -p '#S')
session_layout=~/.local/share/tmux/layouts/session-$session_name session_layout=~/.local/share/tmux/layouts/session-$session_name
# Set by `session -p <project>`, which names the session after the project but
# can't be relied on for the lookup above since tmux rewrites `.` in names.
session_project=$(tmux show-environment -t "$session_name" TMUX_PROJECT 2>/dev/null |
sed -n 's/^TMUX_PROJECT=//p')
if [ -f $session_layout ]; then if [ -f $session_layout ]; then
$session_layout $session_layout
elif [ -n "$session_project" ]; then
~/.local/share/tmux/layouts/session-project "$session_project"
elif [ "$session_name" != "agent" ]; then elif [ "$session_name" != "agent" ]; then
tmux rename-window home tmux rename-window home
fi fi

View File

@@ -31,6 +31,8 @@ symlink $HOME/.config/tmux/layouts/session-infra \
$HOME/.local/share/tmux/layouts/session-infra $HOME/.local/share/tmux/layouts/session-infra
symlink $HOME/.config/tmux/layouts/session-main \ symlink $HOME/.config/tmux/layouts/session-main \
$HOME/.local/share/tmux/layouts/session-main $HOME/.local/share/tmux/layouts/session-main
symlink $HOME/.config/tmux/layouts/session-project \
$HOME/.local/share/tmux/layouts/session-project
symlink $HOME/.config/tmux/layouts/session-visor \ symlink $HOME/.config/tmux/layouts/session-visor \
$HOME/.local/share/tmux/layouts/session-visor $HOME/.local/share/tmux/layouts/session-visor
symlink $HOME/.config/tmux/layouts/session-work \ symlink $HOME/.config/tmux/layouts/session-work \

35
layouts/session-project Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env zsh
# usage: session-project <project>
#
# Layout for a session created by `session -p <project>`, where <project> is a
# path in ~/Projects with the prefix removed. The session-created hook passes
# the project along, taking it from the session environment.
project=$1
repo=$HOME/Projects/$project
tmux rename-window home
$(dirname $0)/window-auto
# Without a project there is nothing but the home window, which is all a
# session created directly from this layout's name can get.
if [[ -z "$project" ]] || ! git -C "$repo" rev-parse --git-dir &>/dev/null; then
exit
fi
# The remote's default branch, falling back to whatever HEAD points at for
# repositories without an origin/HEAD, e.g. those with no remote at all.
branch=$(git -C "$repo" symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null)
branch=${branch#origin/}
if [[ -z "$branch" ]]; then
branch=$(git -C "$repo" symbolic-ref --short HEAD 2>/dev/null)
fi
if [[ -z "$branch" ]]; then
# Detached HEAD, name the window after the commit it sits on.
branch=$(git -C "$repo" rev-parse --short HEAD 2>/dev/null)
fi
tmux new-window -c "$repo"
tmux rename-window "$branch"
$(dirname $0)/window-auto

View File

@@ -57,7 +57,21 @@ if [[ "${1:-}" == --pick ]]; then
) || exit 0 ) || exit 0
[ -n "$project" ] || exit 0 [ -n "$project" ] || exit 0
tmux new-window -n "$project" -c "$projects_dir/$project" # Inside a session for this same project, e.g. one created by `session -p`,
# the slug only repeats the session name, so name the window after the branch
# checked out there instead — a worktree's whole identity. Everything up to
# the `@` is the clone the worktrees hang off, and tmux rewrote `.` and `:` in
# the session name, so match both before comparing.
window_name=$project
session=$(tmux display -p '#S')
root=${project%%@*}
if [ "${root//[.:]/_}" = "$session" ]; then
branch=$(git -C "$projects_dir/$project" symbolic-ref --short HEAD 2>/dev/null ||
git -C "$projects_dir/$project" rev-parse --short HEAD 2>/dev/null || true)
window_name=${branch:-$project}
fi
tmux new-window -n "$window_name" -c "$projects_dir/$project"
~/.local/share/tmux/layouts/window-auto ~/.local/share/tmux/layouts/window-auto
exit exit
fi fi

View File

@@ -4,9 +4,12 @@ set -e
sessions=() sessions=()
# Get list of predefined session layouts # Get list of predefined session layouts, skipping session-project since it is
# parameterized by `session -p <project>` rather than a session of its own
for item in $HOME/.local/share/tmux/layouts/session-*; do for item in $HOME/.local/share/tmux/layouts/session-*; do
sessions+=(${item#$HOME/.local/share/tmux/layouts/session-}) layout=${item#$HOME/.local/share/tmux/layouts/session-}
[ "$layout" = project ] && continue
sessions+=($layout)
done done
# Get list of existing sessions # Get list of existing sessions

View File

@@ -3,7 +3,10 @@ if -b '[ "$WSL_DISTRO_NAME" != "" ]' \
'setw -g status-left " #(hostname)|#{WSL_DISTRO_NAME}|#{session_name}"' \ 'setw -g status-left " #(hostname)|#{WSL_DISTRO_NAME}|#{session_name}"' \
'setw -g status-left " #(hostname -s)|#{session_name}"' 'setw -g status-left " #(hostname -s)|#{session_name}"'
setw -g status-left-style fg=colour240,bg=colour233 setw -g status-left-style fg=colour240,bg=colour233
setw -g status-left-length 32 # Only a maximum, and the component is never padded out to it, so leave room
# for the hostname beside a full session name: project sessions are named after
# a path, e.g. modularml/modular@benie/some-branch.
setw -g status-left-length 100
# Centre status style # Centre status style
setw -g status-style fg=colour240,bg=colour233 setw -g status-style fg=colour240,bg=colour233