Sharing Models between two Rails Projects - using git submodules? - ruby-on-rails

I have a Rails website which has been divided into two separate projects - the public site, and the administration site.
As both sites are using the same database the models are shared between the applications (actually right now they are duplicated). The problem I have here is that when an update to the models occurs in the public project I need to copy the changes over into the admin project.
I've had a look around SO and noticed that there was a question which had answers suggesting using svn:external or git submodule, but I'm not entirely sure how to do this.
Essentially my aim is to be able to make the changes in one place only, commit those changes to git and then be able to pull the changes in the other project when I need to update that as well.

You need to:
commit the submodule in one place
commit the main project (said the public site)
go to the same submodule in the other main project (the admin site)
pulling the latest content (changing the HEAD of that submodule)
going one directory up in the main (admin) project
commit (to record that you now reference a different version of the submodule)
See also true nature of submodules.

Do not use submodules. They are ugly, hard to understand and to maintain. Much better is to use subtrees.
Git subtree is a part of GIT since 1.7.11 and I wrote an article about sharing code between Rails applications: http://igor-alexandrov.github.com/blog/2013/03/28/using-git-subtree-to-share-code-between-rails-applications/
In short: yes git-subtree works and works great!

Related

Git submodule vs Git subtree vs dependency manager CocoaPods

I have two apps/projects - one for customers and one for workers. Both projects have the same back-end API related code, the same business-level objects, the same custom GUI controls and some functionality. I want to replace the identical code with the shared one. For example to move this code to a separate repo.
Since both projects are under development everything (including shared code) will be changed very often. Shared code will be usually updated as a part of one of these two projects.
What is the best way to share the code between two projects if I need an easy way to frequently update it?
My ideal use case will be the following:
I change the customer project (customer and shared code).
I commit and push new changes to the customer repo and to the shared code repo.
I open worker project, do pull for the shared code and then update worker code if it needs to reflect shared code changes.
P.S. Qestions Differences between git submodule and subtree and GIT Nested repositories: Composer vs. SubModules vs. Subtree vs.? have very good answers but it is still not clear what should I choose if I need an easy way to frequently update shared code.
I would use a git submodule personally, it's a very good link to a shared codebase that is itself a git repository that can be managed separately without being tracked in your other projects.
You can use git submodule foreach git pull origin master on both the client and worker side to pull in changes when the shared library is updated.

Git repository structure for two iOS apps where one app derives heavily from the other

The scenario is as follows. I am working at a company that started out with one iOS application. Now, the company is interested in creating a second iOS application, that shares much of the same code base. The original application was not written with the intention of being reusable, as it was not known at the time that a second similar application would be created. In future, there may be even more similar applications that build on the existing code base.
We are trying to determine the "best" option with respect to how we maintain the source code going forward. So some of the options we're contemplating include single repository with shared library, one repository for shared library and one repository that contains all of the iOS applications, one repository for shared library and one repository per iOS application, etc etc. There's also the question of whether to use git submodules or not if using multiple repositories etcetera.
Currently, the two applications + library are all in one git repository. One of the advantages of this is that a developer can checkout a commit of the single repository and expect the product to build, without having to worry about updating multiple repositories. Basically, the developer doesn't have to be concerned with multiple repositories needing to move in lockstep with one another or requiring some specific combination of repositories commits for a build to work. The developer also doesn't have to worry about cases where another developer may have remembered to commit one repository, but not the other.
Here are some more things I've considered:
Submodules
I've used submodules before, but am no expert. My understanding is that the "super" repository containing a submodule also stores a reference to a specific commit of the submodule. This partly deals with ensuring that multiple repositories (i.e. application + library) would move in lockstep, though I'm guessing there are still issues with needing to manually pull changes from the sub module. Also, issues with a submodule commit not being available to pull if a developer happens to forget to push its changes and it is referred to by the super repository.
One nice aspect of submodules is that it creates a stronger semantic separation between the library and the applications which happen to use the library. Whether this is useful in practice, I'm not sure.
Single repository
As previously stated, this is what we're currently doing. Two applications + shared library code all in one repository. The greatest concern has been around the relatively non-existent ability to isolate changes between project one and two and the library. E.g. someone makes changes to both some library code and some application code in a single commit. Then, another developer just wants the changes in the library code.
One nice aspect of single repository is that everything moves in lockstep - nobody has to worry about keeping multiple repository versions matched. If using XCode workspaces, refactorings are even possible across the two applications.
Branching
Another option is to use some kind of branching model, either in a single or multiple repositories, to manage the code.
Ultimately, we're just trying to figure out a good model going forward for managing two or more iOS applications plus shared library code. Whether this be achieved via multiple repositories, submodules, branching models, or something else. Any general suggestions on the pros and cons of the various options?
Use submodules. You don't need to be an expert because they are really easy to use. Especially when combined with a GUI like SourceTree. I had the exact same scenario as you and that is what I did. SourceTree will even warn you if you are trying to commit a repo that has uncommited changes in a submodule.
A single repository is ludicrous. That would mean that every time someone new wanted to download a project, they would have to download them all.
Branching is going to turn out to be too complicated with making bug fixes that apply to all relevant branches.
The structure I have for my current project is:
Project repo (For the project I am personally working on)
-Project base repo (For shared code between team members)
--Utilities repo (For code that is reusable in any project)
Cocoapods, they make managing related code between applications simple.
We had a similar base for a suite of apps and initially it was a huge pain to manage but once you get custom cocoapods running you will never look back. You should check out this for a starting guide on managing your own cocoapods.
It's free, it's powerful and you will wonder why you never used them sooner.

