2

What may be a plausible workflow for using nested repos instead of submodules, in a git repository? the idea being, to decouple parts of a large repo without using git submodules, but without adding much complication.

Can it be accomplished by simply nesting repos having their own remotes, while still resulting in a sane workflow?

matanster
  • 15,072
  • 19
  • 88
  • 167
  • A submodule _is_ a nested repository. Everything the submodule command does is just (intended to be) a convenience, e.g. for helping cloners find he right upstream for the repo and and keeping it safe from `rm -r` (by hoisting it into a handy, and arbitrary, hideaway spot in toplevel repo) and such. `git add` of a repo adds the currently-checked-out commit hash. That's all it does. `git checkout` of a path that has a commit hash aka commit id just creates the directory there, if you want that commit checked out, either you do it or get, oh, say the submodule command, to do it for you. – jthill Jan 06 '16 at 02:00

2 Answers2

3

That would be called git subtree (see "The power of Git subtree" ,and "Alternatives To Git Submodule: Git Subtree ").

I illustrate one git subtree workflow in this answer.

subtree

It uses git read-tree and git merge --squash –s subtree

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
2

Submodules are aggravating and in my experience, usually a bad idea. What I do in some of my projects is combine nested repositories and .gitignore entries. So the nested repos are ignored by the outer container repo, but I don't have to hassle with submodules at all.

In my situation, I usually use my own scripts to handle things like cloning, updating, and cleaning up the nested repos. It's not difficult to cook up something like that.

Here is a Perl example of something I do for managing Vim plugins as nested repositories. Full script at this URL, snippet of it below.

https://github.com/tangledhelix/dotfiles/blob/master/install.pl

# install or update vim bundles
sub vim_bundle_installer {
    my $bundle_path = "$ENV{HOME}/.vim/bundle";
    mkdir $bundle_path unless -d $bundle_path;

    foreach my $bundle (keys %vim_bundles) {
        my $repo = $vim_bundles{$bundle};
        unless ($repo =~ /^(https?|git):\/\//) {
            if ($use_ssh) {
                $repo = "git\@github.com:$repo.git";
            } else {
                $repo = "https://github.com/$repo.git";
            }
        }
        my $this_bundle_path = "$bundle_path/$bundle";
        if (-d $this_bundle_path) {
            next if $vim_newmods_only;
            if ($vim_do_updates) {
                print "    updating vim bundle $bundle\n";
                system "cd $this_bundle_path && git pull";
            } else {
                print "    skipping vim bundle $bundle (already exists)\n";
            }
        } else {
            print "    cloning vim bundle $bundle\n";
            system "git clone $repo $this_bundle_path";
        }
    }

}

sub vim_newmods_installer {
    $vim_newmods_only = 1;
    vim_bundle_installer();
}

sub vim_bundle_updater {
    $vim_do_updates = 1;
    vim_bundle_installer();
}
Dan Lowe
  • 51,713
  • 20
  • 123
  • 112
  • This makes sense, other than it might preclude the possibility of using standard-laden continuous integration services like travis.ci... as it won't necessarily run your script for getting all of the code in. I haven't checked, but I think it might be a problem. – matanster Oct 29 '15 at 17:03