Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GIT Version Control setup for multiple projects with shared code

I've used about 10 version control systems over the years. And I'm moving to Git, which before a few days ago I've never used. (Git over SSH to a "public" repo)

I'm not asking about how to use Git, but rather how to structure the repository, or if I need multiple ones or what. I have multiple projects that refer to multiple libraries. I want to version label the libraries such that I can have something like this easily maintained:

Project A, Shipped in 2012
Main Project Source, Version 1.0, Current Development version
Lib-A, Version 1.0
Lib-B, Version 2.0
Lib-C, Current Development Version

Project B, To be shipped soon, update to 1.0
Main Project Source, Version 2.0, Current Development version
Lib-A, Version 2.0, Current Development Version
Lib-B, Version 1.0
Lib-C, Current Development Version

The idea being that I can pull down into a directory everything I need to build Project A and B - with whatever requirements they may have had back then - with the ability to use the current development version, OR stay with the older version (example: Lib-B in project B is an older version and is not being updated at this time, or if it is it would be a branch.)

Originally, I was thinking of something along the lines of (In Repo):

/Src/Project A
/Src/Project B
/Src/Lib/LibA
/Src/Lib/LibB
/Src/Lib/LibC

In which case, I'd have to bring them down into a different structure than exists in the archive, or at least, bring them down into different directories, either:

/Src/ProjectA/Project A
/Src/ProjectA/LibA
/Src/ProjectA/LibB
/Src/ProjectA/LibC


/Src/ProjectB/Project B
/Src/ProjectB/LibA
/Src/ProjectB/LibB
/Src/ProjectB/LibC

or
/Src/ProjectA
/Src/ProjectB

/Src/Lib/LibA
/Src/Lib/LibB
/Src/Lib/LibC

(Sorry for the bad formatting, I tried really hard to convince this it wasn't code)

But with this structure, you would need to switch the Lib directories when you switched from project A to B's development... Not something I want to do.

It seems to me in order to do this in GIT I would want multiple Git repo's, maybe one for each Lib

I've been recently told the first option, bringing multiple versions down into different locations, would be a bad idea. (He was talking about under SVN, so may not apply), The company I worked for did this kind of thing under Source Safe years ago and it worked pretty well - we were able to create a file that specified the version label of each lib to bring down and used a NANT script to fetch the correct versions, and could update them as required. (Not sure what the easiest way to do that here is, initially, it would be something much simpler. like just a file that said what versions it needed or something) One other thing that could be done is to apply a label across all Project A's source for a release something like: "RELEASE_1_0_PROJECT_A" and have all source brought down based on that version label. (Tag or whatever you wish to call it)

With Source Safe though, the labels are only across that location and below, not across the whole repo.

I've also worked places where they would branch the code and create a new top level tree, such as:

/Dev/x64 Branch/ProjectA (With the rest of the structure the same as the 2nd example.

And /Dev/trunk/ProjectA (With the rest of the structure the same as the 2nd example.)

In which case, to work on A and B at the same time you would have two branches of everything you needed for that project, a Project A Branch, and a Project B branch.

Suggestions?

Thanks

Update: (Would have done this as a comment below, but StackOverflow overflowed and wouldn't let me post comments that long)

OK, I did that and ended up with:

 Project\
     Libs\
        LibA
        LibB

I created it with:
git add submodule ../Lib/LibA ./Libs/LibA
git update --init

Modified a file, and then tried to push it:

git push
warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

Counting objects: 7, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 378 bytes, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, **updating the current branch in a non-bare repository
remote: error: is denied,** because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /src/C#/Lib/TraderhutLib
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to...

The comment: "By default, updating the current branch in a non-bare repository is denied, because it will make the index and work tree inconsistent..."

Sounds like I would LOL about someone making that comment - Basically, it sounds like it says: "You can ONLY check in files to an empty .Git Repo, because otherwise we will mess up your working directory to not match what you just checked in."

So, my new question: HOW Do I check in changes? What is the Simple/matching thing? Which do I use (it looks like it gives me the command to make it the default.)

Thanks.

like image 639
Traderhut Games Avatar asked Apr 03 '13 18:04

Traderhut Games


People also ask

How do I manage multiple versions in Git?

Probably the easiest way is create branches for each version and then do for example git checkout v1. 0.14 or whatever branch you want to work on. The clients can then also check out the appropriate branch for the one they need as well as when upgrading to next version.

Is there a way to put multiple projects in a Git repository?

Yes. You can put multiple projects in one Git repository but they would need to be on different branches within that repo. The Git console in ReadyAPI gives you the ability to create or switch branches from the UI. More information on the Git integration can be found here in the documentation.

What is a shared code repository?

A shared library is a way to place multiple packages in one repository, then publish it to npm and install it in other projects. It's meant to save the overhead of developing different components in different repositories and get one Git repository for all of them. It's a common practice to save overhead.


2 Answers

It sounds like you want to use submodules.

You'd have five repositories:

  • Project A
  • Project B
  • Lib A
  • Lib B
  • Lib C

Project A would have three submodules, one for each library. Project B would also have three submodules, one for each library.

When you clone a project, you'll make sure to use --recursive and you'll get all of the library sources checked out too, at the right versions (different versions for different projects, if you want). When you update library code, you'll want to commit changes into project code so the projects will use the new version of the libraries.

Submodules work by storing a reference to the SHA-1 of the submodule version in the parent project. So version 1.0 of Project A will reference commit abc123... of Lib A, which corresponds to version 1.0 of Lib A. When you check out Project A you automatically get version 1.0 of Lib A.

like image 155
Dietrich Epp Avatar answered Nov 15 '22 17:11

Dietrich Epp


Please take the time to get your hands dirty with git, and study e.g. Scott Chacon's "Pro git", Ben Lynn's "git magic" and have the various tutorials/cheat sheets linked at git's homepage nearby. Depending on the extent of the development group(s), you should also read up on git workflows. Finding out early what git can and can't do, where it differs from the systems you know (and there are differences), what things that used to be just pipe dreams or impossibly complicated are trivial in git; before commiting on how to organize the data and workflow can save many frustrations later on.

Just as I was told when studying English: Don't translate, learn to think in English. You'll be done when you dream in it. Yes, it takes time. But it is saved time.

like image 27
vonbrand Avatar answered Nov 15 '22 18:11

vonbrand