/git-overhere

Primary LanguageShellMIT LicenseMIT

git-overhere

Add individual files or sub-trees from other repos into your git tree.

Motivation

It is often the case that you wish to break up a repo into multiple repos while preserving a similar working copy environment. Common reasons include:

  • you wish to have some sub-tree shared across multiple repos

  • you wish to make some sub-tree a public repo while the main repo remains private

  • you wish to have different update flows for some sub-tree and the main repo

Existing tools

git core packaging provides git-submodule, a command that allows you to, at various points in your working copy, provide checkouts to other working copies. The user experience for git-submodule is generally awful. Users of the repo must be aware of the presence of submodules and actively use the init and update sub-commands of git-submodule. Furthermore, a user checking out a repo that leverages git-submodules must have access permissions to all referenced repos at time of checkout and future updates, often creating a case where a user can check out a repo but not usefully use it since there are unresolvable gaps in the tree.

There are some better tools such as git-subtree and git-subrepo which allow you to take the root from another repo and graft it in at some point into your git tree. git-subtree does this preserving the history of the grafted-in tree, git-subrepo does this as a point-in-time snapshot. Both of these tools (as with git-submodule) are only able to graft in another repo at its root, not a sub-tree or file.

git-subtree gives no idication in the repo that a graft has happened in the working copy, only some annotations in the commit message when a graft is done. Repos using git-subtree just work for users cloning the main repo as they will automatically get the content of the grafted repo but it doesn’t make it clear to those who might make changes and need to be aware of the difference between the main repo content and the git-subtree managed content.

git-subrepo adds a metadata file .gitrepo in the directory containing the root of the graft. This alteration of the grafted content, coupled with the .gitrepo metadata file containing the parent commit SHA that the most recent graft was done on to, means that certain git activities, particularly commit rewriting activities like rebase, are very complex or prone to fail.

Goal

git-overhere is a tool that aims to avoid the above limitations. It is not interested in preserving the full history of grafts (as with git-submodule or git-subtree). Rather, `git-overhere aims to provide clear, easy to maintain grafts of any file (blob) or tree from another repo.

Historical Note

I had wanted to name this project git-graft which felt most descriptive but, deep in git’s long, twisty history, there was a git subcommand called git-graft so I decided to avoid it entirely.

Usage

$ cd my-main-git-repo
$ git overhere add git@github.com/abrooks/subrepo.git master path/in/subrepo:path/in/our-repo
$ ls path/in/
.GIT-OVERHERE_our-repo
our-repo
$ cat .GIT-OVERHERE_our-repo
version: 1
repo: git@github.com/abrooks/subrepo.git
ref: master
path: path/in/subrepo
commit: abcdef1234567890

Notes

Use cases

  • add

  • show

  • rm

  • fetch

  • status

  • unmodified/modified update local

  • modified/modified clobber local

  • modified/unmodified clobber local (reset)

  • modified/modified merge local

  • modified/unmodified push upstream

  • modified/modified rebase local

  • move local