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?
4 Answers
I can't be the only one to think of the Xzibit nested items meme, right? Anyway...
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.
-
1
-
1Okay. The solution I've settled on is to just
checkout
into the Git tree, and exclude the SVN working copy from the Git repository altogether with.gitignore
.– JonahJan 27, 2012 at 19:14 -
Sarcastic edit summaries aside, reputation is there to encourage good behaviour and make the site a better place for everyone, comments are there to highlight where improvements can be made. I think with your edits your question is much more useful, hence the reversal of a not useful selection to a useful. If I didn't think your answer would benefit from my comments, I wouldn't have made them. If they were offensive to me I would have flagged. As it is, I think we all benefit from good answers being made better. (This comment will self destruct in...) Feb 2, 2012 at 14:37
-
Yo dawg, I heard you like svn, so I put svn in your git, so you can svn while you git... Jan 11, 2013 at 17:04
-
The problem is that if your svn repo itself contains externals, you can forget using
git-svn
because it doesn't handle them Sep 3, 2015 at 8:45
Although discouraged by Charles, I think that you really are looking for git sub-modules:
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 git
and 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
. In 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 .gitignore
it.
- Given the way
svn
works, the way externals work is perfectly acceptable. - Given the way
git
works, 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"
etc.
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.
-
I think the thing is I don't want Git to track the SVN working copy, because that would be redundant.– JonahJan 28, 2012 at 23:01
-
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...
-
1I found that link before, but it seems to be about using Git to manage a Subversion working copy. I want to put the Subversion working copy inside of a Git repository.– JonahJan 27, 2012 at 18:54
-
would you mind explaining more on what it does and what it's good for? "Link-only answers" are not quite welcome at Stack Exchange– gnatMay 1, 2013 at 9:53