Grab the git cheatsheet once it's released here: philomatics.com/git-cheatsheet (Might still take a bit though, of course I underestimated how much work it would be lol)
I agree with Grug. Good grug sense here. Complexity of worktree only worth in specific situations. Grug sorry for clickbait, but bring views. Grug hope other grug still learn something so no reach for club! If not, grug sorry for waste time!
@@philomatics You also mentioned that worktree allows you not to have multiple cloned repos. But at the end of the day, that's just semantics. A worktree is just another full version of the tree in your filesystem. Cloning or not, one is managed on a fs level, one on a git level, but tomato tomato.
This all stems from commit aversion and people treating commits as production-ready items. If you push your commits and that starts some CI or release process, then sure you'd want to avoid that. Committing locally to a feature branch should never do that in any sane workflow, so there's no reason to avoid a local commit. You can always fixup, squash, amend, etc. before you're ready to push your polished code to the remote. For some reason people conflate "commit" with "irreversible code changes that are production-ready" when all a commit means is "this is the current state of the tracked code." All these weird workflows can be avoided by just getting rid of unreasonable, commit-averse mentalities. What you've done here is basically commit code mentally ("these are the changes I've made and I'd like them to remain in this state," which is literally a commit) and developed a workflow to avoid using the one feature that all of Git relies on.
This is so fucking true. We also need to understand that it's fine to have not-yet-finished code in your codebase. I've always taught commits to serve as a checkpoint, nothing more nothing less. I personally think that the release process should be almost entirely separate from the push, and people have made me feel insane for years
No, having multiple worktrees has not necessarily something to do with "commit aversion". If you are working on multiple features, fixes etc. in parallel and the build times are slow: That is the use case.
@@cdoubleplusgood Sure, if you willfully ignore the premise of the video presented in the first 12 seconds: " *You're not quite ready to commit* your work yet, so you stash your changes." Commit aversion. Maybe you watched a different video, but I am responding to the premise *actually* presented in this video, not your opinion of a viable workflow.
my workflow has come to include many temporary commits that get rearranged/squashed/renamed before pushing, so whenever i need to switch branches i just commit everything and undo it when i come back. this has the added benefit of being virtually unable to lose those changes due to reflog.
and, you can use config to do this automatically. I use these options git config --global pull.rebase true git config --global pull.autoStash true git config --global rebase.autoStash true
I used git worktree for quite a while. I had separate worktrees for some release branches and for a special build for a particular customer. That was exactly to avoid long rebuild times when switching between those. But I stopped doing that for two reasons. I just need to switch to an older release version much less frequently than I used to because we roll out new versions much faster these days. And the rebuild time with faster hardware and newer IDE versions is much shorter. There are also some drawbacks of git worktree. If your repo is big you may run out of disk space if you always keep many worktrees, or maybe just backups or virus scanning or similar stuff may take longer. Also, keeping track of your worktrees can be a bit confusing. Maybe git has gotten better at worktree maintenance, but when I removed worktrees I always had to make sure that I removed both the directory where the worktree was checked out and also tell git that the worktree is now gone. Even if that works better now, you still have to mentally keep track of the worktrees you have, what you use them for and in what state they are in. If you are like me, that can be a mental burden.
It's better in so far that you can list and delete worktrees pretty easily via the cli. I still sometimes find a random folder in my projects folder and wonder what it is, just to realise it's a worktree of a different one ^^ I guess that could be helped, by having a shared parent folder for all work trees.
@@SourceOfViewsyeah I don't get why you can have worktrees inside of worktrees. Do people use that? It only makes sense for me to have one parent directory contain all worktrees. Or _maybe_ categorize the branches in folders
@@yochem9294 worktrees in worktrees? Does that work? I meant that usually, you just git clone and then get one folder with the repository in there (aka the default worktree). Then if you just quickly want a new worktree, you'd have to make that in a completely new folder. I guess if you use it heavily you could do something like mkdir myrepo git clone /myrepo main
It doesn't really replace git-stash, it's just another layer of things that get out of control if you don't put in the time to prune frequently. For me the big advantage of worktrees is that it's more like being off on a branch, so if you try to update to a more frequent base, and it goes awry, you can more easily back out and retry. For that reason I mostly use it for development which has gotten kind of distant, like trunk vs production branches, or a particularly gnarly set of changes which are going to have to be heavily revised before landing.
it's by far _the_ best video about git worktree I've seen, you really nailed it showing the file structure, other videos just brag about how good it is without explaining how the heck it works.
Oh my goodness, this is so helpful! Thank you so much! I had to wait for over 10 minutes when I was switching between branches, and I even thought about cloning the git to keep each in its own branch, but that would waste space.
Sounds more like a faster alternative to making another clone of the repo to work on two branches in parallel, than a replacement for stash. I don't do that too often, but when I do I'll try to remember this.
Vscode doesn't support them either, that's why in the video he opens the worktree in a new vscode instance. You can do the same with eclipse/vs-ide/intellij, just open the new worktree as a "project". Second con, is not a problem specific to worktree, its a git skill issue.
@@Metruzanca But unlike VSCode, Eclipse(or STS for that matter) should import the project . Furthermore the project name should be changed to avoid duplicate error. Not difficult but a bit more bothersome.
🤯wow :) I can't say I'm going to use it instead of git switch, but I wanted another branch/commit opened at the same time a few times, it's really a saver for these situations!
I just create a wip commit. Powerline 10k even shows a wip indicator in the shell prompt git status if the last commit has "wip" in the name so I'll immediately be reminded that I still need to clean that commit up.
Been using git for years but this is new to me - thanks! Been doing something similar using 'cp -a' but this has some worthwhile extra safety features.
15 seconds in and I already can't relate. I'd just commit rather than stash. What are you crazy? What if the computer fries and I lose all that work I've been doing? Just commit and push, that's what it's for. If your workflow is setup like any other normal project, nothing should be deployed to prod until a PR is merged. Stashing to me is something I do for something super short term. Like, I need to stash so I can drop the changes on another branch, or pull, or do some other modification where the code needs to be placed in some short term storage. Anything that'll take more than 1 minute, just commit.
This is fine if you don't care about running CI needlessly (you probably should care), or your pull requests are squash merged (otherwise you'd have a ton of "WIP" commits in your Git history)
The #1 purpose of a remote repository is source code backup. If your workflow is hindering you from backing up your code to a remote repo, your setup is not correct. Perhaps CI should be enabled on only a few branches and not all branches in your workflow. Regarding WIP commits, it is what it is. One can create a new branch and squash commits into meaningful ones if needed, before merging to the main branch. That is better than the alternative, which is crashing your laptop and losing hours or days worth of work.
@@AmitB You work on a local branch, commit to that brach and push that branch to the server. It doesn't triggert CI, CI has no business running on user branches. It should run on pull requests, not branches that are pushed. You will squash and cleanup your branch before turning that into a pull request. Stash do not fix any problem, they are the equivalent of zipping and unzipping your changes locally and you have no server backup
I’m with you. Is git meant to be a tool to get work done or is the whole git tree another product that has to be some sort of work of art in itself? Maybe the whole thing in your branch is currently a shambles that will melt the servers and kill your dog. Who cares? You’re going home for the day, so commit it. Now it’s backed up and shared and if you’re hit by a bus or just stuck remote tomorrow all that work won’t be lost. The idea that this is somehow not in service of collaboration boggles my mind. Hoarding all your work till it’s in some pretty bow-tied form isn’t collaborative.
Worktrees are nice and I've been using them a bit. It can be quite useful, but it's a very different feature than stashing. In your example, yes worktrees are fine. Personally I'd probably just make a quick temporary commit and then checkout whatever I want to have. But if building takes a long time or I'm currently executing some longer running tests, I would probably use worktrees. The temporary commit also has the benefit of you being able to push it and also making it much harder to loose as opposed to worktrees. Stashes I mostly use when - I quickly want to move the changes e.g. while rebasing or even sometimes when I was accidentally on the wrong branch - I want to quickly undo all the changes that I made to test in a before-after manner.
I don't get the argument about compilation-time. It's a complete additional instance, so you have to download all dependencies again and compile the whole project again. But with a stash, in most cases only a few files should change, so only a small part of the project has to be re-compiled.
That's a good point. I guess it depends on how much you're stashing and especially how different the state of the other branch you're switching to is. So in some cases stashing might make more sense.
@@philomatics Yes, and probably also on the language/framework. I'm working on a project with an Angular frontend, switching branches or stashing is super fast. No need to restart the dev-server, it just hot-reloads within a few seconds. But if the backend changes, I have to recompile and (which takes longer) restart the server. And if the database schema changes ... then I hope somebody else does that task so I don't need to switch xD
Thanks for this comment, I had the same thoughts and I was wondering if I was missing something. Another issue would be if it's a web project using a server configured to serve specific directories - the newly created work tree wouldn't be used by it. So overall, it seems like use cases are fairly limited here.
If I find myself reviewing a lot of pull requests locally for a specific repository, I might create two separate copies of the project - one for making coding changes and another for reviewing PRs. I'll create an alias for the PR repository so I can easily distinguish between the project folders. It's similar to using "git worktree", but it's a one-time manual setup. If I need a more dynamic setup where worktrees are created and removed frequently, then using a tool for managing worktrees makes sense.
My main use for stash is counteracting my bad habit of just starting work for a new feature on my current branch before I've created a new feature branch for it and then I have to move over my changes to that new branch
Worktree is great! If you set it up correctly, you can use it with workspaces in most programming languages. This means you don't have to rebuild when switching work trees.
This exact scenario is 80% of my personal motivation to just use jj (jujutsu vcs) as a cli for git repos. It treats working copy as a commit (aka revision) that you are currently editing. So if I'm working on a feature, and I suddenly need to work on a different feature, I just switch to that feature's revision, work there, and switch back when I'm done. I don't even have to think about stashing something, remembering to pop it later, or manually managing worktrees. I can still use worktrees (jj calls them workspaces) if I need to leave build running in the background while working on different features, or to just avoid rebuilds as mentioned in this videos, but in my case - I never had to. And the rest of jj's features (commit editing with automatic rebasing, ability to just leave conflicts in the working directory to resolve them later, operation log, etc) so far is just a nice bonus.
thanks for sharing this command! seems like if you use this often enough, it would be easier to just have a second cloned repo. if you don't use this often, it might be easier to just do a commit. If you want to change the commit, you could do a soft reset after coming back to the branch the second repo has the added benefit of retaining your untracked gitignored local configs and settings
Right, it's definitely situational. There are some advantages over a full clone though, mainly disk space usage and also a bit less fetch/pull/push ceremony.
personally, I structure my bare git repos (for git worktrees) like this, a folder named "source" in the root of the folder structure for the repo, then branches like "main" and "preprod" under the "source" branch. then I also have a folder "feature" (among others) under the "source" branch, then I keep feature branches in there. So if I have a branch "feature/implement-important-thing" I would place it here: "source/feature/implement-important-thing" (git worktree add -b 'feature/implement-important-thing' source/feature/implement-important-thing main)
I almost didn't watch that video because I never stash, always just commit and rebase all stuff interactively later (or amend to that commit, whatever). The worktree feature is really nice, I knew that it exists but never used it somehow, thank you!
Wait, I don't see node_modules in the new worktree. So would that mean I'd have to run npm install again before I can run it? Isn't that a waste of time, the few seconds which we intended to save in the first place?
I just maintain separate workspaces even if it's the same repo, what I get as a benefit here is, now I can put other files and folders, that the repo's code is dependent on, in this isolated workspace
Great video. Clear explanation! Can you also make video on these. Why these issues happens? 1. You have divergent branches and need to specify how to reconcile them 2. There isn't anything to compare. main and your branch are entirely different commit histories.
Thank you for the suggestions and the nice comment! Just to clarify: 1. Do you mean merge conflicts? If so, I already have a video on that here: th-cam.com/video/DloR0BOGNU0/w-d-xo.html 2. Gotcha. Can you tell me about a specific situation where that happened to you? Would help me understand the use case a bit better. What were you trying to do, what was your goal?
@@philomatics I made a branch fix/bugs from dev branch. 1. I committed to fix/bugs but before pushing to fix/bugs, I took pull from dev branch in case if some one merged the PR on dev. But strangely, I got divergent branches error. I went with fast forward option but fast forward option did not work. With git config pull.rebase false, it said that fix/bugs is Already up to date. 2. Now I created a PR in base:dev
@@HaiderAli-oi5fm Thanks for clarifying! For 1.: How exactly did you pull? Here's what I would do: git checkout -b fix/bugs # fix the bug, commit git checkout dev git pull origin dev git checkout fix/bugs git merge dev Does this match your workflow? If you'd like additional help, you can send me a screenshot of your commit history graph via email (in my YT about page).
Git can always find ways to make things unnecessarily complex. There are two functions TFS had, that either I didn't discover how to do it in Git, or Git does not have them: Suspend Work and Shelve. Git Stash is not the same thing, because it only stores changes on the local machine.
The closest equivalent to shelvesets in git is committing to a temporary feature branch and pushing to the shared repo so the other person can look at it, make further changes, etc. I say "the closest equivalent", because git doesn't have all the fundamental flaws that are built into all linear history VCSs that necessitated things like shelvesets, checking out code, and locking files in the first place.
@@philomatics You should have mentioned in the video the worktrees should be used as workspaces, in the sense that, you shouldnt do 1 worktree "per branch", but 1 worktree per simultaneous tasks you can handle at once. This workflow framing makes way more sense. Great introductory video to worktrees anyway.
@@philomatics Disk-space, yes.. "regular fetching" prob not. I assume he has folder he does most of his work in, and only goes to the secondary folder when he needs to the quick fix.. And I would always do a fresh fetch if I was asked to do a quick fix, (I will hope/assume he does the same).. So prob the same amount of fetching. Though, the fetch will likely be bigger in size depending on how often he does quick fixes. Though, he hasn't needed my help with any git related stuff in multiple years now, so I assume whatever his process is, is working for him.
Worktrees are better than separate clones, since you're really working in just ONE git repo. Besides being more efficient, you can reference commits made in one worktree (say for a cherry-pick) in another worktree without any push/pull! And I use both worktrees AND stashes: you can reference your same stashes across all your worktrees. I sometimes do this when I start a change in one worktree/branch and quickly decide it should be in another instead but I don't want to create a commit - I'll stash save in worktree 1 and stash pop in worktree 2. This is nice especially when you have long-lived worktrees checkout out anyway.
I really liked using worktrees, they're useful when you have very long-running things you keep having to switch between. They do have one major downside - they don't work well with submodules. It's even still in the documentation that the support is incomplete, but it was even worse when I needed it. Also, I feel that when your repository is huge it's sometimes nicer to just stash and switch in-place for the hotfix scenario you mentioned.
I built my own simple implementation of “open in terminal” using a shell script running in an Automator app, and then making my own toolbar icon. The problem is that as I have upgraded MacOS and the UI changes, I have to update the icon, which is a pain in the ass to get to fit with the rest of the native ones. So I’m going to give this a try ^
My approach is even simpler, more brute force and works with every version of Git: I always have each of my projects cloned multiple times. Disk space is cheap; 1 TB SSD costs 50 bucks (maybe 80 for a high quality SSD module) and my biggest project is around 1.2 GB when fully cloned, so even with having this one fully cloned 4 times, I require 0.0048 TB of disk space. Usually I have 4 clones named main, feature, hotfix and release and you can probably guess which branches each of them is currently set to. However, there isn't always an active feature, hotfix or release branch, so even when I'm working on feature A on the feature clone and need to quickly fix something for feature B, I can just switch hotfix or main to the branch of feature B and make the fix there, commit, push and continue to work on feature A without stashing anything. The clone names are just hints what that clone is intended for but in the end, those are just 4 copies that can each be set to any branch at any time. I could also name them 1 to 4 but most of the time they are used for their intended purpose, hence the naming does make sense.
Yeah full clones totally work too. One thing I like about worktrees is that you save yourself from a lot of fetch/pull/push ceremony. But other than that, using clones is totally fine!
I've used both `git stash` and worktrees. Worktrees are undoubtedly more flexible but a pain to setup if you have uncommitted files in the folder (.venv, vscode config, passwords that don't get committed, etc.). Committing immediately and cleaning up the branch at the end is my preferred method but that won't always work if the precommit hooks say you haven't done everything you need to do (linting, formatting, updating documentation, ...) so then it's back to stashing.
I can see the value of this when you need to test a feature branch that's waiting for some webhook but still need to work on your own feature branch in the meantime. Happend to me a shit load of times actually.
I will continue stashing with this one. It's a huge mono repo and the entire system (even dev envs) have some hard dependencies on the path, it would be impossible for me to test changes in another folder. If the worktree feature worked like a seamless layer on top of stash and switch it would be far easier to make this work. Right now it's a doesnotworktree.
Since it's a separate repo, you'll have more disk space usage, also when you fetch/pull, of course only one of the repos will get updated, which can get annoying after a while.
Interesting, but I probably won’t be using it. My current use of git stash is for when we are doing a major project rework and I have uncommitted changes. I don’t want to commit them to the main branch since that’s about to have a massive overhaul, so instead I stash them which as looks to be about the same thing as creating then committing to a dead branch, except quicker. For actually doing this sort of workflow for switching between branches, I don’t know why anyone didn’t tell me earlier but squashing commits is super easy as long as they aren’t pushed to remote, just a git revert -soft HEAD~n. This also makes rebasing super easy, since it’s all just one commit instead of having to deal with merge conflicts across multiple, which I don’t fully understand how to do yet. With rebasing just one commit, it acts the same as a merge conflict resolution, which I can do.
In addition to what people suggest about commiting with plan to amend later - in a project with scenario as described I am not enjoying idea of cleaning up commits. Just do a WIP commit and merge it - you will be able to see what was your progress with adding some bizzare bug - like implementing something one way before weekend, and continuing it wrong after. And keep merge/PR history clean instead of the full commit history. And blame git for not having concept of remote reflogs 😢
Worktrees are the Right Answer for most people in most situations. Worktrees are also default in bzr since 2006, and have a much more robust implementation there. The non-worktree style was one of Linus's big mistakes with git.
Not quite, since it's a separate repo, you'll have more disk space usage, also when you fetch/pull, of course only one of the repos will get updated, which can get annoying after a while.
I don't know.... Nnless I have a global build cache, creating a new worktree means building everything from scratch. That doesn't sound good. A scenario where is does make sense, is if you have significantly divergent branches, e.g. LTS branch, current branch, next-release branch. I try to avoid them for small changes, because it can be quite painful to wait for the IDE, to reindex all files and I can't really have more than 2 instances open anyways because I'll run out of memory.
That's a good point. I guess it depends on how much you're stashing and especially how different the state of the other branch you're switching to is. So in some cases stashing might make more sense.
I didn't understand this "benefit" either. The video suggests there is a benefit of not having to wait for a compile (for example). But I thought the same as you - if the new worktree is bare, you are stuck with the build requirement. If the "worktree" command copied your current directory, then updated the new GIT metadata and switched to a different branch, you could (possibly) do an incremental build in the new tree. Otherwise stash and checkout wins, because you do keep all your compiler outputs and can build incrementally.
Sure! Main difference is disk space usage, and with multiple clones you often have to fetch/pull/push, which can get annoying. If that doesn't bother you, nothing wrong with having multiple clones.
I just never felt the need to stash when i could just commit to any old branch. Its not like it is hard, and in some ways it doesnt require you to think about the whole stash stack. you just go back to the work whenever you want. rebase if you need to bring it together.
What I use git-stash for: for changes that I want to apply at anytime. like changing ports for local dev, custom files, log outputs, endpoints that are just for debugging etcpp. for temp commits (your use-case of git stash), this is goat: alias gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"' alias gunwip='git rev-list --max-count=1 --format="%s" HEAD | grep -q "\--wip--" && git reset HEAD~1'
What are the benefits of using worktrees as opposed to just cloning the git directory? `git clone example-project example-project-hotfix` I can think of two things. `origin` is the directory, so you cant push to the actual remote without extra steps. 2nd is that you can get a list of worktrees, but not if you just clone. Are there other benefits?
This worktree thing seems being mentally heavier than just cloning the repo into a neighboring folder without any "worktree" concepts and links. Frankly, don't see a single reason to memorize that stuff.
I agree - too much complexity and things can break mysteriously. Better to have independent clones. If disk space is a concern, buy a bigger disk, it’s cheaper than increased mental load in the long run.
@@philomatics maybe, but for me the mental model is way simpler when there are two absolutely separate clones that are easy to control in a clear explicit way, and when you are absolutely sure there is no covert magic going on. Explicitness and simplicity over efficiency (which never was a problem for me). In dev env, will choose those every day
@@cdoubleplusgoodif you clone from a local clone on Linux it hard-links to the original .git directory and takes up no more space than a work tree. Then adjust the push target to push changes upstream.
I would like to know why I would ever use a worktree instead of just cloning the local repo to another folder. Is it maybe a lot faster? Looks a lot like a solution looking for a problem.
What happens if I'm using an IDE with uncommited config files, maybe some secrets or just compiled stuff? Would that be copied into the second worktree? Wouldn't it break directory-based filepaths? Seems that this works best for very simple project structures...
Great questions! No, unfortunately those files won't be copied automatically. And yeah, directories will break, but hopefully you don't have any hardcoded absolute paths ^^
@@philomatics Hopefully not! :D But I meant relative paths reaching out of, say, modules which are separated between different repositories, but depend on each other? "../../module2" will become "../module2"
hey, great video - I'm using worktrees for a while, but never seen so well explained. quick question: what's that file manager that appears around 1:44? Thanks!
Thanks for the kind words :) Maybe I misunderstood, but that's just the Finder, the default file manager on macOS. The cyan frame is just from my video editing software :)
Then you have to load your new worktree in your IDE and do whatever setup you need to do on a project by project basis in that IDE. Worktrees could be useful in some cases, but I don't feel like temporary branch hopping is the case. Rather than stash, I'd say just commit with a comment to make it clear it's a work in progress, then squash that commit away before you push to your repo.
You're right about the IDE. I think I should've highlighted this in the video better that this is more for long-lived workflows and only useful in specific situations. I think your WIP commit workflow is a good one too! Thanks for your comment!
I guess open source has product managers trying to hit OKRs now, because this is a terrible misfeature. Worktrees and stash are symptoms of the obscurity of interactive rebase, and the (perceived?) cost of clone. It is much simpler to commit whatever is in-flight with a “WIP - ” message and then checkout the hotfix branch. Interactive rebase before push cleans up the history, which is the main reason why people think they need stash or worktree.
Fully agree, making wip commits and rebasing is what I do most of the time as well. That said, you gotta be comfy with interactive rebase for that, which unfortunately not many people are.
Something you failed to mention is that it doesn't duplicate ignored files (obviously). In any normal environment files in the .gitignore are vital for execution and so a worktree will either require manual duplication of ignored files or it simply won't work. Sometimes these files are enormous, so in cases such as this worktrees aren't particularly viable
Is this more space efficient than just having 2 copies checked out? Sure. but is it more convenient? Hardly. I've been working with multiple checked out instances of my big projects for years and as an extra those git "instances" are linked to each other by adding a git remote pointing to the other folder. This gives me full control, the ability to push things between editor instances as well as a convenient backup in case i mess up a rebase.
For those files that are checked out in the other worktree, yup, that'll use more disk space. So might not be suitable depending on your repo/workflow.
I still prefer git stash but I see the merit of this for long build times as you said. The main thing I don't like about this is that I need to open a new editor instance.
Never used git stash. I just make a local branch ([ featureBranchName ]-local), then git merge everything to the feature branch. The local version filled with countless micro commits. Worktrees seem better tough.
Grab the git cheatsheet once it's released here: philomatics.com/git-cheatsheet
(Might still take a bit though, of course I underestimated how much work it would be lol)
Grug sense complexity spirit demon. Grug say, "no thanks"
I agree with Grug. Good grug sense here. Complexity of worktree only worth in specific situations. Grug sorry for clickbait, but bring views. Grug hope other grug still learn something so no reach for club! If not, grug sorry for waste time!
Grog think same thing
@@philomatics You also mentioned that worktree allows you not to have multiple cloned repos. But at the end of the day, that's just semantics. A worktree is just another full version of the tree in your filesystem. Cloning or not, one is managed on a fs level, one on a git level, but tomato tomato.
Other Grug agree
Another agree
This all stems from commit aversion and people treating commits as production-ready items. If you push your commits and that starts some CI or release process, then sure you'd want to avoid that. Committing locally to a feature branch should never do that in any sane workflow, so there's no reason to avoid a local commit. You can always fixup, squash, amend, etc. before you're ready to push your polished code to the remote. For some reason people conflate "commit" with "irreversible code changes that are production-ready" when all a commit means is "this is the current state of the tracked code." All these weird workflows can be avoided by just getting rid of unreasonable, commit-averse mentalities. What you've done here is basically commit code mentally ("these are the changes I've made and I'd like them to remain in this state," which is literally a commit) and developed a workflow to avoid using the one feature that all of Git relies on.
This is so fucking true. We also need to understand that it's fine to have not-yet-finished code in your codebase. I've always taught commits to serve as a checkpoint, nothing more nothing less. I personally think that the release process should be almost entirely separate from the push, and people have made me feel insane for years
I agree with you. Committing and then potentially rebasing later is totally fine, especially if you are comfortable with interactive rebase.
I commit always on a branch while working on it but it is also just necessary so that the CI/CD can actually build it so I can deploy and test.
No, having multiple worktrees has not necessarily something to do with "commit aversion". If you are working on multiple features, fixes etc. in parallel and the build times are slow: That is the use case.
@@cdoubleplusgood Sure, if you willfully ignore the premise of the video presented in the first 12 seconds: " *You're not quite ready to commit* your work yet, so you stash your changes." Commit aversion. Maybe you watched a different video, but I am responding to the premise *actually* presented in this video, not your opinion of a viable workflow.
my workflow has come to include many temporary commits that get rearranged/squashed/renamed before pushing, so whenever i need to switch branches i just commit everything and undo it when i come back. this has the added benefit of being virtually unable to lose those changes due to reflog.
Fucking TH-cam deleted my fucking comment. No idea why. Anyway, I said that I agree with you.
Been doing this recently and it’s honestly fine because can also squash a follow-up commit.
This is how I work too
Yeah I really like doing that too. You need to be comfortable with interactive rebases to do that, but if you are, it's a good workflow as well.
Honest question, why do you prefer this over stash? I used to do this too, until I learned about stash
Also, instead of git stash; git pull; git stash pop. There's git pull --autostash. It even works with --rebase
I forgot this was even an option, it's one of the first things I configure on new machines to have autostash by default.
and, you can use config to do this automatically. I use these options
git config --global pull.rebase true
git config --global pull.autoStash true
git config --global rebase.autoStash true
I used git worktree for quite a while. I had separate worktrees for some release branches and for a special build for a particular customer. That was exactly to avoid long rebuild times when switching between those. But I stopped doing that for two reasons. I just need to switch to an older release version much less frequently than I used to because we roll out new versions much faster these days. And the rebuild time with faster hardware and newer IDE versions is much shorter.
There are also some drawbacks of git worktree. If your repo is big you may run out of disk space if you always keep many worktrees, or maybe just backups or virus scanning or similar stuff may take longer. Also, keeping track of your worktrees can be a bit confusing. Maybe git has gotten better at worktree maintenance, but when I removed worktrees I always had to make sure that I removed both the directory where the worktree was checked out and also tell git that the worktree is now gone. Even if that works better now, you still have to mentally keep track of the worktrees you have, what you use them for and in what state they are in. If you are like me, that can be a mental burden.
It's better in so far that you can list and delete worktrees pretty easily via the cli.
I still sometimes find a random folder in my projects folder and wonder what it is, just to realise it's a worktree of a different one ^^
I guess that could be helped, by having a shared parent folder for all work trees.
Agreed, it's definitely a trade off!
@@SourceOfViewsyeah I don't get why you can have worktrees inside of worktrees. Do people use that? It only makes sense for me to have one parent directory contain all worktrees. Or _maybe_ categorize the branches in folders
@@yochem9294 worktrees in worktrees? Does that work?
I meant that usually, you just git clone and then get one folder with the repository in there (aka the default worktree).
Then if you just quickly want a new worktree, you'd have to make that in a completely new folder.
I guess if you use it heavily you could do something like
mkdir myrepo
git clone /myrepo main
@@SourceOfViews What you can do is clone your repo as a bare repo (git clone --bare), then you can create worktrees inside the repo without issue.
Note that you can use: git switch -C , to switch to a branch and create it beforehand
Good suggestion! I wanted to separate the commands here as to not confuse beginners, but yeah, I usually do `git checkout -b branchname`.
I prefer creating a dump commit and just amending it, stashes are basically "special" branches so what makes them so special to use
Yeah that works well too!
Exactly my view and workflow . Stash also has no branch knowledge, so no point to use them .
Yep in this case I would do a WIP commit
This is the way
Idk about that, when I make a stash in Git Fork it is displayed in the tree view as the latest item of the branch it was made on @@dudeabideth4428
It doesn't really replace git-stash, it's just another layer of things that get out of control if you don't put in the time to prune frequently. For me the big advantage of worktrees is that it's more like being off on a branch, so if you try to update to a more frequent base, and it goes awry, you can more easily back out and retry. For that reason I mostly use it for development which has gotten kind of distant, like trunk vs production branches, or a particularly gnarly set of changes which are going to have to be heavily revised before landing.
You can also commit the partial changes and then ammend when ready
This is the way. No need to add yet another layer of complexity.
I thought I was crazy😂....thank you😊
it's by far _the_ best video about git worktree I've seen, you really nailed it showing the file structure, other videos just brag about how good it is without explaining how the heck it works.
Another great example of why everyone should work the way they personally feel most productive, creative, and do their best quality work.
Oh my goodness, this is so helpful! Thank you so much! I had to wait for over 10 minutes when I was switching between branches, and I even thought about cloning the git to keep each in its own branch, but that would waste space.
Sounds more like a faster alternative to making another clone of the repo to work on two branches in parallel, than a replacement for stash. I don't do that too often, but when I do I'll try to remember this.
That's right! Difference is mainly disk space usage, and with worktrees you have a lot less fetch/pull/push ceremony.
Agreed. I'm definitely gonna try using worktrees, but not as a replacement for clones instead of a replacement for stash/temp-commit.
Worktree CONS:
- unsupported by some tools, e.g Eclipse,..
- easy to accidental remove local branch used in other worktree
Vscode doesn't support them either, that's why in the video he opens the worktree in a new vscode instance. You can do the same with eclipse/vs-ide/intellij, just open the new worktree as a "project".
Second con, is not a problem specific to worktree, its a git skill issue.
@@Metruzanca But unlike VSCode, Eclipse(or STS for that matter) should import the project . Furthermore the project name should be changed to avoid duplicate error. Not difficult but a bit more bothersome.
Everyday I learn something new about git.
Same goes with neovim and gnu std lib
you make fantastic videos on git! i've learned more from them than my years of basic git usage alone
Thank you very much!
git config -global rebase.autostash true; git config -global rebase.autosquash true; : you’re welcome
🤯wow :) I can't say I'm going to use it instead of git switch, but I wanted another branch/commit opened at the same time a few times, it's really a saver for these situations!
I just create a wip commit. Powerline 10k even shows a wip indicator in the shell prompt git status if the last commit has "wip" in the name so I'll immediately be reminded that I still need to clean that commit up.
Yeah I think this is a really good approach too.
Works fine but sometimes I don't want to rebuild and reinstall dependencies
Another thing, git clone --bare can create a wrapper for the worktree feature branches. Example mobile-app/ folder can have all the worktree inside.
Been using git for years but this is new to me - thanks! Been doing something similar using 'cp -a' but this has some worthwhile extra safety features.
15 seconds in and I already can't relate. I'd just commit rather than stash. What are you crazy? What if the computer fries and I lose all that work I've been doing? Just commit and push, that's what it's for. If your workflow is setup like any other normal project, nothing should be deployed to prod until a PR is merged. Stashing to me is something I do for something super short term. Like, I need to stash so I can drop the changes on another branch, or pull, or do some other modification where the code needs to be placed in some short term storage. Anything that'll take more than 1 minute, just commit.
This is fine if you don't care about running CI needlessly (you probably should care), or your pull requests are squash merged (otherwise you'd have a ton of "WIP" commits in your Git history)
The #1 purpose of a remote repository is source code backup. If your workflow is hindering you from backing up your code to a remote repo, your setup is not correct. Perhaps CI should be enabled on only a few branches and not all branches in your workflow.
Regarding WIP commits, it is what it is. One can create a new branch and squash commits into meaningful ones if needed, before merging to the main branch. That is better than the alternative, which is crashing your laptop and losing hours or days worth of work.
If your repo is your glorified backup, fine. If your repo is a collaboration tool, worktree is awesome.
@@AmitB You work on a local branch, commit to that brach and push that branch to the server. It doesn't triggert CI, CI has no business running on user branches. It should run on pull requests, not branches that are pushed. You will squash and cleanup your branch before turning that into a pull request. Stash do not fix any problem, they are the equivalent of zipping and unzipping your changes locally and you have no server backup
I’m with you. Is git meant to be a tool to get work done or is the whole git tree another product that has to be some sort of work of art in itself?
Maybe the whole thing in your branch is currently a shambles that will melt the servers and kill your dog. Who cares? You’re going home for the day, so commit it. Now it’s backed up and shared and if you’re hit by a bus or just stuck remote tomorrow all that work won’t be lost.
The idea that this is somehow not in service of collaboration boggles my mind. Hoarding all your work till it’s in some pretty bow-tied form isn’t collaborative.
Well explained, thx. I've done that with separate folders without knowing worktree feature until now.
Worktrees are nice and I've been using them a bit. It can be quite useful, but it's a very different feature than stashing.
In your example, yes worktrees are fine.
Personally I'd probably just make a quick temporary commit and then checkout whatever I want to have. But if building takes a long time or I'm currently executing some longer running tests, I would probably use worktrees.
The temporary commit also has the benefit of you being able to push it and also making it much harder to loose as opposed to worktrees.
Stashes I mostly use when
- I quickly want to move the changes e.g. while rebasing or even sometimes when I was accidentally on the wrong branch
- I want to quickly undo all the changes that I made to test in a before-after manner.
Thanks for sharing! Temporary commits work well too in my experience!
I don't get the argument about compilation-time. It's a complete additional instance, so you have to download all dependencies again and compile the whole project again. But with a stash, in most cases only a few files should change, so only a small part of the project has to be re-compiled.
That's a good point. I guess it depends on how much you're stashing and especially how different the state of the other branch you're switching to is. So in some cases stashing might make more sense.
@@philomatics Yes, and probably also on the language/framework. I'm working on a project with an Angular frontend, switching branches or stashing is super fast. No need to restart the dev-server, it just hot-reloads within a few seconds. But if the backend changes, I have to recompile and (which takes longer) restart the server. And if the database schema changes ... then I hope somebody else does that task so I don't need to switch xD
Thanks for this comment, I had the same thoughts and I was wondering if I was missing something.
Another issue would be if it's a web project using a server configured to serve specific directories - the newly created work tree wouldn't be used by it. So overall, it seems like use cases are fairly limited here.
If I find myself reviewing a lot of pull requests locally for a specific repository, I might create two separate copies of the project - one for making coding changes and another for reviewing PRs. I'll create an alias for the PR repository so I can easily distinguish between the project folders. It's similar to using "git worktree", but it's a one-time manual setup.
If I need a more dynamic setup where worktrees are created and removed frequently, then using a tool for managing worktrees makes sense.
My main use for stash is counteracting my bad habit of just starting work for a new feature on my current branch before I've created a new feature branch for it and then I have to move over my changes to that new branch
Worktree is great! If you set it up correctly, you can use it with workspaces in most programming languages. This means you don't have to rebuild when switching work trees.
This exact scenario is 80% of my personal motivation to just use jj (jujutsu vcs) as a cli for git repos.
It treats working copy as a commit (aka revision) that you are currently editing.
So if I'm working on a feature, and I suddenly need to work on a different feature, I just switch to that feature's revision, work there, and switch back when I'm done.
I don't even have to think about stashing something, remembering to pop it later, or manually managing worktrees.
I can still use worktrees (jj calls them workspaces) if I need to leave build running in the background while working on different features, or to just avoid rebuilds as mentioned in this videos, but in my case - I never had to.
And the rest of jj's features (commit editing with automatic rebasing, ability to just leave conflicts in the working directory to resolve them later, operation log, etc) so far is just a nice bonus.
Cool, gotta check that out, thanks for commenting!
thanks for sharing this command!
seems like if you use this often enough, it would be easier to just have a second cloned repo.
if you don't use this often, it might be easier to just do a commit. If you want to change the commit, you could do a soft reset after coming back to the branch
the second repo has the added benefit of retaining your untracked gitignored local configs and settings
Right, it's definitely situational. There are some advantages over a full clone though, mainly disk space usage and also a bit less fetch/pull/push ceremony.
personally, I structure my bare git repos (for git worktrees) like this, a folder named "source" in the root of the folder structure for the repo, then branches like "main" and "preprod" under the "source" branch. then I also have a folder "feature" (among others) under the "source" branch, then I keep feature branches in there.
So if I have a branch "feature/implement-important-thing" I would place it here: "source/feature/implement-important-thing"
(git worktree add -b 'feature/implement-important-thing' source/feature/implement-important-thing main)
Thanks for sharing!
I almost didn't watch that video because I never stash, always just commit and rebase all stuff interactively later (or amend to that commit, whatever). The worktree feature is really nice, I knew that it exists but never used it somehow, thank you!
Thank you! I think your workflow is also totally fine though!
Bro came on my feed out of nowhere and started cooking
Wait, I don't see node_modules in the new worktree. So would that mean I'd have to run npm install again before I can run it? Isn't that a waste of time, the few seconds which we intended to save in the first place?
That's right, unfortunately. This is why I prefer to keep worktrees around for longer usually.
That's one of the advantages of pnpm over npm.
Simply create temporary branch and commit, then reset it and continue. You can even push this branch to server to be super safe in terms of data lost.
Very informative. Looking forward to the cheat cheat 🎉
Cool! I used to checkout whole repo to a new directory to work in parallel in two branches
Thanks for considering my suggestion. good explanation.
Thanks again for the suggestion!
I just maintain separate workspaces even if it's the same repo, what I get as a benefit here is, now I can put other files and folders, that the repo's code is dependent on, in this isolated workspace
I personally use shelve as a more convenient way of storage
Great video. Clear explanation!
Can you also make video on these. Why these issues happens?
1. You have divergent branches and need to specify how to reconcile them
2. There isn't anything to compare. main and your branch are entirely different commit histories.
Thank you for the suggestions and the nice comment!
Just to clarify:
1. Do you mean merge conflicts? If so, I already have a video on that here: th-cam.com/video/DloR0BOGNU0/w-d-xo.html
2. Gotcha. Can you tell me about a specific situation where that happened to you? Would help me understand the use case a bit better. What were you trying to do, what was your goal?
@@philomatics
I made a branch fix/bugs from dev branch.
1. I committed to fix/bugs but before pushing to fix/bugs, I took pull from dev branch in case if some one merged the PR on dev. But strangely, I got divergent branches error.
I went with fast forward option but fast forward option did not work.
With git config pull.rebase false, it said that fix/bugs is Already up to date.
2. Now I created a PR in base:dev
@@HaiderAli-oi5fm Thanks for clarifying!
For 1.: How exactly did you pull? Here's what I would do:
git checkout -b fix/bugs
# fix the bug, commit
git checkout dev
git pull origin dev
git checkout fix/bugs
git merge dev
Does this match your workflow? If you'd like additional help, you can send me a screenshot of your commit history graph via email (in my YT about page).
@@philomatics Sorry i caught up in work. Yeah that solved my problem.
@@HaiderAli-oi5fm No worries, glad to hear it worked!
Git can always find ways to make things unnecessarily complex. There are two functions TFS had, that either I didn't discover how to do it in Git, or Git does not have them: Suspend Work and Shelve. Git Stash is not the same thing, because it only stores changes on the local machine.
The closest equivalent to shelvesets in git is committing to a temporary feature branch and pushing to the shared repo so the other person can look at it, make further changes, etc. I say "the closest equivalent", because git doesn't have all the fundamental flaws that are built into all linear history VCSs that necessitated things like shelvesets, checking out code, and locking files in the first place.
1:04 my co-worker just clones the repo into another folder...
I will just stick to stashing..
Yeah that works too, just more disk space and regular fetching/pulling work, but no biggie.
@@philomatics You should have mentioned in the video the worktrees should be used as workspaces, in the sense that, you shouldnt do 1 worktree "per branch", but 1 worktree per simultaneous tasks you can handle at once. This workflow framing makes way more sense. Great introductory video to worktrees anyway.
@@philomatics Disk-space, yes.. "regular fetching" prob not.
I assume he has folder he does most of his work in, and only goes to the secondary folder when he needs to the quick fix..
And I would always do a fresh fetch if I was asked to do a quick fix, (I will hope/assume he does the same).. So prob the same amount of fetching. Though, the fetch will likely be bigger in size depending on how often he does quick fixes.
Though, he hasn't needed my help with any git related stuff in multiple years now, so I assume whatever his process is, is working for him.
@@BlueCardinal33 Good point! Should have mentioned that.
Worktrees are better than separate clones, since you're really working in just ONE git repo. Besides being more efficient, you can reference commits made in one worktree (say for a cherry-pick) in another worktree without any push/pull! And I use both worktrees AND stashes: you can reference your same stashes across all your worktrees. I sometimes do this when I start a change in one worktree/branch and quickly decide it should be in another instead but I don't want to create a commit - I'll stash save in worktree 1 and stash pop in worktree 2. This is nice especially when you have long-lived worktrees checkout out anyway.
This is super cool.
Had no idea this existed.. Looks useful!
I really liked using worktrees, they're useful when you have very long-running things you keep having to switch between. They do have one major downside - they don't work well with submodules. It's even still in the documentation that the support is incomplete, but it was even worse when I needed it.
Also, I feel that when your repository is huge it's sometimes nicer to just stash and switch in-place for the hotfix scenario you mentioned.
Agreed, it is a situational command for sure.
I didn't know worktrees could reside outside the main repo! That's so much better than how I used to do it!
Amazing. You just changed my life 😂
How did you get the "Open in Terminal" and "Open in VSCode" buttons in the Finder toolbar? The icons as well.
Same question
Actually I found the thing that I use again:
Check out this repo (I use the lite version): github.com/Ji4n1ng/OpenInTerminal
I built my own simple implementation of “open in terminal” using a shell script running in an Automator app, and then making my own toolbar icon. The problem is that as I have upgraded MacOS and the UI changes, I have to update the icon, which is a pain in the ass to get to fit with the rest of the native ones. So I’m going to give this a try ^
worktrees sounded great until I remembered my main project depends on node
I'm glad you've made me discover that
My approach is even simpler, more brute force and works with every version of Git: I always have each of my projects cloned multiple times. Disk space is cheap; 1 TB SSD costs 50 bucks (maybe 80 for a high quality SSD module) and my biggest project is around 1.2 GB when fully cloned, so even with having this one fully cloned 4 times, I require 0.0048 TB of disk space. Usually I have 4 clones named main, feature, hotfix and release and you can probably guess which branches each of them is currently set to. However, there isn't always an active feature, hotfix or release branch, so even when I'm working on feature A on the feature clone and need to quickly fix something for feature B, I can just switch hotfix or main to the branch of feature B and make the fix there, commit, push and continue to work on feature A without stashing anything. The clone names are just hints what that clone is intended for but in the end, those are just 4 copies that can each be set to any branch at any time. I could also name them 1 to 4 but most of the time they are used for their intended purpose, hence the naming does make sense.
Yeah full clones totally work too. One thing I like about worktrees is that you save yourself from a lot of fetch/pull/push ceremony. But other than that, using clones is totally fine!
Thanks for this. Its frustrating to shift to multiple branches during code review and stashing. This reduce most my time.
I use oh-my-zsh with git plugin. It provides two aliases: gwip and gunwip to create and reset WIP commit on the current branch
I've used both `git stash` and worktrees. Worktrees are undoubtedly more flexible but a pain to setup if you have uncommitted files in the folder (.venv, vscode config, passwords that don't get committed, etc.).
Committing immediately and cleaning up the branch at the end is my preferred method but that won't always work if the precommit hooks say you haven't done everything you need to do (linting, formatting, updating documentation, ...) so then it's back to stashing.
I can see the value of this when you need to test a feature branch that's waiting for some webhook but still need to work on your own feature branch in the meantime.
Happend to me a shit load of times actually.
I will continue stashing with this one.
It's a huge mono repo and the entire system (even dev envs) have some hard dependencies on the path, it would be impossible for me to test changes in another folder.
If the worktree feature worked like a seamless layer on top of stash and switch it would be far easier to make this work. Right now it's a doesnotworktree.
What is the difference between worktrees and cloning multiple times (for most used branches)?
Since it's a separate repo, you'll have more disk space usage, also when you fetch/pull, of course only one of the repos will get updated, which can get annoying after a while.
Interesting, but I probably won’t be using it. My current use of git stash is for when we are doing a major project rework and I have uncommitted changes. I don’t want to commit them to the main branch since that’s about to have a massive overhaul, so instead I stash them which as looks to be about the same thing as creating then committing to a dead branch, except quicker.
For actually doing this sort of workflow for switching between branches, I don’t know why anyone didn’t tell me earlier but squashing commits is super easy as long as they aren’t pushed to remote, just a git revert -soft HEAD~n. This also makes rebasing super easy, since it’s all just one commit instead of having to deal with merge conflicts across multiple, which I don’t fully understand how to do yet. With rebasing just one commit, it acts the same as a merge conflict resolution, which I can do.
In addition to what people suggest about commiting with plan to amend later - in a project with scenario as described I am not enjoying idea of cleaning up commits. Just do a WIP commit and merge it - you will be able to see what was your progress with adding some bizzare bug - like implementing something one way before weekend, and continuing it wrong after. And keep merge/PR history clean instead of the full commit history.
And blame git for not having concept of remote reflogs 😢
Awesome video ! CAN you tell us what is the Finder extension you are using at 2:37 ?
Thank you!
Sure, check out this repo (I use the lite version): github.com/Ji4n1ng/OpenInTerminal
finally my brain get the concept of worktrees. already came across some videos about it but this is my "Eureka" moment lol. thanks for the video
Worktrees are the Right Answer for most people in most situations. Worktrees are also default in bzr since 2006, and have a much more robust implementation there. The non-worktree style was one of Linus's big mistakes with git.
okay, but wouldn't cloning the repo in a different directory accomplish the same?
Not quite, since it's a separate repo, you'll have more disk space usage, also when you fetch/pull, of course only one of the repos will get updated, which can get annoying after a while.
@@philomatics yes that makes sense! Thanks!
I don't know.... Nnless I have a global build cache, creating a new worktree means building everything from scratch. That doesn't sound good.
A scenario where is does make sense, is if you have significantly divergent branches, e.g. LTS branch, current branch, next-release branch.
I try to avoid them for small changes, because it can be quite painful to wait for the IDE, to reindex all files and I can't really have more than 2 instances open anyways because I'll run out of memory.
That's a good point. I guess it depends on how much you're stashing and especially how different the state of the other branch you're switching to is. So in some cases stashing might make more sense.
I didn't understand this "benefit" either. The video suggests there is a benefit of not having to wait for a compile (for example). But I thought the same as you - if the new worktree is bare, you are stuck with the build requirement. If the "worktree" command copied your current directory, then updated the new GIT metadata and switched to a different branch, you could (possibly) do an incremental build in the new tree.
Otherwise stash and checkout wins, because you do keep all your compiler outputs and can build incrementally.
This is awesome! I can finally delete the copy of my day job source code, which I had to do exactly this! My small SSD thanks you
Could someone elaborate on why not just clone the repository in a separate directory? git worktree remove is just a fancy rm. So what am I missing?
Sure! Main difference is disk space usage, and with multiple clones you often have to fetch/pull/push, which can get annoying. If that doesn't bother you, nothing wrong with having multiple clones.
I just never felt the need to stash when i could just commit to any old branch. Its not like it is hard, and in some ways it doesnt require you to think about the whole stash stack. you just go back to the work whenever you want. rebase if you need to bring it together.
Why not just have two or more clones, side by side, and then they are truly independent, and if you delete one you don’t risk breaking the other ones.
Sure, if that works for you, no downside! Main difference is disk space usage and more frequent fetching/pushing when having separate clones.
What I use git-stash for: for changes that I want to apply at anytime. like changing ports for local dev, custom files, log outputs, endpoints that are just for debugging etcpp. for temp commits (your use-case of git stash), this is goat:
alias gwip='git add -A; git rm $(git ls-files --deleted) 2> /dev/null; git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"'
alias gunwip='git rev-list --max-count=1 --format="%s" HEAD | grep -q "\--wip--" && git reset HEAD~1'
Beautiful!!
Thanks for the tip!!
What are the benefits of using worktrees as opposed to just cloning the git directory?
`git clone example-project example-project-hotfix`
I can think of two things. `origin` is the directory, so you cant push to the actual remote without extra steps. 2nd is that you can get a list of worktrees, but not if you just clone.
Are there other benefits?
Great question! It's mainly less disk space usage with work trees. Also for long lived worktrees you have less fetch/pull/push ceremony.
DIRECTORY. IT IS CALLED A DIRECTORY.
(nice vid btw :) )
i can barely convince people to use more the same two branches forever, never got anything more complicated to catch on
This worktree thing seems being mentally heavier than just cloning the repo into a neighboring folder without any "worktree" concepts and links. Frankly, don't see a single reason to memorize that stuff.
I agree - too much complexity and things can break mysteriously. Better to have independent clones. If disk space is a concern, buy a bigger disk, it’s cheaper than increased mental load in the long run.
Yeah, the main advantage over separate clones is that you don't need to fetch/push so often for long lived worktrees.
@@philomatics maybe, but for me the mental model is way simpler when there are two absolutely separate clones that are easy to control in a clear explicit way, and when you are absolutely sure there is no covert magic going on.
Explicitness and simplicity over efficiency (which never was a problem for me). In dev env, will choose those every day
If your repo size is 70 GB like mine your conclusion might be different.
@@cdoubleplusgoodif you clone from a local clone on Linux it hard-links to the original .git directory and takes up no more space than a work tree. Then adjust the push target to push changes upstream.
Git is really powerful, I predict that someday someone will build a source control tool on top of it
Nice roast
Thanks for the video, this is interesting. What’s the benefit of worktrees over just cloning the repo into two different folders?
Great question! Mainly disk space usage, and with worktrees you have a lot less fetch/pull/push ceremony.
@@philomatics makes sense, thank you!
there's also gitless which autostashes (including more of the state than just working dir changes) automatically on branch switches
I would like to know why I would ever use a worktree instead of just cloning the local repo to another folder. Is it maybe a lot faster? Looks a lot like a solution looking for a problem.
Not a big difference, mainly less disk space usage and less fetching/pushing.
@@philomatics thanks for info. Sorry about my tone btw, oof.
@@aaaidan No worries, we all got good and bad days :)
What happens if I'm using an IDE with uncommited config files, maybe some secrets or just compiled stuff? Would that be copied into the second worktree? Wouldn't it break directory-based filepaths? Seems that this works best for very simple project structures...
Great questions!
No, unfortunately those files won't be copied automatically. And yeah, directories will break, but hopefully you don't have any hardcoded absolute paths ^^
@@philomatics Hopefully not! :D
But I meant relative paths reaching out of, say, modules which are separated between different repositories, but depend on each other? "../../module2" will become "../module2"
@@urban24 Ah I see, yeah that would break unfortunately.
hey, great video - I'm using worktrees for a while, but never seen so well explained.
quick question: what's that file manager that appears around 1:44? Thanks!
Thanks for the kind words :)
Maybe I misunderstood, but that's just the Finder, the default file manager on macOS. The cyan frame is just from my video editing software :)
@@philomatics I saw two icons for opening the console and vscode at the top, so I assumed it was a different one! Thanks!
@@LeonardoRotaRossi Ah yeah, check out this repo for those (I use the lite version): github.com/Ji4n1ng/OpenInTerminal
Then you have to load your new worktree in your IDE and do whatever setup you need to do on a project by project basis in that IDE.
Worktrees could be useful in some cases, but I don't feel like temporary branch hopping is the case.
Rather than stash, I'd say just commit with a comment to make it clear it's a work in progress, then squash that commit away before you push to your repo.
You're right about the IDE. I think I should've highlighted this in the video better that this is more for long-lived workflows and only useful in specific situations.
I think your WIP commit workflow is a good one too!
Thanks for your comment!
I guess open source has product managers trying to hit OKRs now, because this is a terrible misfeature. Worktrees and stash are symptoms of the obscurity of interactive rebase, and the (perceived?) cost of clone.
It is much simpler to commit whatever is in-flight with a “WIP - ” message and then checkout the hotfix branch. Interactive rebase before push cleans up the history, which is the main reason why people think they need stash or worktree.
Fully agree, making wip commits and rebasing is what I do most of the time as well. That said, you gotta be comfy with interactive rebase for that, which unfortunately not many people are.
Something you failed to mention is that it doesn't duplicate ignored files (obviously). In any normal environment files in the .gitignore are vital for execution and so a worktree will either require manual duplication of ignored files or it simply won't work.
Sometimes these files are enormous, so in cases such as this worktrees aren't particularly viable
Good point, should've mentioned that!
Any info on how to add the terminal and vscode icons on the finder window?
Is this more space efficient than just having 2 copies checked out? Sure. but is it more convenient? Hardly. I've been working with multiple checked out instances of my big projects for years and as an extra those git "instances" are linked to each other by adding a git remote pointing to the other folder. This gives me full control, the ability to push things between editor instances as well as a convenient backup in case i mess up a rebase.
Makes sense! If this fits your workflow, nothing wrong about having separate clones :)
@@philomatics Nothing wrong with the new option either. In fact more options are (up to a point) great.
didn't know about this, thanks a lot
I just commit and switch branch with a dummy message and then I switch back and reset the commit and I'm back where I was.
OMG! Mind blown, thanks for sharing
Is it more like a carbon copy of the entire repo ? Which means we are temporarily consuming double the storage required if we have two work trees ?
For those files that are checked out in the other worktree, yup, that'll use more disk space. So might not be suitable depending on your repo/workflow.
Loved the content😍😍😍😍😍
learning something new in git after long time
I don't understand why one cannot simply fork another branch from the current feat branch, commit, push and proceed with work on the hotfix?
Sure, that works too, but then you gotta continue work on that other branch, or merge it somehow. If you're fine with that workflow, go for it!
Just in time when I was wondering how to isolate a new module development that may take sometime while hot-fixing the current version
Sounds like svn. What happens to all user secrets I the new dir? I don't think it comes along for the ride.
I still prefer git stash but I see the merit of this for long build times as you said. The main thing I don't like about this is that I need to open a new editor instance.
Yeah definitely both workflows have their merits
Never used git stash. I just make a local branch ([ featureBranchName ]-local), then git merge everything to the feature branch. The local version filled with countless micro commits. Worktrees seem better tough.
great vids dude, just wondering how can we add a vscode button to open vscode in the finder? thanks
Thank you! Check out this repo (I use the lite version): github.com/Ji4n1ng/OpenInTerminal
Git has been capable of this since 2015, and you're telling me NOW?! Fortunately there's no risk at all of me going entirely overboard with this....