khebbie
khebbie

Reputation: 2503

Structure in git with multiple websites

I have a website that i keep in git. It is a asp.net webforms website (but that is probably unimportant to this question).

The website is used by our customer for 2 (in the future 4) websites. Most of the functionality is shared. But a few things like web.config and a folder with css is unique for each website.

Here is a simplified version of the code

|--BackOffice
|  \--UI
|--BackOffice.UI
|  \--WebControls
|--BackOfficeTests
|--Deployment
|  \--db
|--BusinessLogicLayer
|  |--bin
|  |--obj
|  \--Properties
|--scripts
|--Website
|  |--admin
|  |--App_Browsers
|  |--App_Code
|  |--App_Data
|  |--Styles
|  |--web.config

What would a good structure for this be in Git?

For instance the BackOffice code would be completely shared. The Website would be shared except for the Styles folder and the web.config file.

Do you have a good suggestion for a structure that does not make merging and branching too long haired?

I have tried to make a structure like so:

Master
|--Site1
|--Site2

But I foresee too much cherrypicking when moving code from one branch to another Would a submodule be ok or would it complicate things?

EDIT: My really big problem is that I want to deploy directly from my git repo. And if I leave in these directories / files they will be merged during merge, unless i do some complicated stuff (then I cant let everybody on the team do this). Or I will have to ignore these files and get them from somewhere else...

Upvotes: 13

Views: 1389

Answers (3)

abhi.gupta200297
abhi.gupta200297

Reputation: 891

Assuming that your master branch contains your entire project:

|--BackOffice
|  \--UI
|--BackOffice.UI
|  \--WebControls
|--BackOfficeTests
|--Deployment
|  \--db
|--BusinessLogicLayer
|  |--bin
|  |--obj
|  \--Properties
|--scripts
|--Website
|  |--admin
|  |--App_Browsers
|  |--App_Code
|  |--App_Data
|  |--Styles
|  |--web.config

Now, any change which is common to all websites, gets committed to this branch.

Make separate branches for various sites. Example:

From the master branch,

git checkout -b site1
git checkout -b site2
git checkout -b site3
git checkout -b site4

now whenever you want to change any site specific files, i.e. Styles folder or web.config, do it in these branches.

Now comes the deployment part. Suppose you want to deploy site1, create a temporary branch on local system based off master, merge site1 branch into it and deploy it. Finally delete the temp branch.

git checkout -b temp
git merge site1

tar or zip your code and deploy it. After that,

git checkout master
git branch -D temp

You can even make a small shell script that does that if you do not want to expose the way deployment is done. Lets call this script deploy.sh For example:

#!/bin/bash

if [ ! $1 ]; then
        echo "Please pass in the name of the site you want to deploy."
        exit 1
fi

#Check if we are on master branch
git status | grep "On branch master"
if [ $? -ne 0 ]; then
        echo "You are not on master. Please execute 'git checkout master'"
        exit 1
fi

#Check if the entered site for deployment actually exists
git branch | grep $1 || { echo "No branch $1 exists for deployment."; exit 1; }

#Update from remote
git checkout -b temp
git merge $1
tar -cvf deploy-$1.tar ./deploy.sh *
[ $? -ne 0 ] && echo "Some problem archiving the files..." && exit 1
git checkout master
git branch -D temp

echo "Please use deploy-$1.tar file to deploy the site. Thanks."

exit 0

Now when you say ./deploy.sh site2, this script will do all dirty work behind the scenes and give you a tar file which you can deploy on production server.

I hope this is helpful...

Upvotes: 11

jthill
jthill

Reputation: 60255

I might make separate "Site" and "Common" directories, with "Common" containing symlinks at strategic points and one or both a submodule, like so:

 Project
 |==.git
 |--Site
 |  |--.git
 |  \--Website
 |     |--Styles
 |     \--web.config
 \--Common
    |--.git
    |--BackOffice
    |  \--UI
    |--BackOffice.UI
    |  \--WebControls
    |--BackOfficeTests
    |--Deployment
    |  \--db
    |--BusinessLogicLayer
    |  |--bin
    |  |--obj
    |  \--Properties
    |--scripts
    \--Website
       |--admin
       |--App_Browsers
       |--App_Code
       |--App_Data
       |--Styles -> ../../Site/Website/Styles
       \--web.config -> ../../Site/Website/web.config

That's not the only layout that would serve -- for instance, if it should be easy to have different sites pick and choose what gets tweaked you could preserve your current layout, adding the "Common" subproject and symlinking anything you use from it unchanged, like so:

 Site
 |==.git
 |--BackOffice -> Common/BackOffice
 |--BackOffice.UI -> Common/BackOffice.UI
 |--BackOfficeTests -> Common/BackOfficeTests
 |  [...]
 |--Website
 |  |--admin -> ../Common/Website/admin
 |  |--App_Browsers -> ../Common/Website/App_Browsers
 |  [...]
 |  |--Styles
 |  \--web.config
 \--Common
    |--.git
    |--BackOffice
    |  \--UI
    |--BackOffice.UI
    |  \--WebControls
    |--BackOfficeTests
    |--Deployment
    |  \--db
    |--BusinessLogicLayer
    |  |--bin
    |  |--obj
    |  \--Properties
    |--scripts
    \--Website
       |--admin
       |--App_Browsers
       |--App_Code
       |--App_Data
       |--Styles.example
       \--web.config.example

The more I look at it the more I like that last one better.

Upvotes: 2

VonC
VonC

Reputation: 1323573

A submodule is a good solution for the shared BackOffice code, with each site acting as a parent repo.

But that doesn't address the config files.

For those, one possibility is a content filter, but that would involve storing and pushing the values of the variable for the different clients.

It is best to keep those config files in the parent repo in client-specific branches.

Upvotes: 6

Related Questions