I think your idea of cloning your template is best. But you can tweak that by using GitHub or similar site.
With GitHub you would fork for each new project based on your template.
The fork would create a brand new git repository but based on your template.
Now if one your projects has an update you would like picked up in your original template repository, you could submit a pull request to the original template. Others could too, if you wanted to share.
Then you would simply accept the pull requests you found that you want to incorporate into your original project.
Use the Gitflow Workflow
Following this model, the master
branch contains only releases, the develop
branch contains the WIP (work in progress) commits, and feature
branches are used to develop features.
The main benefit of this approach is, if you screw up and publish a bad commit to develop
you'll be able to rollback the changes without screwing up the the history of the publicly accessible version on master
.
So, that doesn't answer your question...
What about combining partial features into a single feature commit?
Simple, before merging a feature
branch into develop
squash the commits using interactive rebase.
git rebase -i feature-branch
It'll pop up an editor and you can change which commits you want to squash. It also concats the commit logs so you can add all/part of them into the squashed commit message.
Note: There are many ways to squash commit history. IMHO, I think interactive rebase is the most straight-forward but YMMV.
When you're ready for a release, simply create a release
branch from develop
and merge the release
branch into `master.
Developing features can be challenging because a maintainer may require a contributor to make additional changes piecemeal prior to accepting a PR (pull request).
Using the strategy above, the contributor will still have a granular history containing all of the changes made to the feature throughout development. This makes it easy to roll-back and/or cherry-pick commits individually.
Note: The ability to cherry-pick commits is extremely valuable if the contributor runs into complicated merge conflicts.
If you want features to commit cleanly, simply have the contributor squash the changes as the last step prior to a merge.
Best Answer
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.
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:
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.
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.
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.