views:

261

answers:

4

I'm working on a project that is using code from an OpenSource project. One of the requirements is to push as much code back to upstream as possible.

The remote project is using Subversion (not very well).

My current setup looks like this:

[Remote SVN] (git svn fetch)-> [My public Git] <-(push/pull)-> [My dev. Git]
                                    VV
                                  (pull)
                                    VV
                               [Testing grid]

EDIT 11.7. - reformulated the question

My issue is the coexistence of my local public repo and the svn upstream.

I have to provide 3 public branches:

  • conservative stable
  • experimental stable
  • development

These branches are now linear (development becomes experimental stable and experimental becomes conservative), but the target is a standard 3 headed approach with merging. Due to their public nature I can't rebase these branches.

Now completely orthogonal to this I'm trying to somehow make sending patches to upstream easier. Digging them out from my branches is slow and prone to errors.

My typical current workflow is:

  • implement some feature on top development branch
  • test & fix feature
  • test & fix other features broken by this new feature (actually happens a lot)
  • determine if this is something that could be accepted in upstream or not (30:60 yes:no)
  • do something about it (I usually just write a new TODO)

Another problem with the upstream is that they accept patches into different branches (my public branches are based on their stable branch). Once the patches reach stable branch I can simply forget that they exist, but until that happens I need to still keep them locally.

+2  A: 

I'm not really sure I have understood your problem, but I think you might be looking for git stash.

Fififox
Thanks this will help a little, but its not a solution for the whole problem.
Let_Me_Be
+1  A: 

I'm not sure how highly coupled your features are to the upstream code, but you could possibly branch a "core" of the upstream that you maintain separate from your feature additions. This only really works if you can partition the code base.

Adam Shiemke
Well, I do partition the code. I maintain one part of the code completely disjointed from the base because the amount of patches against this code makes upstream bugfixes irrelevant.The problem is the rest of the code.
Let_Me_Be
A: 

You really haven't made it clear what you want to do. In reference to your statement that "(maintaining separate branch for each feature is therefore non-trivial)", I can only wonder why you think it should be trivial. Two patches that are mutually dependent on each other should either be a single patch, or at least on a single branch. A patch B that depends on A (but not the other way) should be either on the branch with A, or on a branch with a parent commit on the A branch.

Now, if you want to maintain a "clear overview" of where your patches are upstream, that's going to come down to keeping a local copy of all the upstream branches. I don't see where the problem is with that. You really need to be precise if you want a more precise answer.


Ok, this is easier to tackle now.

You have two problems.

(1) is getting fork commits that are never going upstream off of your main development branch and into a fork branch once you realize that you're never sending them back.

Make a fork branch. Once you realize a feature is not going back, pull from the branch holding the fork feature. Then git revert the fork feature to apply a patch that undoes the feature from local-*. Repeat as needed.

(2) Is that you're worrying about what happens to the patch upstream.

You really shouldn't have to track whether they've applied your patch to remote-stable (henceforth r-stable) yet. You won't lose a patch in L-stable if you pull from r-stable and they haven't applied the patch yet. The only possible problem is that there will be merge conflicts on code from the patch, but you are not going to be able to get around that. Once they apply the patch, it will either look exactly like the way that you resolved the merge conflicts (in which case you will get no diff from that when you pull the patch from R-stable), or they will merge in a different way, and you will get a merge conflict and be given an opportuntity to decide to keep their way or your way. Just remember that if you want to keep your way, you will be forking from r-stable. One option is to move "your way" onto fork and keep their way on local-*.

masonk
I have reformulated the question once again. Hopefully it will be clear now.
Let_Me_Be
+4  A: 

The git svn documentation recommends the following workflow when dealing with Subversion branches:

# Clone a repo (like git clone):
git svn clone http://svn.example.com/project -T trunk -b branches -t tags

# Append svn:ignore settings to the default git exclude file:
git svn show-ignore >> .git/info/exclude

# View all branches and tags you have cloned:
git branch -r

# Create a new branch in SVN
git svn branch waldo

# Reset your master to waldo:
git reset --hard remotes/waldo

# local changes
git add ...
git commit ...

# pull changes on current branch
git svn rebase

# send changes to Subversion
git svn dcommit

# check for new branches
git svn fetch

The workflow above is for an uninterrupted change on a single Subversion branch to which you have the luxury of a commit bit, but juggling multiple active Subversion and git branches is a little tricky.

To track the Subversion repository's waldo branch, start off with

git checkout -b waldo-svn remotes/waldo

The -svn suffix is to avoid warnings of the form

warning: refname 'waldo' is ambiguous.

and also to remind you that this git branch is for tracking the Subversion branch. Always keep changes to these branches linear!

To update waldo-svn, run

git svn rebase

This will fetch the changes from Subversion and rebase any local changes on top of those. It's also smart enough to recognize when one of your local changes has been accepted verbatim upstream: it will be replaced by the Subversion commit and have a line beginning with git-svn-id: ... in its commit message.

When the upstream maintainers alter the contents and structure of your patches (e.g., modifying the code, splitting a patch into multiple Subversion commits, or combining multiple patches into a single commit) is when life gets fun resolving conflicts and trying to untangle the mess.

For full generality, keep your -svn branches in git clean (no changes) and create issue branches off the -svn branches. To send a patch, use

git diff waldo-svn waldo-fix-frobnicator

Then when you git svn rebase to catch up with the Subversion repo, you'll need to review the log and decide on the respective dispositions of your issue branches, sort of a GTD for git.

Greg Bacon
+1 for "keep your svn branches clean". They're essentially not *your* svn branches, they're upstream branches, and therefore they must persist in your local Git repository as separate branches as well. If that holds, you can noq just work with them the same way as with Git upstream branches.
Pavel Shved
Thx for such long answer gbacon. But that's not the part I'm having trouble with. I have reformulated the question, hopefully it will be more clear now.
Let_Me_Be