9

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?

1
  • In light of your comments below, your question is/was "can I have an svn checkout inside a git repo?" - and the simple answer is: yes. The answer you've accepted does not answer this question.
    – AD7six
    Jan 29, 2012 at 1:00

4 Answers 4

14

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.

5
  • 1
    Check for answering the question, +1 for the yo dawg :)
    – Jonah
    Jan 27, 2012 at 19:13
  • 1
    Okay. 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.
    – Jonah
    Jan 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...)
    – Mark Booth
    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
3

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.

2

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.

2
  • I think the thing is I don't want Git to track the SVN working copy, because that would be redundant.
    – Jonah
    Jan 28, 2012 at 23:01
  • It won't, unless you explicitly add them to the git repo jonah
    – AD7six
    Jan 29, 2012 at 0:23
1

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...

2
  • 1
    I 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.
    – Jonah
    Jan 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
    – gnat
    May 1, 2013 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.