Master GIT repository with shared sub respoitories

I have created a basic admin system using RoR. It has very basic functionality such as users, roles, security features and a basic UI. I want to put this project into a master GIT repository.
If I want to create future projects, I'd like to use this base project as the foundation. Do I create braches?
MASTER PROJECT
MASTER PROJECT > SUB PROJECT #1
MASTER PROJECT > SUB PROJECT #2
So both sub projects are identical to the master project at this point. If I want to make a universal code change to any file within the MASTER PROJECT, how do I make that change trickle down to all sub projects. That is my FIRST QUESTION.
SECOND QUESTION:
What if I want to make a code change to a particular file on one of the sub projects?
e.g.: If I customize the layout in SUB PROJECT #2 (application.html.erb), I want that change only to affect SUB PROJECT #2. I want all sub projects to use the application.html.erb from MASTER PROJECT UNLESS it has changed (customized). It would be nice if SUB PROJECT #2 only contained the one customized file. All other missing files fallback on MASTER PROJECT.
THIRD QUESTION:
If I make a change to application.html.erb in the MASTER PROJECT, it is supposed to tickle that change down to all sub projects UNLESS one of the sub projects has a customized change to that file already. In this case, SUB PROJECT #2 does.
I'd want GIT to either:
a) Skip the update on application.html.erb on SUB PROJECT #2
OR
b) Prompt a warning to allow for some sort of merge.
Does that make sense? Is this setup possible? What would it be called? Where do i start?
Question 1:
You could use branches to track this. However, you should also consider whether what you need is simply a set of templates.
Git does not perform automatic merges by itself. You can write a script to do this, but otherwise you'll need to manually perform a git merge on each subproject branch.
Question 2:
Any branch you create will initially be identical to the original branch (master), at the time you created the branch. It will not change until you commit changes or merge in changes from the master branch. It wouldn't make sense to have this branch contain only the one customized file, so you may want to consider why you're asking for that if you want to use version control branches. The branch may only contain modifications to the one file, but nothing enforces this.
Question 3:
This is what git is designed for. When you do a git merge on the subproject branch, git will try to automatically merge the content and if it fails it will mark a conflict and allow you to manually perform a merge. You can also tell git to use another merge strategy, such as 'keep the local version', but this is a more advanced technique, and probably isn't what you want.
I recommend you start with the git-tutorial and make sure you have a good understanding of branching in git. Then, revisit this idea and make sure it still makes sense for what you're trying to acheive.
Maybe it's the right choice to put your master project into its own repository and make a new one for each project. There's git submodule which enables you to integrate other repositories in a project. YOu should try to have project specific changes only in the relating repositories, changes on the master project you can update via git submodule!

Sharing code between two or more rails apps... alternatives to git submodules?

