views:

99

answers:

7

Not sure how to ask this. I want to build upon a mature and actively updated open source project, using it as a foundation to tweak and learn from. I'd like to be able to add code to my local source, but be able to update the core source as it improves while retaining my add ons.

The goal is to keep the foundation always up to date, and adding my code to the updated build (instead of being overwritten with changes, as I'd imagine would happen if I just edited the source as is).

Is there a way to 'patch' my code onto the updated project code, so when the core source is updated with svn my changes would remain independent of the foundation? I'm sure there's a simple way to do it but I'm new to programming/svn/version control and haven't a clue what or where to look.

+1  A: 

You could install a source control system locally.

Populate it with a copy of the source from the project server.

Then make your changes on top of this.

When the reference project is updated get a new copy and then merge the edits into your modified code. Exactly how you do this will depend on the source control system you choose.

However, if the project's source control supports branching (which it should) you could create a branch on their server and merge between them, which might be a lot easier.

ChrisF
+1  A: 

The closest thing I can think of would be to start with the open source code in the trunk of your SVN repository, then branch it and make your changes in the branch. When the OSS code is updated, you would update the trunk with that then do a merge up to your branch from the trunk. At that point you would resolve any conflicts that might have occurred between what they changed and you changed, essentially "patching in" their changes to your code.

Eric Petroelje
A: 

Use a different, modern version control system. A good candidate would be git which is used for Linux kernel development all over the world. branching and merging comes much more natural than with svn.

A: 

The way to do this in SVN is to check out a working copy of the code, make your changes to the working copy, and then when you svn update, it will grab the most recent version of the code from the repository while still keeping your local changes. It will notify you if there are any conflicts.

I think the answers that refer to branching and merging and distributed version control systems (viz. Mercurial, Git) are more complex than what you need.

Michael Hackner
A: 

It looks that your usecase exactly match the Mercurial Queue mechanism. I would say that even for a complete newbie to mercurial it's damn easy to set up and maintain.

gizmo
MQ's look interesting: when I finally get round to learning Mercurial (I'm a git user) I'll be sure to give them a look.
jkp
A: 

While personally I would do this through mercurial, you might look into the quilt tool.

Also check out this overview.

Dave Bacher
+1  A: 

What you are looking for are called SVN Vendor Branches.

Basically, you keep a separate branch in your repository for baseline versions of the project only and then merge changes between versions of the project into your trunk.

For example:

svn import ./projectdir svn://repourl/project/branches/vendor/current/ -m 'Home for current core version of source code'
svn copy svn://repourl/project/branches/vendor/current/ svn://repourl/project/branches/vendor/1.0.0/ -m '1.0.0 tag of core source code'
svn copy svn://repourl/project/branches/vendor/current/ svn://repourl/project/trunk/ -m 'Initial trunk commit of 1.0.0'

What we have now are:

  • A "current" branch that has the most up to date version of the core code you are using.
  • A "1.0.0" tag of the core code (you should not commit any new changes to this tag)
  • Your trunk, which now has 1.0.0 of the core code.

Now, let's say you've been working on the project for a few months and have made a bunch of updates to the project in your trunk. Version 1.1.0 of the core comes out, and you want to take advantage of some new features without losing your existing work.

You can use your vendor branches for this.

svn co svn://repourl/project/branches/vendor/current/ ./project

* extract version 1.1.0 on top of the working copy *

svn status | grep -E '^?' | xargs svn add # add all new files/directories to the project
svn status | grep -E '^!' | xargs rm -rf  # remove all files/directories from the project that have been deleted
svn commit -m 'Version 1.1.0 of the core code'
svn copy svn://repourl/project/branches/vendor/current/ svn://repourl/project/branches/vendor/1.1.0 -m 'Tag for 1.1.0'
rm -rf ./project

Now, what do we have? We have:

  • A tag for version 1.0.0 of the project
  • A tag for version 1.1.0 of the project
  • A trunk with a modified version of the project that we want to bring up to date.

So, what do we need to do? A simple merge.

svn co svn://repourl/project/trunk ./project
svn merge svn://repourl/branches/vendor/1.0.0 svn://repourl/branches/vendor/1.1.0 ./project

What you are telling SVN to do in the line above is essentially: "Find the differences between version 1.0.0 of the project and 1.1.0 of the project, then merge those differences into my modified version of the project."

For most files, the merge will be smooth and painless. For others that both you and the community have modified at the same time, SVN will complain about conflicts. Unless you've made really huge changes, these conflicts should not be difficult to merge. I recommend selecting "p" for "Postpone conflict resolution" and resolving them using TortoiseSVN. It's much, much easier to do that way.

Once your conflicts are all resolved, go ahead and test the application. If everything is working as expected, go ahead and svn commit your working copy.

... and you're done!

Some more reference material on the subject:

Mike
+1 for being so exhaustive
Noufal Ibrahim