Skip to content
  • Duy Nguyen's avatar
    doc: outline how submodules work with multi worktrees · 07a84fe5
    Duy Nguyen authored
    This lays out the very first step of making multiple worktrees and
    submodules work together. No actual changes are here. And real changes
    are not even in the very next patches since they are cleanup and
    preparation patches.
    
    When a submodule is added to a superproject, the superproject's config
    file records info related to the submodule in its config file. The
    submodule's config file also has core.worktree to point back to the
    submodule worktree's location.
    
    Since config files are shared without extensions.worktreeConfig, adding
    a secondary superproject or submodule worktree will run into trouble [1].
    The problem could be solved with extensions.worktreeConfig and we keep
    per-worktree config in config.worktree files, both at superproject
    (submodule.*.*) and submodule (core.worktree) levels.
    
    The whole directory layout would look like this. This shows how
    multiple worktrees of a submodule or a supermodule are organized:
    
      .git/
        config                           contains shared submodule.*
        config.worktree                  contains submodule.sub1.*
                                         for the main worktree
        worktrees/
          super1/                   (1)
            config.worktree              submodule.sub1.* for super1
            modules/
              sub1/                 (2)
                config.worktree          contains core.worktree
                objects/            (3)
                worktrees/          (4)
                  wt1/
                  wt2/
          super2/                   (5)
            config.worktree              submodule.sub1.* for super2
            modules
              sub1/                 (6)
                config.worktree          contains core.worktree
                objects/            (7)
      super1/
        .git                     -> (1)
        sub1/
          .git                   -> (2)
        sub1-wt1/
          .git                   -> (4)/wt1
        sub1-wt2/
          .git                   -> (4)/wt2
      super2/
        .git                     -> (5)
        sub1/
          .git                   -> (6)
    
    This directory layout works, but not optimal. Submodule clones (inside
    the "modules" directory) are per-worktree. If you have two
    superproject worktrees that contain a submodule, you need space for
    _two_ clones, e.g. the object databases (3) and (7) are almost
    identical, but they are still duplicated.
    
    This is definitely not elegant. The tentative plan is to move the
    clones to a common tree like below. This is however just an idea and
    not implemented in this series.
    
      .git/
        config                           contains shared submodule.*
        objects/
        common/
          modules/
            sub1/                   (0)
              objects/              (shared)
              worktrees/
                super1/             (2)
                super1-wt1/         (4)/wt1
                super1-wt2/         (4)/wt2
                super2/             (6)
    	  common/
    	    modules/
    	      nested-sub/...
        worktrees/
          super1/                   (1)
            config.worktree              submodule.sub1.* for super1
          super2/                   (5)
            config.worktree              submodule.sub1.* for super2
    
    The subtree (0) is shared across all worktrees because it's inside
    "common/" directory. Once we keep the clone in a common place like
    this, the submodule's worktree can be created and managed with
    git-worktree[1].
    
    Another good point about this approach is we could finally safely
    allow "git worktree remove" to work with submodules. With current
    solution, removing $GIT_COMMON_DIR/worktrees/X directory means also
    removing potentially precious clones inside the "modules" subdir.
    
    But whether we can do this depends on:
    
    - if we need separate ref namespace for submodule on each worktree.
      Use cases that can share ref namespace will work best.
    
    - how does submodule's worktrees interact these worktrees
    
    - handling nested submodules can get very messy (or not?)
    
    This series does not attempt to implement subtree (0) at all. Once we
    get submodules and worktrees work well together (even wasteful of disk
    space), we can start thinking about absorbing clones back to common/
    
    [1] It's milder for secondary submodule worktree because core.worktree
        will not be shared (core.worktree by default is only visible to
        the main worktree). But then the second worktree cannot have its
        own core.worktree.
    07a84fe5