tags:

views:

45

answers:

4

Hi, I have the following problem: We have a large product which is in master branch. Also we have other branches that have only few files, the files that are specific to this branch only. Each of those branches represent a plugin to the main product. So for example when you get the main product, you receive lots of files, install them, etc. and later when you decide to get a plugin, you receive a package containing several files only and by uploading these file (and replacing the original ones) you get the plugin installed.

Let's I have payment.php in master branch (as well as many other files). And I have paypal branch which has one file only which is payment.php. Now I fix a bug in master's payment.php and want to merge this fix in paypal branch. However when I run merge, absolutely all files get added to that branch. So in the end paypal branch has all the files from master branch. Do you by chance know how this can be fixed? I want GIT to merge the files that exist in this branch only, so in the example above the paypal branch should still have one file only (payment.php) with the bug fix merged in.

A: 

This is why it's important to manage your branches well, in particular to use topic branches and to merge upwards.

You should make that fix on a topic branch, forked from a common ancestor of all branches which will need the fix, and then merge it into both master and paypal:

x - x - x - x ------------- X (master)
|\                          |
| x - x - x ---- X (paypal) |
 \              /           /
  x (bugfix) ---------------

If you have already made your bugfix, and you mistakenly made it on master instead of from the appropriate merge base, and the history on master hasn't been published, you should cherry-pick or rebase it to the right place:

# If the bugfix commit is not at the tip of master, you can rebase to get it there:
git rebase -i <commit before the bugfix> master
# rearrange the list of commits to put the bugfix at the tip, save and quit

# Now either cherry-pick or rebase the commit to the right place
# (rebase is easier if the bugfix is actually several commits)

# Cherry-pick
# make a branch and cherry-pick
git checkout -b bugfix <SHA1 of merge base>
git cherry-pick <SHA1 of bugfix>
# remove the commit from master, assuming it's still on the tip
git checkout master
git reset --hard master^

# or rebase
# make the bugfix branch (assuming it's still on the tip)
git branch bugfix master
# and remove the commit from master (assuming it's still on the tip)
git checkout master
git reset --hard master^    # or if the bugfix is composed of n commits, master~n
# rebase the bugfix branch to the right place
git rebase --onto <SHA1 of merge base> master bugfix

If the history has been published, all you can do is cherry-pick the bugfix onto the paypal branch, and remember to do it right the next time:

git checkout paypal
git cherry-pick <SHA1 of bugfix>
Jefromi
Hi, I was thinking of having the paypal branch and merging master into it from time to time. So when I need new features implemented or bugs fixed I'll be doing that in master's files and then before the release I'll be merging the changes in paypal branch (so that the paypal can have the new fixes and features). I am quite new to this stuff so please correct me if I don't see some hidden problems with this. Earlier I've been doing this work manually. So I was implementing the new feature in master and then manually copying the pieces of code to paypal branch.
Eugene
In the example above the two branches seem to be very different (all those commits after branching point) while my branches usually have one difference only (paypal functionality for example). All the rest is the same and the main work is to keep the new code modifications always go into both branches. Of course sometimes I have a fix specific for paypal branch only but this is rather rare because that code is well tested by this time.
Eugene
@Eugene: I'm really not sure what you're trying to ask in those comments. No matter what, you can always make the modifications from the right branch point, then merge them into all branches that need them. It doesn't matter how different those branches are, as long as your patch still applies...
Jefromi
+1  A: 

Why don't your other branches contain all the files that are part of the master branch? You're just making things harder on yourself by going through the trouble of removing all the other files. Especially if you later end up needing to change some other file that you already removed.

jamessan
A: 

You can do something similar to this: http://nvie.com/git-model

(I hope this works)

master will continue to be your main branch. You create a second branch off master called bugfix. You create a third branch off bugfix called plugin-foo.

In plugin-foo you delete all the files that are not needed. Now, whenever you make a change to the files that are not in the plugin branch, you do those on the master branch. All bugfixes go into the bugfix branch. You periodically merge the bugfix branch into both master and the plugin branches. Which leads to bugfixes going into both of those branches.

igorw
A: 

You're doing it wrong. You're supposed to have all the files in the branch.

It's Git's job to keep track of which files differ between the branches, not yours. That's sort of one of the points of using a VCS.

If you want to distribute just the files that differ between branches, those can easily be extracted by a script.

Christoffer Hammarström
Hi, thanks for your reply. I am testing this solution at the current moment and will most likely use it.
Eugene