1. 27
  1. 5

    My work often involves working on multiple independent patch sets. Love using worktrees to get separate branches in their own directory and being able to switch without the typical git checkout I/O wait time. In fact, I like it so much that I tweet the single URL https://git-scm.com/docs/git-worktree about once a year.

    Previously:

    1. 4

      I started using git worktrees a couple of weeks ago. I had been aware of them for a while, but they didn’t sound that appealing. Now that I’m using them… should have tried sooner. It just saves me tons of time switching between branches to have them checked out simultaneously (and not having to worry about hooks being right, etc, as would be the situation with multiple clones.)

      1. 1

        The problem with multiple checkouts via worktrees is that you end up with different build directories. For small projects, that’s fine, but for something big like LLVM I want a release build and a debug + asan build and that adds up to almost 80 GiB. Doing the build also takes a lot of time, so I’d rather switch branches and do an incremental build.

        What I really want is something like a FUSE FS that uses git worktrees to give me different views of the same git repo easily, but also gives me a CoW (or, better, dedup’d) view of the associated build directory and lets the build tool see a view of the source where it only sees changes between branches and some common ancestor.

      2. 4

        Has anyone found a nice pattern for where to create these additional directories? Like the author I create them 1 directory above but it pollutes this space that holds directories for many other projects…

        Something like the following I guess should be melded into my head:

        mkdir project-being-cloned && cd project-being-cloned && git clone ... # now start making trees?
        
        1. 14

          i like to think of a project as more than just code, it has notes, references, sample data, blueprints and what not. so i start by creating a directory for the project and have all the code (worktrees) reside in one corner of this directory:

          project/
          |- worktrees/
          |  |- main/
          |  |- feature/
          |  `- bugfix/
          |- notes/
          |  |- timeline.txt
          |  `- builds.txt
          |- reference/
          |  |- prior_art.txt
          |  `- similar_project/
          `- test_data/
          
          

          so i suppose it starts with:

          mkdir -p project/worktrees && cd project/worktrees && git clone xyz main
          
          1. 2

            I really like this 🙂 Stealing!

            1. 1

              i like to think of a project as more than just code, it has notes, references, sample data, blueprints and what not.

              I completely agree here, but I am curious why you then don’t think that all of these other things belong in your revision control system.

            2. 4

              What I do is I clone the project to a branch named after the default branch, ie main, inside a directory named after a project. That way, when I checkout a worktree 1 directory above it is on the same level as the main branch

              1. 2

                I usually have one worktree per project. E.g. projectA/linux, projectB/linux, etc.

                1. 2

                  I’ve been initializing repositories from a bare clone for a few years now. The trick is to clone the git directory under, well, .git.

                  git clone --bare $remote $out/.git
                  cd $out
                  git worktree add main
                  git worktree add fix-something
                  # …
                  

                  With this strategy, you also get a simple git integration with any file manager, i.e. directories correspond to branches and worktrees are not nested.

                  Unfortunately, Git currently writes absolute path to $out/.git in worktree. That can be fixed by manually editing worktree/.git to refer to gitdir: ../.git.

                  1. 1

                    I like this idea but I’ve trouble updating the bare repository. A plain git fetch won’t fetch new branches from the remote and in a worktree something like git switch --track <remote>/<branch> which I normally use in non-worktree setups to switch branches is not available.

                  2. 1

                    You could steal the suggested layout from Subversion:

                    • trunk/projectA and branches/projectA/{feature…,bug…} or
                    • projectA/trunk and projectA/branches/{feature…,bug….}

                    Replace trunk with “master” or “main” as needed.

                    1. 1

                      I use $project for the main and then $project–$branch in the same parent directory. Also, I’ve noticed that git worktrees don’t work exactly the same as a regular repo. For instance you can’t switch a worktree to an already checked out branch, for some reason.

                    2. 3

                      Also great writing regression tests, to check whether they fail before your fix.

                      1. 3

                        I keep seeing praise of this, but the ux is horrible, pretty much no 3rd party tool supports it, and it feels like an alien concept to how most people use and understand git.

                        1. 1

                          This reminds me a lot of Perforce’s path mapping feature (I haven’t used Perforce in… at least 10 years now). Didn’t realize git had this facility!

                          1. 1

                            It seems like such a good idea, but there needs to be some workflow adjustment. Installing dependencies in each copy separately is wasteful. Copying the configuration each time is slightly annoying. It’s a bit easier for ruby where I can point bundler at a shared space, but node for example has no such configuration and an allergy to symbolic links - hope your file system can deduplicate, I guess?

                            1. 2

                              This very much sounds like a Node problem. I don’t do Node, but for things I do do where I might need per-project dependencies installed somewhere, I guess Python, I would use virtualenvs outside of the git repositories. (I’m not yet yet using multiple git worktrees with any of my Python projects.)

                            2. 1

                              This is another good illustration of why git should not win the VCS Wars forever. Obviously, all the stuff in .git should be stored in a single global per user cache. It’s not for historical design reasons, and so now you need to use worktrees to get minimally useful deduplication.

                              1. 1

                                So I love this way of working but I find that editor/IDE state doesn’t support it very well. What strategies to people have for that?