Showing posts with label svn. Show all posts
Showing posts with label svn. Show all posts

Saturday, June 4, 2011

migrate Subversion repository/dump to Git & Github, with tags and branches

A simple and complete method for migrating from subersion to git, bringing over past tags and branches.

I migrated a work repository from Subversion to Git last week. It went surprisingly smoothly. There were a more steps than I expected after reading various, selected, sources.

My repository was in "standard layout" containing only a single tree/project. I was sent a dump of the repository created with svndump. If you have direct access to your svn repository, skip step one. Similarly you can skip the github steps or replace them with your own "primary git server."

Note, if you don't want to maintain the svn tags and branches, then there is a simple single step solution using git-svn. This works if you don't have tags and branches to keep, or you just want a personal git checkout of a remote svn repository.
git svn clone --no-metadata --stdlayout --A users.txt http://svn/repo/here/ new_checkout_name/

Overview:

  1. import svn dump into svn repository
  2. create mapping file of svn committer to email address
  3. create empty git repository
  4. cd to git repository
  5. import from svn repo to git repo
  6. pull branch and tag information from svn to git
  7. create github repository
  8. add remote repository
  9. push all tags and branches to github repository.
Steps:
  1. import svn dump into svn repository from dump file svn_repo.dump
    % svnadmin create svnrepo
    % svnadmin load svnrepo < svn_repo.dump
  2. create mapping file of svn committer to email address
    Create a file called authors.txt and fill it with line separated “svn-name = git-name ” pairs.
    #example:
    % cat authors.txt
    user_a = Alpha <alpha@example.com%gt;
    user_b = B Dawg <bdawg@github.example.com%gt;
  3. create empty git repository
    % mkdir gitrepo
    % git init gitrepo
  4. import from svn repo to git repo
    #   git svn clone file:///pathto/svnrepo /pathto/gitrepo –no-metadata -A authors.txt --stdlayout
    svn repo path must be an absolute path when using file://
    % git svn clone file://$(pwd)/svnrepo gitrepo/ --no-metadata -A authors.txt --stdlayout
  5. cd to the git repository
    % cd gitrepo
  6. pull branch and tag information from svn to git
    tags and branches are both viewed as remote branches, tags are prefixed with "tag/".
    For each branch you want to migrate, make a local branch.
    For each tag, make a local tag.
    % git svn fetch                          # fetch remote branches and tags from svn
    % git branch -r                          # view remote branches
    % git branch local_branch remote_branch  # for each branch to migrate
    % git tag local_tag tags/remote_tag      # for each tag to migrate
    % git branch                             # check work by viewing local branches and ...
    % git tag -l                             # ... local tags 
  7. create github repository
    ( github repo ui, create yourrepo )
  8. add remote repository
    % git remote add origin git@github.com:yourname/yourrepo
  9. push all tags and branches to github repository.
    % git push origin --tags   # push all tags
    % git push origin --all    # push all branches 

Sunday, October 4, 2009

vimdiff ... where have you been all my life?

I'm finally giving vimdiff a try. I normally get by with diff, diff -u (unified) and diff -u -w (unified, ignore whitespace) and their ssh equivalents svn diff (unified) and svn diff -x -w (to ignore whitespace).

I know vimdiff exists, and have used it trivially once or twice. But never felt a need to dive in.

Right now, I'm looking at a file of a coworker's modified code, trying to figure out which version it originally corresponded to. I've looked at the diffs, and I think I know which version it is, but I was having trouble comparing the lines to see what some of the diffs mean.

I popped it up in vimdiff vimdiff file1 file2 and now I have a lovely side-by-side view of the two files, with coupled scrolling. Chunks of unmodified code are folded and out of the way. The vim folding commands work normally: zo will open a given block if I need to see that code and zc will close that block back up. zA to open all and zC to close all.

The normal vim window/frame commands can be used to switch between the two frames. Since scrolling in either file scrolls both files, there isn't a big need to switch between the frames, except when examining long lines. By default, line-wrap is off for the diff, so long lines appear truncated until the viewport is scrolled. control-w w will switch between the two frames. Jump to the end of the long line with $. Again, both frames will scroll together left/right just as with up/down. Alternatively, :set wrap in command mode will enable word wrapping, this needs to be done in each frame independently. If literal tabs are making your lines too long, try displaying tabs as smaller entities: four character :set ts=4 or two character :set ts=2. Again, this must be applied to each buffer independently.

I really like the intra-line difference highlighter. The whole line is highlighted, but the changed portions are highlighted in a different color. Purple and Red respectively in my setup. That helps me pinpoint the exact character changes, so I can focus on see the "why" of the change instead of digging for the "what".

vimdiff and svn is not an either/or proposition. svn allows an external diff command, via the --diff-cmd switch. Unfortunately, vimdiff doesn't work out-of-the-box with this flag, as svn adds extra information when passing to the diff program. A have a very short wrapper called vimdiff-svn-wrapper that I use to drop the extra arguments. I have this in my path and use svn diff --diff-cmd vimdiff-svn-wrapper filename to run svn diff on filename, displaying the output in vimdiff.

On the other end of the spectrum is svnvimdiff from vim.org. This runs vimdiff on the output of svn diff. It's messy the way it uses temp files and I just tried the version I downloaded last year it didn't work for me. I've just written a new version. Had I checked the link, I'd see the original is on version 1.5 and I have version 1.2. My version uses the vimdiff-svn-wrapper with svn diff --diff-cmd. I have directly copied his clever method of getting the modified svn files by parsing the output of svn stat.

Time to get back to figuring out the changes in his code...