1

I'm developing an App for Windows Phone, using SDK version 7.1 (for WP7) and hosting it in a git repo. In order to make it available on Windows Phone 8 devices with higher resolutions, I created a branch WP8 where I converted the Visual Studio project and made some necessary code adjustments.

Now that I continue developing on master, I would like to update functionality-related changes to the WP8 branch. My first thought is to merge those branches, but I fear two possible problems:

  1. When using merge, one branch will disappear. (Not true)
  2. Firmware-related changes (WP7 → WP8) might be overridden.

Is there a proper way in git to develop for several different (but similar) target SDKs that depend on a big amount of identical code?

Cedric Reichenbach
  • 8,970
  • 6
  • 54
  • 89
  • Merge doesn't make a branch disappear. It creates a new commit on the current branch that has the current branch as the first parent, and the merged in branch as the second parent. The new commit is the content of both merged, plus any conflict resolutions you had to make to complete the merge. The branch that gets merged in has no knowledge of the merge, but continues to exist, and can still be checked out and committed against, and this is commonly done. – Gary Fixler May 04 '13 at 09:55
  • Oh I must have messed that up in my head... – Cedric Reichenbach May 04 '13 at 09:56

3 Answers3

1

When using merge, one branch will disappear.

No, no branch will disappear

Firmware-related changes (WP7WP8) might be overridden

First, try rather to rebase WP8 on top of master.
That is, try to apply WP8 on top of master (see merge vs. rebase).
As Gary Fixler comments below, this makes sense for branches with a short history (otherwise, re-applying very old commits on top of recent work can be troublesome, and the history wouldn't make sense).


I only bring up rebase, because it is considered bad practice to merge master to any other branch (this is called "back merge", and makes Adam Dymitruk angry;)).

You should use Feature branches, which you can then merge to master, and to WP8 branch.
That takes advantage of the ease of branching offered by git, and leave master with only a stable state of the code: any further evolution to master should be done in a feature branch (and then merged to master), instead of being done in master (resulting in "back merge" from master to another branch, which is bad practice)

See more on Adam's article "Branch Per Feature".


Regarding configuration files, you can also store the values in separates files, and use template file to build the right config file with the right values, depending on the branch you are.
See "What's the easiest way to deal with project configuration files?".

