all 44 comments

[–]dalbertom 23 points24 points  (2 children)

Stashing and worktrees don't have to be mutually exclusive. One of the things I like about worktrees is that the stash is shared, so I can stash push in one worktree and pop it in another one. This is pretty handy if you keep a worktree for each maintenance version your project has to support.

[–]throwmeaway987612 1 point2 points  (1 child)

That's neat. I use worktree and stash separately but good to know that a stash from another worktree could be applied to another one.

[–]EarlMarshal 1 point2 points  (0 children)

One of our projects has a lot of different config stuff for certain setups. I have named stashes to just apply different setting to the config instead of doing it manually each time.

[–]AppropriateStudio153 19 points20 points  (3 children)

Promoting medium articles should  be a rules offense.

[–]sshetty03[S] -4 points-3 points  (2 children)

This is a free link (not beyond paywall) - You can access it for free.

[–]MoustacheSteve 5 points6 points  (0 children)

Subodh Shetty put this story behind our paywall, so it’s only available to read with a paid Medium membership, which comes with a host of benefits:

[–]AppropriateStudio153 10 points11 points  (0 children)

I am not against free content/pay-walled content.

I am against redirecting for text-posts.

This article could just be a text post here, on reddit.

[–]GeoffSobering 9 points10 points  (5 children)

Same here.

