2

I'm creating a base php project for my company, so far it has user authentication, roles, permissions, groups, etc..

My goal is that for every project we start we copy this base project and just add the features required by the client. Some of this feature may be interesting to bring back to our base project.

This is my basic workflow. My question is: how can I use git as a tool to make this workflow happen? Could you explain me in high level or would you have some link that would explain how to use git in this scenario, or a similar one?

My experience with git is reduced to create branch, make my changes and then merge back to the master, so I'm having a hard time to figure out how to use git to achieve my goal.


UPDATE: I feel I'm missing an important part of the workflow:

Currently I follow this workflow for the projects: enter image description here

There is the master branch, which I can deploy at any point to the production enrionment. Everytime I start a new sprint (scrum) I create a new dev branch and for each new feature I want to add to this dev branch I create another branch (feature branch). As I finish each feature I merge its branch back into the dev branch (the dev branch is our staging environment). And at the end of the sprint I merge the dev branch into the master branch.

This workflow works fine for me and I want to keep it for the projects I use this base app.

Let's say I find a bug in this base app, thus every project using it will have the same bug. I also want to be able to apply the fix to all the projects.

Thanks for the help

André Luiz
  • 6,642
  • 9
  • 55
  • 105

3 Answers3

3

Since the other answer here has suggested using submodules, I'll try to use a different strategy and use branches instead. This method is easier if you're just beginning with git, and don't want to use submodules. This method also assumes that your project only has one branch. Working with multiple branches is possible, but would be difficult to keep track of the changes.

Init a new project, and add the base project as a remote:

git remote add base <url>

Here, base is the name you're assigning to the remote. Now, create a new tracking branch which represents your base branch:

git branch --track base-project base/master 

With this, you'll be able to update the base branch when its updated by someone else in the remote repo.

Next, you need to checkout master and update it so that it contains all the commits in the base-project branch.

git checkout master
git rebase base-project

With this, you are ready to start building on top of your base project. If you have some changes which you would also like the base project to have, you can use the cherry-pick command to individually pick specific commits and add them to the base-project branch. Make sure your working tree is clean and your HEAD is pointing to base-project:

git cherry-pick <commit-hash> 

If you want to apply all changes introduced by master:

git cherry-pick ^HEAD master

And then push the branch to the remote repository:

git push base base-project
  • Thanks for the answer! I have up vote it and I will be trying it on monday. I like the cherry pick, if we follow some rules for the commits I may work pretty well. I have updated my question, please check it. – André Luiz Nov 12 '16 at 16:46
  • After you have created a commit with the fix and pushed it onto the remote repo, you can pull the change onto your local base-project branch (I suggest using `git pull --rebase`) and then rebase your master on top of base-project. –  Nov 12 '16 at 17:27
  • I used this answer. I achieved using fork, remote references and cherry picks. All the answers are correct but I used this one and so far it seems to be working for me. Thanks – André Luiz Nov 15 '16 at 17:06
2

My question is: how can I use git as a tool to make this workflow happen?

You should use submodules. 'Submodule' is simply a git project inside another got project, you can look on it as a dependency manger for git (but not really)

You simply need to be in your root folder and then add the submodule folder which will be the common project shared between all your other projects.

git submodule add <url>

Now when you clone the project you simply need to init and update the submodule

Add & Commit the .gitsubmodule file and in each project use this:

git submodule init
git submodule update

This will fetch the latest changes from upstream in each submodule,

If at any given time you decide to remove the submodule here is a full answer on how to do it.
What is the current way to remove a git submodule?


enter image description here

Community
  • 1
  • 1
CodeWizard
  • 128,036
  • 21
  • 144
  • 167
  • 1
    Thanks for your answer, I have up voted it! The easy update to the submodule is something I do want. I have updated my question with some more information on my current process. Please check it and tell me if you still believe that the submodules still apply. – André Luiz Nov 12 '16 at 16:54
2

My goal is that for every project we start we copy this base project and just add the features required by the client. Some of this feature may be interesting to bring back to our base project.

The best solution depends on the coupling between the base project and the added features.

If your project is designed with loose coupling in mind and the added features are independent modules that can be safely added or removed without affecting the rest of the project then you can place each feature in a Git sub-module or you can even create them as separate components (independent projects) and load them into the main project using Composer.

For both approaches, each feature will stay in its own Git repository.

Each customer will get the base project, a customized composer.json (and its corresponding composer.lock) file and some customized configuration files.

The files specific to each customer can be stored on different branches in the main project or they can be stored in sub-directories of a dedicated directory (no customer branches). They need to be copied from there (an the configuration for other customers removed) by the deployment script (or a script that is able to prepare the package for a customer).

The pros and cons of this approach:

  • (+) there is one copy of the code of each feature; changes, fixes and improvements performed on one feature are easily transferred to all customers by running composer update on the directories of all customers that use the feature;
  • (-) it doesn't allow a feature to evolve independently for two different customers; in order to do this the feature project must be duplicated.

On the other hand, if the coupling is tighter and the features cannot be extracted as independent sub-projects (they all depend on the main project nonetheless) then I would place each feature in its own sub-directory (all of them located in a features/ directory).

The main branch (master or develop or whatever name convention you use) contains the full-featured project (the main project and all the features). For each customer create a new branch starting from the main branch. All the changes for this customer happens on this branch. Start by removing from features/ the features that are not provided to the customer.

This strategy works well as long as you operate all the changes in the main project in one direction: apply them on the main branch then merge the main branch into the customer branches.

The changes on the features are usually applied on one customer branch first and, after they are validated, they can be ported to the main branch and from there to the branches of the other customers.

Porting a change in a feature from a customer branch to the main branch cannot be done by merging because usually the features are customized for each customer in a different way. You probably need to apply to the main branch only a couple of commits (that contain a fix or a functionality improvement) and you can do this using cherry-pick. Porting the changes in a feature from the main branch to the customer branches usually can be done using merging because the main branch should contain only generic code, no customization.

axiac
  • 68,258
  • 9
  • 99
  • 134
  • Thanks for your answer, I have up voted it! I will be going for the tight couple way, with cherry picks. I have added some more information to my question, please check it. – André Luiz Nov 12 '16 at 16:50