An open-source, federated content repository

Git and SVN: the beginning

My previous post about Git and SVN hopefully intrigued you enough to want more. Yes, you can use Git locally even though your stuck with using Subversion for the central repository. In this post I’ll show you how to get started, while in the next post we’ll see how the Git Eclipse plug-in.

1. Install Git

You can install it several different ways, depending on your platform and your preference. I have a Mac, so I could download and compile it using MacPorts, or I could grab the latest installer. I like simple, so since I don’t yet have MacPorts I went for the installer. Piece of cake. I also chose to manually set up my path, so in my .bashrc file I added these statements:

export MANPATH=${MANPATH}:/usr/local/git/manexport PATH=${PATH}:/usr/local/git/bin:/usr/local/git/libexec/git-core/

(Okay, I actually used some variables in my real .bashrc to keep things DRY. I thought the above might cut through all that noise.) Note that we added “git/libexex/git-core/” to the PATH. This directory contains all the commands that start with “git-” (e.g., “git-svn …” is really the same as running “git svn …”).

2. Clone a remote SVN repository

The next step for me was creating a local git repository that mirrored the remote SVN repository.

$ git svn clone -s local_dir

The “-s” option tells git that the Subversion repository use the “standard” naming convention of using “trunk”, “branches”, and “tags” directories. When this command runs, it creates a subdirectory called “local_dir”, initializes the git repository in that “local_dir”, connects to the SVN repository at the URL (which does not include “trunk” or any other branch/tag information), proceeds to download all of the history (including branches and tags) in the SVN repository, does some cleanup, and checks out the equivalent of the SVN “trunk” to our working area. And, because of Git’s bridge with SVN, we’ll be able to regularly pull changes from SVN into our git repository, and we can even upload changes we make locally back into SVN.

We now have our new Git repository, so cd into it:

$ cd local_dir

If you look closely, you’ll see a couple of things. First, Git doesn’t proliferate your working area with “.svn” folders. Instead, there’s just one “.git” directory at the top. Git also uses a different technique than SVN for remembering which files and directories should be ignored. But we can bootstrap Git’s ignore information automatically from SVN’s. We’ll use the “.gitignore” file in our working area, since we want this information to be versioned and we want everyone using the repository to be able to use it. If your SVN repository already has a “.gitignore” file, then someone’s done the work for you. Otherwise, you’ll have to run the command to generate the file:

$ git svn show-ignore > .gitignore

This will take a minute or two, depending upon the size of your working area. I would then commit this new file, placing it in the master branch.

3. Committing (locally)

To commit our new file, we first have to tell Git that we want to start tracking this file. Or, in Git parlance, we want to stage the file by adding it to the index:

$ git add .gitignore

We can use the status command to see a summary of what’s already staged, what’s being tracked but hasn’t been staged, and what’s not being tracked at all:

$ git status .

We can also get a more detail report showing all the individual changes that have been staged:

$ git diff

We can then commit our staged changes:

$ git commit -m "Description of commit" .

or, if we want to automatically stage any modified or deleted files, we can add use the “–all” (or “-a”) option:

$ git commit -a -m "Description of commit" .

With the “commit” command, Git records the entire set of staged changes as a single commit to our current branch, and it moves the branch’s HEAD pointer to this last commit. Remember, Git works locally, so this commit is recorded locally. This may sound strange at first, but really it allows you to commit (locally) much more often, which can improve your development process since backing out things that don’t work is really easy.

To see the history of commits, use the “log” command

$ git log

This displays each time, message, and SHA-1 hash (the unique identifier) for the last n commits. You can use these hashes (or the first 4 characters or so) in the diff command.

$ git diff <hash>

displays the difference between a previous commit and changes, while:

$ git diff <hash1> <hash2>

displays the difference between two previous commits.

There are a lot of things Git can do – way too many to cover here. But look at “git bisect”, “git grep”, “git revert” jut to name a few. But let’s get back to our workflow.

4. Updating from Subversion

If you’re familiar with Subversion, you’re hopefully used to doing “svn update” before committing your changes. This pulls any revisions that others have made since you last updated, and its good form to do this and to make sure everything compiles and runs locally before committing.

In Git, you do this with the “git svn rebase” command. This command fetches revisions from the SVN used by the current HEAD (of the current branch), and “rebases” any current commits on the branch to apply to these latest SVN changes. This is analogous to creating a patch file for each local commit (relative to that commit’s parent) since the last rebase, updating the branch with the new SVN revisions, then sequentially applying the patches. In other words, it takes all your local changes (in the form of commits) and reapplies them to the latest SVN revisions.

Here’s the actually command to rebase the current branch:

$ git svn rebase