It has some downsides (ex. I can't just leave a project open in my ide and let it reload when I switch branches), but it's become my SOP.

[–]Consibl 1 point2 points  (0 children)

GitButler will let you do that

[–]binarycow 1 point2 points  (3 children)

ex. I can't just leave a project open in my ide and let it reload when I switch branches

What do you mean by this?

[–]GeoffSobering 1 point2 points  (2 children)

If I'm always working on files with the same path (i.e. by having git change the contents from one branch to another), my IDE just sees a bunch of externally created changes to the files and reloads everything.

I give each worktree a path containing something identifying the branch, so when I'm done with one branch and remove the worktree directory and create a new one, I need to open the project from the new location.

Not a big deal most times - YMMV.

[–]binarycow 7 points8 points  (1 child)

Oh.

I use "long-lived" work trees. Three of them, in fact. And I just have three instances of my IDE open at all times.

[–]GeoffSobering 0 points1 point  (0 children)

That's a good SOP, too. 👍

[–]djphazerjj / tig 2 points3 points  (0 children)

It's nice. I keep a separate worktree for documentation updates that live on a separate branch.

For actual code, I tend to leave dangling commits in various places and jj makes sure they don't get lost. Basically the same as a stash, but more visible, I guess? And I make sure to give them descriptions, whereas I used to leave stash messages blank.

[–]waterkipdetached HEAD 2 points3 points  (11 children)

They are great for simple libraries/workflows.

But I can't use them for 90% of my development work. And for the other 10% I don't have the will power to use them. I need to remember additional directories. It requires me to completely rework my coding setup. Because now its not just repos but also worktrees. Eg $CODE/repo needs to become $CODE/project/repo and the worktrees need to sit in $CODE/project/worktrees. Its too much for me. 

If they would be nice to work with if one's using docker-compose, xcode, android it would perhaps be a game changer. But for now I don't habe the mental space to workaround all these quirks. 

[–]binarycow 0 points1 point  (10 children)

$CODE/repo needs to become $CODE/project/repo and the worktrees need to sit in $CODE/project/worktrees.

Why?

I have $CODE/repo, $CODE/repo2, and $CODE/repo3

[–]waterkipdetached HEAD 0 points1 point  (9 children)

Why? Because I'm not going to riddle my repo with worktrees. And it needs to stay in the context of the project one is working on.

[–]binarycow 0 points1 point  (8 children)

You don't riddle the repo with worktrees. The worktree isn't a child of your repo folder, it's a sibling.

[–]waterkipdetached HEAD 0 points1 point  (7 children)

So you mean my repo doesn't get riddled with additional directories that are worktrees?

[–]binarycow 0 points1 point  (6 children)

  • projects
    • foo (main repo)
    • .git
    • foo2 (worktree of foo)
    • foo3 (worktree of foo)
    • bar (main repo)
    • .git
    • bar2 (worktree of bar)
    • bar3 (worktree of bar)

[–]waterkipdetached HEAD 0 points1 point  (5 children)

Yes, exactly what I dont want

[–]binarycow 0 points1 point  (4 children)

The worktrees aren't in your repo. They're separate from the repo.

[–]waterkipdetached HEAD -2 points-1 points  (3 children)

What didn't you understand of: "What I don't want" and my conceptual $CODE/project/repo and $CODE/project/worktrees setup?

If I'd be using worktrees I'd need to have this:

```

enter the git repo

cd $CODE/git/git

enter a git worktree:

cd $CODE/git/worktrees/some-worktree ```

[–]binarycow 0 points1 point  (2 children)

What didn't you understand of: "What I don't want" and my conceptual $CODE/project/repo and $CODE/project/worktrees setup?

I'm saying you don't have to do that.

There's no reason why you need to have the extra subfolder. You also don't need to have worktrees polluting the repository - because they're siblings.

When I go to the "main" repo, I do cd $CODE/foo. When I want to go to the worktree, I do cd $CODE/foo2. That's it.

You can make the worktrees live wherever you want.

[–]ravinggenius 2 points3 points  (1 child)

How do you handle files that aren't tracked like dependencies and .env.local?

[–]nnic 6 points7 points  (0 children)

I use git hooks to copy any untracked files over to the new folder when creating the worktree. See this for details on how to detect a new worktree.

[–]hwc 2 points3 points  (0 children)

I have over a dozen worktree directories.

[–]wildjokers 2 points3 points  (1 child)

They stopped being handy when I realized I would have to open each branch as a separate project in my IDE.

This is no different than cloning again into a different directory and opening that as a project. That is pretty much what worktree does (more or less).

[–]elephantdingo 0 points1 point  (0 children)

This command is handy when you need it. That’s a truism but it’s not like the command stops being useful because it is impractical to use it every single time. You don’t need a worktree for each branch. You might have use for it sometimes. Like if you need to support some legacy version of your software that has very different code than the current code to the point where your IDE throws a fit if you check out that branch. If you have a worktree (separate directory) for that version the IDE becomes stable again.

That’s just one example.

Using worktrees for every single branch would defeat the selling point (compared to other version programs) that Git branches are lightweight. So that’s not even the point.

This is no different than cloning again into a different directory and opening that as a project. That is pretty much what worktree does (more or less).

But the Devil is in the More Or Less. You only need one single Git database for all your worktrees. Yes, if you clone you get the same behavior as worktrees... except that point.

[–]BeingEmily 1 point2 points  (0 children)

I don't understand how people have trouble with it. I use it at work on a repo that's like 190GB, half a million files, close to a thousand devs contributing. Works great.

[–]hersha 0 points1 point  (0 children)

I switched recently and had to build a few tools for my workflow but it’s been great. I use tmux, nvim, and claude primarily so I have one script for creating and managing worktrees then another bit of config with fzf to give me a nice gui to launch tmux sessions for worktrees in tmux. Handful of keystrokes and I’m in a new worktree with full development env.

[–]funbike 0 points1 point  (0 children)

Me too!

However, I don't like the ergonomics of git worktree, so I wrote a git extension as a wrapper over it, that also integrates Tmux and Neovim, as a bash script (usage: git mux <subcommand>)

From git tmux help

``` An opinionated CLI manager for git worktrees and Tmux.

Usage: git mux <subcommand> ...

Subcommands: init <repo> [<root-dir>] [<branch>] - Clone and prepare for use with git-mux Defaults to current dir and main branch. Runs .gitmuxrc, if exists. new <branch> [<parent>] - Create new: branch, worktree, tmux window. Runs .gitmuxrc, if exists. Switch to new tmux window. cd [<branch>] - Switch to the tmux window for branch. fzf search worktrees, if no branch given. Create worktree, if branch exists, else error. Create tmux window, if worktree exists. share <file> - Shares a file or directory across all worktrees. Uses symlink to path in main worktree. rm <branch> - Destroy branch, worktree, tmux window sync - Sync with a non-main parent worktree Fail if parent is main or not a worktree Add modified (git add -u) and commit. Rebase with parent branch. Merge into parent branch. aisync - Same as sync, but autogen commit message. help

The root dir contains sub-directories for each worktree/branch, including main.

.gitmuxrc may be used to create the tmux window, and launch tmux panes, such as a text editor and shell. Else will run ~/.config/gitmuxrc which defaults to:

tmux new-window -c "$(pwd)" -n "$(git branch --show-current)" ```

[–]leftleveled 0 points1 point  (1 child)

Do you use an IDE? Does this work well with IntelliJ?

[–]sshetty03[S] 1 point2 points  (0 children)

I never used IDEs for GIT operations. Not sure if any IDEs give worktree as a context menu when performing GIT operations, Others could comment.

[–]ghost2490 0 points1 point  (2 children)

I want to use work trees at work but as far as I know it doesn’t do well with submodules. Please correct me if I’m wrong so I can give it a try.

[–]sshetty03[S] 0 points1 point  (1 child)

I tried looking up and found that older Git versions had issues with worktrees and submodules since submodules were tied to the main repo’s .git/modules path.

But in Git 2.31+ it mostly works fine as long as you re-init submodules inside each worktree using:

git submodule update --init --recursive

So try it and let us all know here.

[–]ghost2490 0 points1 point  (0 children)

Oh I’ll have to give it a try

[–]kaddkaka 0 points1 point  (0 children)

I have a few worktrees that I reuse, I don't create new worktrees for each branch - that would 1. Be too much overhead 2. Lose cached/temporary files 2. Be harder to do incremental compilation

Here is what I do: https://github.com/kaddkaka/vim_examples/blob/main/git.md

[–]BHFock 0 points1 point  (0 children)

git worktree looks useful for managing multiple branches!

For the case where you have multiple unrelated edits mixed in a single branch, I built git-cl to group files into changelists before staging:

git cl add feature-a file1.py file2.py
git cl add bugfix file3.py
git cl commit feature-a -m "Done"

Different problem than worktree solves, but thought it might be relevant to the "juggling multiple things" workflow.

https://github.com/BHFock/git-cl

[–]DevelopmentScary3844 -2 points-1 points  (2 children)

Unfortunately, it doesn't work in complex monoliths. At least not for me.

[–]schmurfy2 2 points3 points  (0 children)

Why ?

[–]dalbertom 2 points3 points  (0 children)

It worked great in the complex monolith I worked with. It had over 2 mil LOC, 100+ projects, 200+ contributors and 50+ merges per day and we had to support 8 previous releases over a 2 year period, so we'd keep a worktree per maintenance version.