Question

I have a template repository consisting of a folder structure, scripts, makefiles, example files (text templates) etc.

The easiest way would be to clone the repo, delete the .git folder and create a new repository. Then I’d need to update the template manually.

Branching can be difficult due to great differences between a template and a project.

I want to be able to apply improvements over time to my template from/to all of my projects, with the template repository serving entirely as base for project repositories. Maybe 2 remotes can be used to do this?

Was it helpful?

Solution

You can't really do that. This isn't like in OOP where you can inherit a class and just override some things.

A git repository represents the history of your project. When you fork/clone a repository, you are building upon that history. Note, git treats remote repositories just like a branch.

x---x---x  templates
         \
          x---x---x project

You cannot really do further work on the templates repository and then do a ret-con as if your project had always included that further work. Well, you can do a merge, but if the project changed any of the template files then you will have lots of merge conflicts:

x---x---x---x-------x  templates
         \           \
          x---x---x---merge project

Git also allows you to do a ret-con of the project history, which it calls rebasing. But this doesn't prevent any merge conflicts. You effectively still have to solve all those conflicts. Rebasing works by replaying all your commits on a different history, so you get different commits as a result (as shown by a different SHA identifier). Rebasing can also get difficult if merge commits are involved.

x---x---x---x---x  templates
         \       \
          \       x'---x'---x' project (rebased)
           \
            x---x---x project (original)

Note that as far as Git is concerned, the rebased project history is completely unconnected to your original history.

The only way to prevent problems: do not modify the template files. But this defeats the purpose of the template repository.

You cannot reasonably use a template repository which you simply clone/fork. You cannot make changes to the template repository so that they are easily available in all projects created from that template. As soon as a project is started, you might as well detach from the template repository's history. If you need to include template improvements in a project, the easiest way to do this is probably to do it manually.

Could git-submodules help?

In practice, it is sometimes desirable to include the contents of one repository in another repository. You can use git-submodules to mount a repository as a directory within another repo. This lets you use git as a simple package manager.

superproject/
  .git/
  .gitmodules
  module/  (module repository checked out at commit @123abc)
    ...
  ...

But any changes within that submodule are like modifying a cloned version of the submodule repository – because that's exactly what it is. The changes are not contained to the outside superproject. Git's submodules can also be notoriously difficult to work with, and require special care for your workflows and build processes. For example, submodules are not cloned when you clone a superproject, unless you git clone --recurse-submodules.

In some cases, submodules could be a valid solution to your problems – in particular, if literally contain template files that are filled in when your project is built/deployed/run. A submodule could also be used to provide default config files.

This is still not going to work if the template is a template for the project structure, or if the template contains boilerplate files that you manually edit.

Personal recommendation

Forget about git in this scenario. Use git for version control, nothing else.

If you experience repeated boilerplate across projects, build tools and libraries to eliminate it. Require as few files to be manually edited as possible, and let your tools do as much as possible at build time.

Licensed under: CC-BY-SA with attribution
scroll top