17

Some Background

I have been using Git for a while now. The projects that I have been working on have not been too complicated in regards to branches/tags.

I have decided to use git-svn at work. The SVN repository has many different branches. A lot of these branches are customer customized versions of the trunk.

The Problem

I often work on problems for different customers at different the same time. So I switch back and forth between branches all the time. The problem is that to test the products I have to rebuild the project each time I switch between branches. A build takes > 2 hours (from scratch):(

I am assuming that there is a way to stash the build files in branch customer_a and then checkout customer_b, modify, build, test, commit. Then stash the build files and checkout customer_a again and pop the customer_a stash to get back to where I was.

This only works if the build files are tracked (i.e. added or committed). I do not want to track the build files and I definitely do not want to check them in. Is there a way to stash (or do something similar) for non-tracked files? Or a common practice that people use to achieve the same type of thing?

Note that the way our project gets built each library (of which there are thousands) gets builds the files local to the library folder i.e. they are not moved to a build folder at the root of the project. All the built files are spread out all over the place.

Update...

So based on some of the comments I think I need to give an example of my problem

Here is my folder structure.

branch1/
      src/
         component1/
                    c1.c
         component2/
                    c2.c
      libsrc/
          library1/
                    lib_1.c
          library2/
                    lib_2.c

branch2/
      src/
         component1/
                    c1.c
         component2/
                    c2.c
      libsrc/
          library1/
                    lib_1.c
          library2/
                    lib_2.c

So the problem is that branch1 and branch2 have the same ancestry but have diverged quite a bit. So if I check out branch1 and build it I will get binaries (e.g. lib_1.o) that I link against in my Makefile to build the final component binaries.

If I then checkout branch2 make a change to c1.c and run make it tries to link to the binaries that were created by branch1 (lib_1.o), since they still exist in the directories as built in the previous branch. To avoid this I have to do a clean build each time I switch branches (which takes hours).

Will
  • 8,102
  • 5
  • 30
  • 32
  • 2
    This isn't a version control issue, it's a build engineering issue. You'll need to be able to direct your build artifacts (object files, library archives, executables) to separate subtrees, one for each customer/task you're working on. – Phil Miller May 14 '10 at 14:58
  • @Novelocrat I somewhat agree. I too would like to have the build file is a build folder somewhere. However my colleagues use SVN and what I am asking here is possible with SVN since every branch has its own file structure on the local machine. So this is also an SCM issue too (since it is possible in SVN but not Git). – Will May 14 '10 at 15:51
  • 1
    If people are checking out multiple branches from Subversion, then there's no reason you can't just use multiple working trees in Git, each with a different branch checked out. The effect is exactly the same, except that Git will share the metadata and thus use less disk space. – Phil Miller May 15 '10 at 17:13
  • The effect is only the same for tracked files (as far as I can see). It does not protect the untracked files if I switch branches. I added more info to the question above to give an example of my problem. – Will May 17 '10 at 03:01

5 Answers5

7

Okay

So this question has been unanswered for a while now and I just been trying different solutions locally.

The best one I came up with is to use pre amd post checkoout hooks.

Here is what I have done

  1. Create a .binaries folder at the top level of your repository and add it to the .gitignore file.

  2. Add the file formats of the binaries to your .gitignore file also.

  3. write a script in your favorite scripting language to find all files of said format that moves them to the .binaries/<BRANCH>/ folder under the same path structure e.g. src/library1/lib1.o should be MOVED to .binaries/<BRANCH>/src/library1/lib1.o - this should be called by pre-checkout

  4. Write a script to move files from the .binaries folder into the current branch e.g. .binaries/<BRANCH>/src/library1/lib1.o should be MOVED to src/library1/lib1.o - this should be called by post-checkout

Now switching between branches will revert to the binaries that were built during for that branch only and you will have a clean checkout when creating a new branch.

Will
  • 8,102
  • 5
  • 30
  • 32
  • This is excellent, thanks a lot! I wonder if you have an idea for a similar situation with more than one developer though? put the .binaries on a shared network folder maybe? And I think that VonC is right about this needing to work for versions and not just branches... – Benjol Jul 08 '10 at 05:37
  • Yes, this could be carried over for versions too. You just have to decide what you want to do and use the hooks appropriately. You could probably create a hook that will build and deploy to the shared folder when a new version is created. – Will Jul 08 '10 at 21:58
2

Have you thought about worktrees?

$ git worktree add ../branch2 branch2

This will create a working tree checkout out to branch2

$ cd ../branch2
$ git branch
* branch2

You only have 1 local repo, but 2 different working areas, one for master and the other for branch2.

That way you can keep the object files separate as well.

Alan
  • 21
  • 1
1

Perhaps I'm missing something obvious, but when switching branches, Git won't touch untracked or ignored files, so if you build a product in one branch and then switch to another branch, the built products should remain.

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • 1
    Exactly, but the built files are different since the source is different. So when I switch I want what was built on that branch to be present not what was built on the prior branch. – Will May 14 '10 at 15:46
0

The problem is that you need to get back the right binaries:

  • not only need for the right branch,
  • but also for the right version

The last point is not overly important if you keep developing the latest versions of your 2 branches (and accept to rebuilt everything if you checkout an old tag and branch from there).
But still, if after a build you automatically publish those '.o' files into a repository made for managing binaries, that would solve your problem neatly.
A local Nexus repo for instance would be appropriate.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Related to this: http://stackoverflow.com/questions/2888299/is-there-any-disadvantage-to-putting-api-code-into-a-jar-along-with-the-classes/2888312#2888312 (for the maven/nexus aspect) – VonC May 28 '10 at 21:00
0

I usually solve these kind of problems by creating 2 clones of the repo to 2 separate folders (called customer_a and customer_b) and checkout branch1 in one folder and branch2 in the other folder.

Magnus
  • 9
  • 1