That way, you want have any merge issue for those files with different content in different branches, because their values are stored in different files.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Wouldn't rebase overwrite things exactly like merge? I thought the difference was that rebase copies the individual branch commits to master, while merge creates one commit containing all changes from the branch. – Andomar May 04 '13 at 09:40
  • @Andomar it is a better practice to reapply one's work in progress on top of master instead of merging (http://stackoverflow.com/questions/804115/git-rebase-vs-git-merge/804178#804178). That is why I suggest content filter driver for config files (see my edited answer). – VonC May 04 '13 at 09:42
  • @Andomar - No, rebase doesn't overwrite anything. It replays commit changes at a new location, essentially disconnecting a branch and reconnecting it elsewhere. The problem to watch out for with this is that you end up ruining context in your history. You commit on common to create A, rebase WP7 on top, refactor in common to create B, rebase WP7 on top - now the commit that was on common's A makes no sense on top of the refactored B. I have 500+ commits in a repo with this problem. I learned it the hard way. – Gary Fixler May 04 '13 at 09:43
  • In short, I'll have to do the rebase everytime I want to update changes from `master` to `WP8`, then maybe resolve merge problems, correct? – Cedric Reichenbach May 04 '13 at 10:06
  • @CedricReichenbach this will not resolve all merge problem (especially ones from changes *both* on master and WP8, but it will do those merges in the right order (`WP8` on top of `master`). For config files, I recommend content filter driver. – VonC May 04 '13 at 10:32
  • 1
    I'll say it again. Rebasing long-lived branches destroys any meaning in their history. It really only makes sense for recent, or extremely stable things. People doing this aren't thinking. They're seeing that the latest commit on the rebased branch makes sense, but the further back on that branch you go, the less sense it makes, and the older commits become increasingly pointless. – Gary Fixler May 04 '13 at 11:11
  • Well, I don't like the new tree resulting from a rebase. Some history information might get lost due to wrong (manual) merging, right? – Cedric Reichenbach May 05 '13 at 10:17
  • I'm not quite sure I follow. Merges are always manual, and they don't lose history. It's possible to lose something in the merge commit itself if wants you to resolve conflicts and you wipe out a bunch of things before finally committing the merge, but the historical inputs won't change. – Gary Fixler May 05 '13 at 11:28
  • @CedricReichenbach any merge can result, if done incorrectly, into some kind of issue. My point in suggesting rebase is that you should never merge from master to a branch. See my edited answer. – VonC May 05 '13 at 11:39
  • Well, since I already continued developing on master, I'm going to "backmerge" now from `master` to `WP8`. For the future, I will consider using feature branches. Thx to all of you. – Cedric Reichenbach May 05 '13 at 16:01
1

You can get away with this with branches or folders, but it's a prime candidate IMO for submodules. I use them for such things. Here's an example set of 3 repos:

common/ (bare repo of common files)
    .git/

wp7/ (regular repo of wp7 specifics)
    .git/
    common/ (submodule)

wp8/ (same as wp7, but for wp8)
    .git/
    common/ (submodule)

To make the common one you would just take a regular repo and git clone --bare repo optional_bare_repo_name. If you don't give it a name, it'll clone common into a folder called common.git, which is the bare version. Now you can from within either wp repo do git subdmodule add path/to/common optional_folder_name (it uses the repo folder name if you don't specify one). This effectively clones the common repo into a folder inside each wp repo. These can also be branches of a single repo; you'd just do the submodule add while on each branch.

Submodules are slightly more maintenance than branches, but they do something branches can't. They give you a parallel line of development inside your repo. When you make a change in the common repo inside either wp repo, you commit it there, and you can push it back to the external, bare version of common, and pull it down in the other wp repo's common repo. It's just a regular repo, but its clones live inside the wp repos. In your wp repos you would tell it which version you want right now by first checking out the correct commit inside the common repo, then outside in the wp repo doing git add common and git commit -m'Update common for feature X'. This creates a commit in the wp repo that just stores the hash of the commit in the common submodule.

When you checkout this commit in the wp repo later, it'll checkout the wp code, and also the appropriate commit in the common repo. Basically you're able to track which version of the common repo to be at at particular times. This is nice for a couple of reasons. For one, you don't have to get latest in common in a particular wp repo if you don't want or need it. It also means you can actually checkout an older commit in either common repo, add it, and commit it in that wp repo, and then work against that older one for as long as you need to. It is a little more work, though, and you have to remember to work in the wp and common repos together. I do it every day, but I've heard many people say it's too much bother.

You can also add and commit a particular version of common along with files in a wp repo, so for example you could go in and refactor things in common, hop out and fix changes against that refactoring in wp7, then add common and the wp7 changes together in wp7 and commit them to track both changes. Now if you roll back 1 commit the common repo will also roll back to before the refactoring, so you can have properly functioning code at every commit.

Gary Fixler
  • 5,632
  • 2
  • 23
  • 39
  • Looks cleaner than rebasing, but might be an overkill for my project of ~50 classes. The changes for WP8 are rather small, but scattered all over my project... Also, I'm a bit afraid of changing the whole project setup. – Cedric Reichenbach May 05 '13 at 10:15
0

Firmware-related changes (WP7 → WP8) might be overridden.

Branches are meant to be versions of the same thing in different stages of development. If you merge a branch, git will try to move all changes from one to the other. There is no easy way to move only architecture-independent changes from one branch to another.

The best situation is when you can get one branch to build for both. Share the files that can be shared, and store the project specific things in separate directories, like arch/wp7 and arch/wp8.

Andomar
  • 232,371
  • 49
  • 380
  • 404
  • Well, the problem here is that it's not that easy to distinguish shared from non-shared parts, since they might even be in the same files. For instance I might have changed an XAML page (UI design) for higher resolutions in `WP8`, but in `master` I added new features. – Cedric Reichenbach May 04 '13 at 09:55