Last active
February 19, 2026 11:53
-
-
Save Duologic/29725b14bc9ef397366e32020d3423ce to your computer and use it in GitHub Desktop.
scripts to manage worktrees
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| DIR="/home/duologic/git/$1" | |
| MAIN="${2:-main}" | |
| mkdir -p "$DIR" | |
| gh repo clone $1 "$DIR" -- --bare --depth 100 | |
| cd "$DIR" | |
| git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*' | |
| git worktree add wt/$MAIN $MAIN |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Parse command line arguments | |
| STATE_FILTER="MERGED" | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| -s|--state) | |
| STATE_FILTER="$2" | |
| shift 2 | |
| ;; | |
| *) | |
| echo "Usage: $0 [-s|--state STATE]" | |
| echo " STATE: PR state to filter (default: MERGED, use empty string \"\" to match all)" | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| worktrees=$(git worktree list | | |
| grep -v '\[master\]' | | |
| grep -v '\[main\]' | | |
| grep -v '\(bare\)' | | |
| awk -F' ' '{print $1}') | |
| for wt in $worktrees; do | |
| state=$( | |
| cd $wt | |
| gh pr view --json state | jq .state | |
| ) | |
| if [[ -n "$STATE_FILTER" && $state != "\"$STATE_FILTER\"" ]]; then | |
| continue | |
| fi | |
| # Set default based on state | |
| if [[ $state == '"MERGED"' ]]; then | |
| echo -n "Remove worktree '$wt' ($state)? (Y/n) " | |
| read -r remove | |
| # Default to yes for merged PRs | |
| if [[ -z "$remove" ]]; then | |
| remove='y' | |
| fi | |
| else | |
| echo -n "Remove worktree '$wt' ($state)? (y/N) " | |
| read -r remove | |
| fi | |
| clean=$(git -C "$wt" status --porcelain) | |
| has_submodules=$(git -C "$wt" submodule status 2>/dev/null) | |
| if [ "$remove" = 'y' ] && { [ -n "$clean" ] || [ -n "$has_submodules" ]; }; then | |
| if [ -n "$clean" ]; then | |
| echo "Worktree '$wt' not clean:" | |
| git -C "$wt" status | |
| fi | |
| if [ -n "$has_submodules" ]; then | |
| echo "Worktree '$wt' contains submodules:" | |
| git -C "$wt" submodule status | |
| fi | |
| echo -n "Force remove? (y/N) " | |
| read -r force_remove | |
| if [ "$force_remove" = 'y' ]; then | |
| remove='force' | |
| fi | |
| fi | |
| if [ "$remove" = 'y' ]; then | |
| echo "Removing '$wt'" | |
| git worktree remove "$wt" | |
| echo | |
| elif [ "$remove" = 'force' ]; then | |
| echo "Force removing '$wt'" | |
| git worktree remove --force "$wt" | |
| echo | |
| fi | |
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| worktrees=$(git worktree list \ | |
| | grep -v '\[master\]' \ | |
| | grep -v '\[main\]' \ | |
| | grep -v '\(bare\)' \ | |
| | awk -F' ' '{print $1}') | |
| for wt in $worktrees; | |
| do | |
| state=$(cd $wt; gh pr view --json state 2> /dev/null) | |
| state=$(echo $state | jq .state) | |
| echo "($state) $(realpath -m --relative-to=$PWD $wt)" | |
| done | column -t |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # call this from tmux bind-key: `bind-key y display-popup -E -T " wtwindow " "wtwindow"` | |
| set -euo pipefail | |
| if [ "$#" != 1 ]; then | |
| GITDIRS=$(fd --glob --type d -H 'wt' $HOME/git) | |
| PROJ=$(printf "$GITDIRS" | sed 's;'$HOME'/git/;;' | sed 's/\/\.git\///' | fzf) | |
| PROJ="$HOME/git/$PROJ" | |
| else | |
| if stat "$1" >/dev/null; then | |
| PROJ="$1" | |
| elif stat "$HOME/git/$1" >/dev/null; then | |
| PROJ="$HOME/git/$1" | |
| else | |
| echo "$1 not found" | |
| exit 1 | |
| fi | |
| fi | |
| NAME="$(basename "${PROJ:0:-3}")" | |
| tmux new-window -c "$PROJ" -n "$NAME" | |
| sleep 1 | |
| tmux split-window -c "$PROJ" -t "$NAME" -h | |
| tmux split-window -c "$PROJ" -t "$NAME" | |
| tmux send-keys -t 2 "watch -n 30 'git wtlist'" | |
| tmux send-keys -t 2 Enter | |
| tmux select-pane -t 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment