5

We will be forking a project into its own codebase, but it will closely follow the project it forked from.

I see it working like this:

Forked project will develop some initial changes to rebrand product. I wouldn't want to share these changes with the original project, but going forward I want to merge changes.

The way we have it setup is separate repos that have the same history now and just add remotes for Each other.

The workflow I was thinking of was this:

We should try to work on feature branches and only have 1 commit per feature so we can each to git cherry-pick . Whenever you work on a feature and make a commit, just do git commit --amend in the branch for the feature. When it is finalized I can cherry-pick the commit.

I don't like this because if the feature gets changed after cherry picking the developer needs to remember to NOT am end but create a new commit.

I would love a way to do this with a merge or rebase.

Chris Muench
  • 17,444
  • 70
  • 209
  • 362
  • 1
    What do you mean by 'their initial changes'? Changes after you fork? – GoZoner Apr 06 '13 at 02:26
  • They will be adding their logo and changing CSS and images. The backend will remain largely unchanged. ( it is a white label version of the program) – Chris Muench Apr 06 '13 at 12:40

6 Answers6

3

One possible way to structure this is with three repositories where one repository is the 'white label version' and the other two repositories are for the two front ends. The two front ends would reference the 'white label version' repository as a submodule.

With this structure you:

  1. have clearly called out the white label version as a shared resource that is 'controlled' but others
  2. yet, still allow for changes to the white label version by the two front ends
  3. allow the two front ends to develop independently with their repository contents.

If your two front ends are going to be similar, then they can be branches of one repository (but both dependent on the submodule). In this case, if you are merging back and forth between the two front ends, a good approach is to create a branch for each and every feature. Having a branch per feature frees you from the restriction of 'one commit per branch'. [edit] Depending on the nature of the feature branch you could a) cherry-pick all the commits using <branch-base>..<branch-head>; or b) rebase everything on the branch into one commit and then cherry-pick that one commit or c) use merge/rebase to get the feature branch onto another branch (See the numerous examples from the git rebase documentation, particularly the --onto option.) [/edit]

Also here is a common, well-respected branching model with a discussion on feature branches.

[edit2] You can do this with one repository if you prefer. Keep three primary branches: white-label-dev, prod1-dev, prod2-dev and have the developers on each of the three teams operate only on their branches or their created branches off of their branches. When one team has something that should be shared, the 'corporate integration lead' will do the work of moving commits from that one team's work to the other team's branches. (Moving the commits as I described above.)

Your teams will need some discipline to avoid mucking with another team's branches. But, if you've got a shared repository you can assign hooks to prevent pushes from the wrong team onto another team's branches. [/edit2]

GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • 1
    For my money this is the only correct answer. A commit is an entire history. If you want two projects with partially shared history you factor the histories into the entirely-shared part and the entirely-per-project part, and reflect the separation in the filesystem and in git. – jthill Apr 08 '13 at 04:52
  • This sounds good, but it isn't easy to separate into 2 distinct repos because I am using a framework (codeigniter) that isn't made for doing it as described. There will also be some different pieces in the backend. Is there a way to do this with 2 repos or is cherry picking the way to go for now? – Chris Muench Apr 08 '13 at 16:11
  • '2 repos' as: a) one for the 'white label version' plus one for both project A and B; or b) one for project A and one for Project B? [I suspect you are asking about 'b'] – GoZoner Apr 08 '13 at 16:17
  • 1
    Code that can't be made to serve two different projects without actually modifying its innards isn't a framework. – jthill Apr 08 '13 at 22:13
2

Suggested workflow:

  • New branch for each feature
  • Developer commits normally to the feature branch
  • When merging to the master branch do:

git merge --squash -m 'new feature' branchname

Now, delete the branch!

git branch -D branchname

  • If the developer needs to fix something or change the feature, he creates a new branch from the master. Everything else is the same.

The next merge will appear as a different commit on the master branch.

