Showing posts with label git. Show all posts
Showing posts with label git. Show all posts

Tuesday, January 15, 2013

Git to SVN

Sometimes cases might arise when you need to transfer projects from Git to SVN, like when you are required to maintain an in-house SVN repository of multiple external Git repositories. In my case I had to transfer two Git repositories (say git1 and git2) to SVN.

Since there are two Git repos, I wanted to set them as different projects in SVN repo. SVN project is simply a folder in the repo server (with trunk/branches/tags subfolders when following standard svn project format).

First step would be to checkout the Git repos to the system.
git clone https://github.com/your-project1 git1
git clone https://github.com/your-project2 git2

The next step would be to follow these set of instructions from each local Git directory to import them to SVN project.
1. cd /path_to/git1
2. svn mkdir --parents protocol:///path/to/repo/PROJECT1/trunk -m "Importing git repo"
3. git svn init protocol:///path/to/repo/PROJECT1 -s
4. git svn fetch
5. git rebase trunk
5.1.  git status
5.2.  git add (conflicted-files)
5.3.  git rebase --continue
5.4.  (repeat 5.1.)
6. git svn dcommit

In step-2, svn mkdir would create both the PROJECT1 and trunk folders and commits the change.
Here protocol:///path/to/repo/ is the http/https location of the SVN repo like http://IP/svn  or the local SVN repo like file:///home/user/svn-repo.

In step-3, "-s" indicates that project follows standard svn trunk/branches/tags folder structure. If not following the non-standard format, we can use --trunk, --branches and --tags flags. Following a non-standard folder structure is complicating the Git-to-SVN process. So prefer the standard structure.

After #3 you'll get a cryptic message like this:
Using higher level of URL: protocol:///path/to/repo/PROJECT1 => protocol:///path/to/repo
Just ignore that.

When you run #5, you might get conflicts. Resolve these by adding/removing files with state "unmerged" and resuming rebase. You might also need to solve content conflicts. To identify the conflicts when the rebase stops at a patch #, use the command:
git status

If there is CONFLICT(add/add) for a file or "added" message in the git status's contents in the unmerged section, then add the file using:
git add conflict-file

If there is a delete/modify message in the status, then we need to remove the file using:
git rm conflict-file

If there is content conflict, then we need to perform the following operations:
git checkout --theirs conflict-file
git add conflict-file
As per [3], when we perform git rebase trunk, our HEAD would be on the svn trunk branch and our git master commits would be on other branch. Hence we need to checkout the file from theirs branch and add the file to SVN.

After we resolve the conflicts as above, type command git rebase --continue.
Eventually, you'll be done; Then sync back to the svn-repo, using dcommit. That's all.

Keeping repos in sync

You can now sync from svn -> git, using the following commands:
git svn fetch
git rebase trunk
And to sync from git -> svn, use:
git svn dcommit

Final note

You might want to try this out on a local copy, before applying to a live repo. You can make a copy of your git-repo to a temporary place, simply using cp -r, as all data is in the repo itself. You can then set up a file-based testing repo, using:
svnadmin create /home/name/tmp/test-repo

And check a working copy out, using:
svn co file:///home/name/tmp/test-repo svn-working-copy

That'll allow you to play around with things before making any lasting changes.

Addendum: If you mess up git svn init

If you accidentally run git svn init with the wrong url, and you weren't smart enough to take a backup of your work (don't ask ...), you can't just run the same command again. You can however undo the changes by issuing:
rm -rf .git/svn
edit .git/config
And remove the section [svn-remote "svn"] section.

You can then run git svn init anew.

References:
1. http://stackoverflow.com/questions/661018/pushing-an-existing-git-repository-to-svn
2. http://stackoverflow.com/questions/8146289/git-how-to-get-theirs-in-the-middle-of-conflicting-rebase
3. http://stackoverflow.com/questions/2959443/why-is-the-meaning-of-ours-and-theirs-reversed-with-git-svn

APPENDIX
Another way of achieving the same would be using https://github.com/guilhermechapiewski/git2svn, where you run a script to transfer the commits from git to svn. But this completely shifts you to SVN and your SVN and Git are delinked. So future commits to SVN will not be reflected to Git and vice versa.





Sunday, June 24, 2012

Using GIT from inside corporate proxy

Shamelessly lifted from the below reference.

Many corporate firewalls prevent git from using its efficient binary protocol by blocking outbound network connections. Sometimes, you are lucky and are trying to clone a repository that is hosted on a site like github which exports their repositories over HTTP, which would enable you to get through the firewall using the http_proxy environment variable. However, you are usually not that lucky and are only given a git:// URL to clone from.

Fortunately, most corporate firewalls allow for tunneling connections through their HTTP proxies, using HTTP CONNECT. This is normally used for allowing browser to connect to secure websites (using SSL over port 443), but if you are lucky, you can have your firewall administrator configure the proxy to also allow CONNECT for port 9418, which is the port used by git.

Once they have appropriately configured the proxy, you should then be able to use tools like netcat-openbsd or socat to connect through as follows…

STEP-1: Install `socat`. For example, on Debian/Ubuntu, just 'sudo apt-get install socat'.

STEP-2: Create a script called `gitproxy` in your bin directory;
#!/bin/sh
# Use socat to proxy git through an HTTP CONNECT firewall.
# Useful if you are trying to clone git:// from inside a company.
# Requires that the proxy allows CONNECT to port 9418.
#
# Save this file as gitproxy somewhere in your path (e.g., ~/bin) and then run
#   chmod +x gitproxy
#   git config --global core.gitproxy gitproxy
#
# More details at http://tinyurl.com/8xvpny

# Configuration. Common proxy ports are 3128, 8123, 8000.
_proxy=proxy.yourcompany.com
_proxyport=3128

exec socat STDIO PROXY:$_proxy:$1:$2,proxyport=$_proxyport

You will need to replace proxy.yourcompany.com with the name of your proxy host and the port with the port used by the proxy (common ports include 3128, 8123 and 8000).

 STEP-3: Configure `git` to use it:
 git config --global core.gitproxy gitproxy

References:
http://www.emilsit.net/blog/archives/how-to-use-the-git-protocol-through-a-http-connect-proxy/