If you want to fetch all of the revisions on all branches in the SVN repository and rebase any local commits on those branches, you can add the “–fetch-all” option.

5. Committing back to Subversion

Once you have rebased your local commits on a branch, you will still have changes to that branch that aren’t yet in Subversion. We want to do the equivalent of an SVN commit, which in Git is to commit each diff on the branch back to SVN:

$ git svn dcommit

This creates a new revision in SVN for each local commit on the branch. Of course, if you want them to look like a single revision, you’d need to squash the commits before running the dcommit command.


This post focused mostly on how to get started with Git using a remote Subversion repository, so I didn’t talk much about how to go about branching and merging. I think you’ll agree, though, that Git’s Subversion bridge seems very intuitive, and in fact many of the same concepts used by the Subversion bridge are the same concepts used by the rest of Git. And once again I’m going to suggest reading the Git Community Book or watching Bart Trojanowski’s presentation.

Note: Portions of this post were taken from a previous post on my personal blog.


Filed under: techniques, tools

Git it together with Subversion

This is the first in a series of posts about how I use Git to work on JBoss DNA. Like many other projects, all of the code for DNA lives in a central Subversion repository. And for a long time, I naturally used a combination of the Subversion command line client and the Subversive Eclipse plug-in.

Git works a little differently than SVN. Git is a distributed version control system, and that means that you have a local copy of your project’s Git repository. Yup, the whole thing. But that’s a game changer, because you can commit, branch, view history, or whatever while your disconnected from the web. And it’s fast (since everything is done locally) and surprisingly space-efficient. Then, when you’re ready, you can push or pull changes to other Git repositories.

Git also works really well pushing and pulling from a remote SVN repository. In fact it’s built right into Git. So if your remote repository is SVN, you can still use Git locally. The only difference is how you push to and pull from the remote repository.

What really convinced me to try Git, though, was how brilliantly it does branching. Actually, branching and merging. Quite a few source control management systems can branch, but the problem is they don’t merge – or if they do, they don’t do it well. Git, on the other hand, makes merging easy. In fact, it’s really easy to create branches, switch between branches, and merge branches.

So why am I so hung up on branches? Well, being able to branch and merge means that I can use branches for everything – bug fixes, new feature work, prototypes, or maintenance. I can create a branch where I do all my work, and I can commit as many times as I want. I can even use tags to help me remember important commits (e.g., “all tests pass”). And when my work is complete, I can merge my changes onto as many branches as I need to. All of this is done locally, without polluting the main repository’s trunk or branches. Of course, if I’m working with other people on a feature or bug (e.g., “please review these changes and provide feedback”), I could expose my own repository or we can leverage a shared repository. And when the work is all complete, merging onto the official branch(es) is cake, too.

In forthcoming posts, I’ll show how to install and use Git with a central Subversion repository, describe some of the tooling I use with Git, and outline a number of very common use cases: simple branching and merging, stashing your work to fix a bug, and so on.

Until then, if you want to learn more about how to use Git, watch Bart Trojanowski’s presentation. It is 2 hours long, but it really is a brilliant tutorial if you’re interested in learning the fundamentals how Git works and how to use Git.

Portions of this post were taken from a previous post on my personal blog.

Filed under: techniques, tools

JBoss DNA 0.4 is released

JBoss DNA 0.4 has been released, and is available in the JBoss Maven repository and our our project’s downloads area. Check out our Getting Started guide, Reference Guide, or JavaDoc. Congratulations to everyone involved with the release!

This release turned out to be much longer than we’d planned, but we were able to achieve a lot with our JCR implementation. We now support updates (even in most federated cases), support node types, and many of the JCR Session and Workspace methods. We’re using the JCR unit tests that Jackrabbit provides/uses, and we can now track our progress towards compliance. We’ve also added a file system connector (which exposes the files and directories as JCR nt:file and nt:folder nodes) and a connector that stores a graph in a relational database using JPA and Hibernate. We have a new sequencer for JCR Compact Node Definition files. We’ve made a lot of improvements and bug fixes to our Graph and Connector API. And this really is just the tip of the iceberg!

Thanks to the whole team! Interest in JBoss DNA continues to grow, and that’s a testament to your hard work and desire to build a great project. Our goal for the next release is to add support for events (observation), queries, and to continue to improve our JCR implementation so that we pass the JCR TCK!


Filed under: jcr, news, repository, uncategorized

ModeShape is

a lightweight, fast, pluggable, open-source JCR repository that federates and unifies content from multiple systems, including files systems, databases, data grids, other repositories, etc.

Use the JCR API to access the information you already have, or use it like a conventional JCR system (just with more ways to persist your content).

ModeShape used to be 'JBoss DNA'. It's the same project, same community, same license, and same software.