We have two separate rails_app, foo/ and bar/ (separate for good reason). They both depend on some models, etc. in a common/ folder, currently parallel to foo and bar.
Our current svn setup uses svn:externals to share common/. This weekend we wanted to try out git. After much research, it appears that the "kosher" way to solve this is using git submodule. We got that working after separating foo,bar,common into separate repositories, but then realized all the strings attached:
Always commit the submodule before committing the parent.
Always push the submodule before pushing the parent.
Make sure that the submodule's HEAD points to a branch before committing to it. (If you're a bash user, I recommend using git-completion to put the current branch name in your prompt.)
Always run 'git submodule update' after switching branches or pulling changes.
All these gotchas complicate things further than add,commit,push. We're looking for simpler ways to share common in git. This guy seems to have success using the git subtree extension, but that deviates from standard gitand still doesn't look that simple.
Is this the best we can do given our project structure? I don't know enough about rails plugins/engines, but that seems like a possible RoR-ish way to share libraries.
Thanks in advance.
I think that the git submodule system have a great advantage over svn:externals or symbolic links (and it is also that makes them more difficult to use): the actual submodule version is stored for each superproject version. So is is quite safe to make changes in the submodule that breaks backward-compatibility: it will be possible to checkout any version of the superproject(s) with the proper submodule version, because the superproject will contain a reference to the proper submodule code. You may also maintain two branches of the submodule (v1.0.x and v2.0.x, for example) and use different branches in different projects without a problem.
So I think it is really worth to use submodules even if they are a bit complicated. Git 1.7 has some major improvements on this area, for example git status now indicates the uncommitted modifications in submodules, so you probably don't forget to commit submodules first. A good GUI may also be a help (I have a small pet project about this, see here).
If you really don't want to care about submodule versions (you never make backward-incompatibile changes in the common code) then I also suggest using symbolic links. Although committing and fetching won't be much easier than for a submodule...
I tend to prefer symbolic links to submodules.
1) Have foo, bar, and the common code (common) in 3 separate repos.
2) In directory for foo, add a symbolic link to common, where necessary.
$ cd foo
$ ln -s /path/to/common lib/common
3) Check in the link.
$ git add lib/common
$ git commit
4) Repeat for bar
This takes advantage of the fact that git respects symbolic links and stores the location of the target (as opposed to following the link.)
Ofcourse, the expectation is for you to consistently use the same target path for common. I work around this by not checking in the symlink, and adding a README.setup file in each of my projects reminding me to add the requisite symlinks upon initialization. Having a devsetup.sh that does this sort of initialization is useful here too.
IMO, this is much nicer to deal with than submodules.
A Plugin is totally the way to go, and if you end up using it on more than two projects or would be useful to the general public, probably worth the effort to make it into making it a gem.
Here is a good resource on the subject
http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-i
and more importantly ...
http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-ii
In the end you will have three git repositories one for foo, one for bar and one for the plugin.
Then in each project to keep it upto data you will be able to do
./script/plugin install --force git://github.com/path/to/plugin/repository
to keep it upto date.
Good luck!
-- jonathan
Git subtree is a part of GIT since 1.7.11 and I wrote an article about sharing code between Rails applications: http://igor-alexandrov.github.com/blog/2013/03/28/using-git-subtree-to-share-code-between-rails-applications
In short: yes git-subtree works and works great!
If you're looking at making a plugin, you should also consider making a gem. They are very similar in terms of using them, but gems tend to be easier to work with, support dependency management, and are easier to share/distribute with the community.
Ryan Bates of Railscast has a great tutorial video about making a gem that you can find here: http://railscasts.com/episodes/135-making-a-gem
You could create a repository with the common code and clone it twice. Both clones would become foo and bar. You could still develop the common code in separate branches in both projects and push that branch to the common code repository. To update the common code in the projects you would just merge the common branch into the master branches of foo and bar.
UPDATE: You can imagine this as a single repository with three branches: common, foo and bar. You would have the common code in the common branch and add the project specific code only to the foo or bar branches. Now you could clone this repository twice as foo and bar and delete one branch from both of them (branch foo from bar repository and branch bar from foo repository). Then you would delete both foo and bar from the first repository. This would become the common repository. The final result would be the same as above.
The best thing you can do is to create a plugin for your common libraries, or even a gem, that way you have a nice way to update/distribute it.

Can ASP.NET MVC Views be re-used across different projects?

This is a follow-up question to this question.
It's a nice solution to sharing common Views across many projects using source control. However I have a couple of questions, specific to Subversion I think.
Subversion Externals allows you to include a folder from a separate repository in your working copy, so you could define an "External" property on the working copy root that added a folder: [/Web/Views/Forum] for example.
What would happen if you wanted to override one of these views with a version specific to one of the dependant projects?
If you added an additional View in that folder, would SVN commit it to the shared repository?
Is the answer at this stage "wait for MVC2", as I believe it is better for these kind of scenarios?
Thanks,
GC
svn:externals are not the answer to your problem
Just to clarify: when using svn:externals, you're really adding a link to the actual external repository. Whatever you modify/add/delete and commit (given that you have commit access to the external repository) from your working copy will simply get committed to that repository. Everyone else using the same repo (as external or not) will get those changes on a subsequent update.
If you really need to be able to modify the views, you will have to work out a branching & merging scheme I'm afraid. If that is the case, make sure it's really worth the trouble.
EDIT: As an answer to the original question, I think your best bet is to wait for ASP.Net MVC 2. You may want to have a look at this series of blog posts by Eric Hexter, explaining 'Portable Areas' with mvc2 and mvccontrib

Resources