this post was submitted on 05 Apr 2024
127 points (96.4% liked)

Programming

17666 readers
382 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities [email protected]



founded 2 years ago
MODERATORS
top 25 comments
sorted by: hot top controversial new old
[–] [email protected] 13 points 8 months ago (8 children)

Why using a worktree? I will simply commit my WIP modifications on the dev branch.

Switch branch to work on the bugfix. And when Im finished I move back to the development branch? Why is this worse than doing this worktree stuff?

[–] QuadriLiteral 16 points 8 months ago (3 children)

I'm a C++ dev, I have one checkout of the main repo and 3 worktrees. Switching branches can be expensive because of recompiles, so to do e.g. quick fixes I'll use worktree 1 where I typically don't even compile the code, just make the fix and push it to the CI system. Worktrees 2 and 3 I keep at older releases so I can immediately fire up development and one of those releases side by side and compare results as well as the code.

The cool thing about worktrees instead of multiple checkouts is that you only have one .git folder, so less disk space. But more importantly local branches (well everything actually) are shared, so you can create a local branch in the main checkout, and later come back to it in a worktree. You also don't need fetching/... in the worktrees, as they share the same .git folder.

Only thing that I found virtually impossible to work with is worktree + submodules.

[–] expr 5 points 8 months ago

Huh, you know what, maybe I'll give something like that a try. In the past I've tried doing one worktree per branch, but it was a pretty big hassle since I'd have to copy over a bunch of files every time (stuff sitting in the directory but not version-controlled). Yeah it can be automated, but it didn't seem worth it. But a persistent set of work trees that I can use to parallelize when needed sounds pretty good.

[–] ruffsl 2 points 8 months ago (1 children)

Ah man, I'm with a project that already uses a poly repo setup and am starting an integration repo using submodules to coordinate the Dev environment and unify with CI/CD. Sub modules have been great for introspection and and versioning, rather than relying on some opaque configuration file to check out all the different poly repos at build time. I can click the the sub module links on GitHub and redirect right to the reference commit, while many IDEs can also already associate the respective git tag for each sub module when opening from the super project.

I was kind of bummed to hear that working trees didn't have full support with some modules. I haven't used working trees with this super project yet, but what did you find about its incompatibility with some modules? Are there certain porcelain commands just not supported, or certain behaviors don't work as expected? Have you tried the global git config to enable recursive over sub modules by default?

[–] QuadriLiteral 2 points 8 months ago

I found basic functioning of worktrees to fail with submodules. The worktree doesn't know about submodules, and again and again messes up the links to it. Basic pulling, switching branches, ..., all of this frequently fails to work because the link to the submodule is broken. I ended up creating the submodules as worktrees of a separate checkout of the submodule repo, and recreating these submodule worktrees over and over. I pretty much stopped using worktrees at that point.

Have you tried the global git config to enable recursive over sub modules by default?

Nope, fingers crossed it helps for you ;) Unrelated to worktrees but: in the end I like submodules in theory but found them to be absolutely terrible in practice, that's without even factoring in the worktrees. So we went back to a monorepo.

[–] [email protected] 2 points 8 months ago

thanks for elaborating. will give it a try :)

[–] [email protected] 6 points 8 months ago

I'm imagining a scenario where you're working on a feature that changes the DB state (e.x. introduces a new DB migration that changes some columns) and the bug is on an unrelated part of the code from your feature. In this hypothetical, going back to the state of the upstream branch would make your local environment non functional, and the bug is on an unrelated part of the code. Fairly specific scenario but hey, you can worktree for that. It's not particularly thorough, though.

[–] [email protected] 4 points 8 months ago

A monrepo is another good reason (besides those mentioned). When switching branches changes hundreds of files, it's not so quick or slick anymore.

[–] [email protected] 3 points 8 months ago (1 children)

A commit followed by a reset or commit --amend later is one more step than a worktree --add. Plus there have been lots of times when I've had some changes staged, and some unstaged debugging or experimental changes that I want to make sure not to commit, and thinking about how to pack all that away neatly so I could get back where I was seemed sufficiently obnoxious that I avoided doing whatever would have required a quick branch switch. Worktree would have let me pick up where I left off without having to think about it.

[–] [email protected] 1 points 8 months ago

Hmmm. Thanks. I might try it out another time soon:).

