Feat: add interactive git worktree operations#402
Conversation
|
@suft Thanks for your contribution! Is this ready for review or did you make it a draft on purpose? |
|
@carlfriedrich I made it draft on purpose. Still have a few things to adjust. |
bin/git-forgit
Outdated
| [[ "$sha" == "(bare)" ]] && return | ||
| # the trailing '--' ensures that this works for branches that have a name | ||
| # that is identical to a file | ||
| git log "$sha" "${_forgit_log_preview_options[@]}" -- |
There was a problem hiding this comment.
- I should probably add preview options
FORGIT_WORKTREE_PREVIEW_GIT_OPTS(like Add *_PREVIEW_GIT_OPTS variables #396) - I've noticed this can run a bit slow (on some computers) if you have a repo with a long history because it attempts to get the entire history for the branch checked out in that worktree
- It would be good to see what others think when they test this out
- Would be quicker if I limit the log entries in the worktree preview options
cae816c to
525441f
Compare
sandr01d
left a comment
There was a problem hiding this comment.
Thanks for you work @suft! I think this is going to be a nice improvement. There are a few things that need to be adjusted. In some of my comments I've pinged the other maintainers for their opinions. Please hold back on implementing those, as those comments are opinionated and I'd like to have feedback from the others first before deciding in which direction to go.
sandr01d
left a comment
There was a problem hiding this comment.
Thanks for the changes @suft, looks good to me so far. Let me summarize the things that still need to be addressed:
- The default preview should look the same as for other commands that use
git log(#402 (comment)) _forgit_worktree_jumpdoes not change the directory when forgit is used as a git subcommand (#402 (comment))- The root worktree should not be selectable with
gwl. We can make it non-interactable with--header-lines=1and also bring this back in the other functions that you used this with. Don't mind my earlier comment regarding this. (#402 (comment)) - We should add completions for the new commands (#402 (comment))
- We should allow passing additional arguments to the underlying git commands (#402 (comment)). The logic for detecting whether the git command should be executed immediately without using fzf needs to be adjusted to do so. Instead of testing if any arguments were passed, we need to test whether non flag arguments were passed. You can use
_forgit_contains_non_flagsto do so.
|
(it looks like there is very thorough reviewing going on here, please ping me if you need another pair of eyes, otherwise I completely defer to @sandr01d and @carlfriedrich ) |
The root worktree doesn't show up as the first selection, so
|
f5c8d6c to
3bfa1d2
Compare
|
Thanks again to @suft for the original work and idea on this PR! I've taken over and done a reimplementation based on the original proposal and the review feedback from @sandr01d and @carlfriedrich. Also thanks to @iloveitaly for providing the link, which helped improve the display format of the worktree list. First — my sincere apologies, @suft. I accidentally force-pushed to your branch, which overwrote your original commits. I'm really sorry about that. Hopefully you still have a local copy of your original implementation. Again, very sorry for the mishap. Summary of the current implementationTwo new commands:
Worktree browser features
Also included
Differences from the original proposal
The main design shift: instead of multiple standalone commands (lock/unlock/jump/remove), the current approach uses a single browser with keybindings for in-place operations + a separate delete command, keeping the alias namespace smaller. I've done a thorough self-review already, but given the scope of this PR — new feature + refactoring of existing branch-related code — I'd appreciate another round of review. @cjappl @carlfriedrich @sandr01d Would you mind taking a look when you have time? And @suft, your input would also be very valuable given all the thought you put into the original design! |
|
Hey @wfxr, could you rearrange the commits in this MR, so we have one commit for each refactoring and one for the new workspace commands? This would make reviewing a lot easier for me. |
|
@wfxr Thanks a lot for pushing this forward and your work on this! I like that you combined multiple commands into one and make use of keybindings instead (that goes into the direction I proposed in #259 some time ago). I did a quick test of your branch and it seems to works as expected. For a useful code review I am going with @sandr01d: given the huge size of the PR it would be really helpful to have a clean history of atomic commits on this branch. |
cb7a084 to
b7382d9
Compare
|
Thanks @sandr01d @carlfriedrich for the review feedback! I've reorganized the branch into two atomic commits:
This should make reviewing much easier. PTAL when you get a chance! |
|
Hi @sandr01d @carlfriedrich, I'd like to move forward with this PR. I've thoroughly reviewed the implementation myself and also had it reviewed with AI assistance. Additionally, I've been using this feature in my daily workflow for quite a while now without encountering any issues. If there's no review feedback by Monday, I'll go ahead and merge this. That said, comments and suggestions are always welcome — feel free to leave them anytime, even after it's merged, and I'll address them in follow-up commits. |
Just found out that I still had the original commits on my machine, so I pushed them here. |
sandr01d
left a comment
There was a problem hiding this comment.
Sorry for the delay @wfxr, I was very busy in the last weeks and couldn't find the time for a review.
First of all, thank you both for your work @wfxr and @suft, I think this is coming along really nicely. I really like the refactoring you did with the branch helpers. I think this improves readability a lot, good work! I've added a few, mostly minor, notes. I think we should be able to merge this sometime soon.
|
Thanks for the thorough review, @sandr01d! I've addressed all your comments — either applied the suggestions or replied with explanations. PTAL |
- Add _forgit_strip_ansi for removing ANSI escape codes - Add _forgit_branch_list to list branches with current branch first - Add _forgit_extract_branch_name to parse branch names from git output - Update checkout_branch, switch_branch, branch_delete, cherry_pick_from_branch, and branch_preview to use the new helpers - Fix _forgit_inside_work_tree to suppress stderr
Add worktree browser (gwt) and worktree delete selector (gwd) with: - Interactive worktree list with lock status, branch info, and age - Preview showing working tree status and recent commits - Ctrl-Y to copy worktree path, Alt-L to toggle lock/unlock - Shell integration for zsh (with cd) and fish (with cd) - Tab completions for zsh, bash, and fish - Documentation in README with keybindings and options Co-Authored-By: Sufien Tout <sufientout@gmail.com>
- Extract dim formatting into _forgit_print_dim() to replace hardcoded ANSI sequences in _forgit_branch_list() - Add empty state check and alt-l lock toggle reload for worktree delete - Fix worktree path completion to handle paths with spaces using -z flag - Add worktree command completion for bash and zsh


Check list
Description
I recently adopted using multiple fixed worktrees as part of my workflow to help with productivity.
Each worktree is used for a different type of concurrent activity:
mainfor looking at the pristine codeworkfor looking at my codereviewfor looking at someone else’s codebackgroundfor my computer to look at my codescratchfor everything elseExample of worktrees in a bare clone

Another approach is to use worktrees as a replacement of, or a supplement to git branches. Instead of switching branches, you just change directories. So that would involve creating a new worktree and branch, then delete the worktree upon merging.
Worktree Operations (should we stick with these abbreviations?)
gwlgwugwrgwjgit worktree listandcdinto that result (not a native git operation)Screenshots
bash (repo with short history) -

gwjFORGIT_WORKTREE_PREVIEW_GIT_OPTS='--oneline --graph --decorate --color'fish (repo with mid-length history) -

gwjFORGIT_WORKTREE_PREVIEW_GIT_OPTS='--oneline --graph --decorate --color'bash (repo with mid-length history) -

gwjFORGIT_WORKTREE_PREVIEW_GIT_OPTS='--oneline --graph --decorate --color --max-count=100'Closes #399.
Type of change
Test environment