Edson Medina
  • 9,862
  • 3
  • 40
  • 51
  • Won't squash still merge in other changes because the branches have diverged? Thats why I was thinking of cherry-pick – Chris Muench Apr 12 '13 at 17:58
  • Yes, diverged commits will be merged. See my earlier answer where I noted: `git cherry-pick ..` will only include commits on the branch itself. (Or you squash the branch to one commit and cherry pick that one). – GoZoner Apr 13 '13 at 00:10
  • 1
    I like this way, it is pretty simple – Chris Muench Apr 13 '13 at 13:58
  • this is pretty much a lightweight variant of [git flow](http://nvie.com/posts/a-successful-git-branching-model/) (here linked for reference) – BlueWizard Dec 15 '16 at 07:38
1

I think that you want to follow a similar procedure that Github uses for keeping forked projects updated.

To start off with would be the whitelabel repo. This is the one that the other projects would fork from. Then the other projects would be a clone of the whitelabel with the whitelabel being set as the upstream repo. Using this you would be able to do git merge upstream/master or git rebase upstream/master depending on the workflow.

The advantage is that you aren't dealing having to keep straight the status of the main project. The other projects become their own forks and can be updated easily. Trying to cherry-pick changes could get onerous easily especially with many commits. And doing this if one of the other projects wants to make changes to code that came from the original repo, you can manage that change much easier.

http://www.techblogistech.com/2012/07/setting-a-default-upstream-branch-in-git/

See the section about pulling in changes here: https://help.github.com/articles/fork-a-repo

Schleis
  • 41,516
  • 7
  • 68
  • 87
0

If the fork is supposed to follow the footsteps of the forkee, better keep the fork in a branch in the master repository. Otherwise cherry-picking upstream changes and such will become unnecessarily hard.

Consider the benefits/costs of the forking repositories. Keeping all together just means dragging along the differences (presumably small?).

With gitolite you can control access to the branches if needed.

vonbrand
  • 11,412
  • 8
  • 32
  • 52
  • The fork is going to be a white label version of the product. They will change a bunch of fronted code for branding and look, but the backend code will be pretty similar. I can do git cherry-pick individual commits but this will be kind of a pain. Is there a way I can merge feature branches? – Chris Muench Apr 07 '13 at 00:01
  • If they are in the same repo, sure. If they are in another accessible repo, it is harder (you can set up to just fetch selected branches). If the remote isn't accessible, it will be extremely hard. – vonbrand Apr 07 '13 at 00:35
0

Assuming your branded code can all reside "cleanly" within the views/ directory I suggest breaking views out into its own git repo and nesting it within your main project. See here

You then have the option to either

  1. Use git branches in a single views repo for your forks, or
  2. Use separate views repos for each brand.

I'd prefer 1. since I'd anticipate parts of the views might need to be shared by either folding them back into white label, or cherry picking them from white label onto a brand.


Possible Project Working Layout

White Label Project layout;

- app_whitelabel/  <<-- clone of "app" repo on default branch
  + config/
  + controllers/
  + errors/
  + views/         <<-- nested clone of "views" repo on branch "brand1"

Brand 1 Project layout;

- app_brand1/     <<-- clone of "app" repo on default branch
  + config/
  + controllers/
  + errors/
  + views/         <<-- nested clone of "views" repo on branch "brand1"

Brand [n] Project layout;

- app_brand2/      <<-- clone of "app" repo on default branch
  + config/
  + controllers/
  + errors/
  + views/         <<-- nested clone of "views" repo on branch "brand[n]"

Pros

  • You don't need to cherry pick to keep the shared code base up to date - just pull.
  • Pulls of "app" will not affect "views".
  • Force you to keep to a clean mvc model - not a bad thing :)

Cons

  • You / others need to be aware of a more complex project layout.
  • Force you to keep to a clean mvc model - not always an easy thing :)
Community
  • 1
  • 1
mounds
  • 1,303
  • 12
  • 11
0

Assuming you have control over both repositories, the solution is simple.

Maintain branches for each feature.

Maintain a feature release branch.

When features are complete, merge the feature branch to the release branch and tag it.

If the feature needs a bug fix, fix it in the feature branch, and then remerge and re-tag it with a new version.

Your feature release branch is where you can cherry-pick updated features or bug fixes collectively. You can easily identify what version of the feature you have by the tag.

You can also easily look at the commit history on the feature release branch to see if there have been any updates.

Aside from these branches, I maintain a version release branch. Anything publicly released is QAd then committed to the version release branch.

Everyone's local working repositories can have as many commits as they want or need without restriction.

The master repos have clearly deliniated branches with clearly segmented commits that continually get merged into feature release and version release.

Any forks are easy to update by following either the feature release branches or the version release branch. Any time they want, the forked repos can grab what is appropriate.

I drew a crude picture

The yellow branch is the tagged feature release branch and the green is the version release branch. Forks can freely pull from either of those branches and know exactly what they are getting with cherry picks. Working Feature branches are all based on the release branch unless they are inter-dependent. Bug fixes are handled separately from release.

And like I said... all developers have their own working repos and can freely commit to those.

Steve Kallestad
  • 3,484
  • 2
  • 23
  • 31