[–] firelizzard 2 points 8 months ago
  • Scenario: I'm in the middle of writing a new feature.
  • Boss, to me: "Shit broke. Go figure it out."
  • Me, thinking: I'm in the middle of doing some complex work. If I commit/stash and close the open files, it will take a day for me to remember WTF I was doing.
  • Me: "Oh look, worktrees! I can leave my workspace intact with all the files open, pending changes, test results, terminal output, everything! And just create a new worktree to checkout the production version and debug! I'm saved!"

Also setting up a worktree is really easy. git worktree add ../hotfix prod-branch && cd ../hotfix and get working. Though in reality it's cd ../hotfix && git checkout prod-branch because I've never needed more than one secondary worktree.

[–] [email protected] 2 points 8 months ago

Recently I had to do an update to the underlying environment a codebase ran on. This was a somewhat involved upgrade and took a longer period of time than most of our work usually does. I did it in a separate worktree, so I didn't have to constantly rejuggle the installed dependencies in the project, and could work on two features relatively concurrently

It also provides some utility for comparing the two versions. Nothing you couldn't do other ways, but still useful

[–] [email protected] 1 points 8 months ago* (last edited 8 months ago) (1 children)

Because spending 1h+ recompiling everything whenever a colleagues points out a typo in a merge request is a waste of time

[–] [email protected] 1 points 8 months ago (1 children)

did I use worktree the wrong way? the subfolder with the repository where the worktree was placed, has to be recompiled anyway?

[–] [email protected] 1 points 8 months ago

If you have a build directory per worktree then no. Every branch is built independently

[–] [email protected] 1 points 8 months ago (1 children)

Because you'd have to stash your modifications to be able to switch branch. The stash is a stack so very limited in what it can do (just push and pop). You might prefer to commit on a temporary branch instead. But you might also need some parts from your current modifications for the bug fix, at which point having it taken away on another branch or in stash won't do. I would usually end up resorting to doing another checkout side by side anyway, and if I can make it a sparse checkout it's even better.

[–] lysdexic 1 points 8 months ago* (last edited 8 months ago) (1 children)

Because you’d have to stash your modifications to be able to switch branch.

OP said nothing about stashing, only committing WIP commits to feature branches. I don't think none of your remarks apply, because if you really need stuff from the WIP commits you can also cherry-pick them or checkout specific files.

[–] [email protected] 1 points 8 months ago (1 children)

If you find it more comfortable to keep swapping checkouts in the same dir that's cool. I'm just explaining that some of use find it easier to keep several different checkouts around, and sparse checkouts are helpful when you do that.

[–] lysdexic 1 points 8 months ago

Fair enough.

[–] [email protected] 11 points 8 months ago (1 children)

I've been using the newer commands like switch and restore for a while. But I learned a few things here that will indeed make my work easier.

[–] lysdexic 3 points 8 months ago (1 children)

git switch and git restore were introduced way back in 2019. I don't think they count as new.

[–] [email protected] 5 points 8 months ago

Wdym? 2019 was last year. Right...?

[–] JavaTheHutt 4 points 8 months ago

I should really start using switch and restore. I haven't destroyed work yet due to a fat finger, but it as always its good to get into the habit of using safer commands.

I would love to get the chance to use bisect one day. Usually when the opportunity comes up, the range of commits I'd have to look through cover large refactors or broken code or tests that make it infeasible, Because I'd have to spend more time than it's worth altering my local setup to try and isolate the issue.

[–] firelizzard 3 points 8 months ago

Additionally, switch performs extra sanity checks that checkout doesn't, for example switch would abort operation if it would lead to loss of local changes.

What checks? Under what situation does checkout lead to loss of changes? If I make changes and attempt to checkout a ref that would overwrite them, I get the following error:

error: Your local changes to the following files would be overwritten by checkout:
        some/file
Please commit your changes or stash them before you switch branches.
Aborting

To my knowledge it's not possible to overwrite changes when switching branches/refs (git checkout <ref> without any other arguments or flags) so I guess what the author really means is, "If you use checkout incorrectly you can overwrite local changes." As far as I can recall I've never accidentally git checkout <ref> <some/file> so I don't see a reason to retrain my muscle memory. I do use git restore since it's behavior is a lot more obvious than checkout/reset though sometimes I still use git checkout <ref> -- <some/file> because muscle memory.

[–] FizzyOrange 2 points 8 months ago

Note that worktree does not work with submodules. Which IMO is a strong enough reason to never use submodules because worktrees are so useful!