I'm developing a project in Git. IT depends on another project, that's in a Subversion repository. I'd like to be able to make changes to the Subversion project in the tree, and commit to/update from the Subversion repository from within the Git project. Is that possible?
One of the remaining cool things that Subversion does is called "externals." It's a way to point at a specific branch or directory in another svn repository. You can even pin it down to a specific version of a specific directory. Externals are really darn nifty, and would solve this problem in an instant, as changes made in an externals directory are automatically pushed back to the source when doing a commit.
Externals is also something missing in git. Git has submodules, but they don't work in the same way, in that they're tied to a specific commit. This effectively means that there's no native solution to the problem of having "nested" repositories that can be read and written to at the same time and remain perfectly in sync, no less nested repositories using different backends.
If you don't want to do the submodule revision pinning dance, there's another workaround.
Git has decent svn emulation in the
git-svn tool. You're probably already using it. The SO question "How do I keep an svn:external up to date using git-svn?" offers us a useful option by abusing that tool.
The accepted answer was simply using
git-svn to check out the Subversion repository outside of the tree controlled by git, simply using a symlink to point to it inside the tree. There's a bit more manual work involved in this one, as you would need to remember to commit that specific repository every time you make a change in it. However, it's simple, it's straight-forward, and it is known to work.
Another option entirely would be looking at Mercurial's subrepositories, which can host both git and svn. I'm not sure if you really want to go three levels deep.
Git has an svn wrapper. Here is a quick run-down: Effectively Using Git With Subversion
Like many organizations using Rails, we have caught the git wave, and are in a state of transition between git and Subversion. Our open-source work is stored in git repositories, but our client work is still stored in Subversion repositories, and probably will be for some time. While git is amazing, Subversion still has its good qualities, and makes an excellent centralized repository, especially with its ecosystem of user-friendly tools.
The integration between git and Subversion (git-svn) is so well done that several of us have been using git as our interface to all our Subversion repositories. Doing this is fairly simple, but there are some interesting tricks, and so I thought I would share a day in the Viget life with git-svn...
Git's submodule support allows a repository to contain, as a subdirectory, a checkout of an external project. Submodules maintain their own identity; the submodule support just stores the submodule repository location and commit ID, so other developers who clone the containing project ("superproject") can easily clone all the submodules at the same revision. Partial checkouts of the superproject are possible: you can tell Git to clone none, some or all of the submodules.
While Charles seem to think that
git submodules are deficient because they can't work like
svn externals (referencing the head of a branch rather than a specific revision), I think this is as much because of the difference in expected workflow between
svn as anything else.
Depending on when and where you have updated your working copy, directories at different points in your
svn working directory hierarchy might be at different revisions. That isn't possible with
git whenever you update to a revision, you update the whole of your working copy to that revision - you expect that when you go to revision 123abc that you will get the exact same code as the last time you checked out 123abc, and that includes any and all submodules that revision might have.
If you want to update a submodule, you have to update it and then make a new commit to the super-module to update it to use the new revision in the submodule. It means submodules are less flexible than externals, but it enforces the primary
git paradigm of a repository wide snapshot.
If you want
svn externals always use the latest revision functionality then you are pretty much on your own. As mentioned, you just have to check out the
svn submodule manually and then
- Given the way
svnworks, the way externals work is perfectly acceptable.
- Given the way
gitworks, the way submodules work is perfectly acceptable.
Incidentally, as far as I understand it, Mercurial subrepositories work in the same way as Git submodules, so that won't help either.
Are you just looking for
git-svn? By depends do you mean the parent version is in svn, or it has vendors which are svn projects?
Assuming by depends you mean dependency:
You can put any kind of repo inside a git repository without problems. e.g.
$ mkdir ~/project $ cd ~/project $ git init $ ... $ git commit -va [master (root-commit) xxxxxxx] Did something ... $ mkdir vendors $ cd vendors $ svn checkout svnproject(url) $ cd svnproject $ ... $ svn ci -m "committing to svnproject"
And then manage
svnproject as you normally would. You can of course use
git-svn instead to interact with your svn repo using git commands.
You can also then do this:
$ cd ~/projects $ git add vendors/svnproject $ git commit -m "adding svnproject source to main repo"
In that case, updates you make to files in
svnproject will show up as both svn and git diffs. An example where
/tmp/gitproject is a .. git project, and
/tmp/gitproject/vendor/minify is a (random) svn checkout:
[andy@laptop:/tmp/gitproject/vendor/minify]$ vim README.txt [andy@laptop:/tmp/gitproject/vendor/minify]$ git status # On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: README.txt # no changes added to commit (use "git add" and/or "git commit -a") [andy@laptop:/tmp/so/vendor/minify]$ svn status M README.txt [andy@laptop:/tmp/so/vendor/minify]$
If you use
git-svn to interact with your svn-dependent repository, it's possible to keep it in sync with changes you've made in the parent git project using
git-filter-branch and therefore not need to commit to each repository individually.
As an aside: from experience keeping a git and svn project in sync is generally quite problematic unless one or the other is read-only.