Git as subversion

    Some time ago, when starting a new project, it was decided to try using Git instead of Subversion. After some time, the team was divided into those who love Git (programmers) and those who hate it (designers and artists). The experiment to replace Subversion with Git failed and the prospect of returning Subversion loomed on the horizon.

    After scratching his turnips and shuddering at the memories associated with Subversion, the men decided: “Well, we are programmers!” and filmed your Subversion with git and cookies. So the git-as-svn project was born .

    Now we can use both Git and Subversion with the same repository. Moreover, access through Subversion directly uses the data of the Git repository, unlike, say, SubGitwhere a separate repository is used for Subversion.

    Why did you need another bike?

    In fairness, it should be noted that both camps were right in their own way. The following can be said in favor of Git:
    1. With Git, you can do a task branch and quietly commit intermediate results without risk breaking everything.
    2. Git, compared to Subversion, is unrealistically fast.

    Against Git:
    1. Higher entry threshold:
      • Git is objectively more complex than Subversion;
      • TortoiseGit is far from as convenient as TortoiseSvn;
      • many things need to be done through the console;
      • many more ways to shoot your leg.
    2. Git is not very good with Windows clients.
    3. To work in the Subversion style (updated → worked → uploaded → worked → uploaded ...) you need a lot more body movements.
    4. There is no separation of rights inside the repository.
    5. With a large number of constantly pouring people, people start banging their heads (between pull and push, someone has time to wedge themselves).

    And most importantly: Git does not give any advantages and creates additional problems if the files are not amenable to merge.

    When it became clear that the experiment to replace Subversion with Git failed, they began to search for a solution to the current situation. During the search were found:
    • Subversion support on GitHub .
      Available with GitHub Enterprise for hundreds of oil.
    • Dumb project SubGit .
      SubGit tries through hooks to keep Git and Subversion repositories in sync. This architectural solution looks very shaky, although it should be noted that the implementation seems to work.
    • Fiercely inhibiting the python implementation of the Subversion frontend for the Git repository.
      The most important thing in this project is its small volume. After that, the task of implementing the Subversion frontend for the Git repository began to seem just insane, and not absolutely insane, as it was before. :)

    What is it and how does it work

    This project is an implementation of the Subversion frontend for the Git repository. It allows you to work with the repository with at least:
    • console Subversion client;
    • TortoiseSVN;
    • Svnkit

    Currently supported:
    • svn checkout, update, switch, diff
    • svn commit (!)
    • svn log
    • svn cat ls
    • svn replay (svnsync)
    • partial checkout
    • sparse working copy (svn --depth / - set-depth)
    • git submodules
    • authentication through LDAP

    In performance, the work is not just comparable, but in places even surpasses the native Subversion server.

    How does a commit work?

    One of the most important parts of the system is saving changes. In general terms, the idea is as follows:
    1. At the time of the svn commit command, the client sends its changes to the server. The server at the same time remembers them. At the same moment, the first check for the relevance of client data occurs.
    2. The server takes the head of the branch and begins to form a new commit based on the data received from the client. At this point, another check is made for the relevance of client data.
    3. Checks the integrity of svn properties for the data being poured.
    4. The server is trying to console the Git client to push a new commit into the current branch of the same repository. Further on the result of the push:
      - if everything is fine - we load the latest changes from git commits and rejoice;
      - if not fast forward - load the latest changes from git commits and go to step 2;
      - if the hooks were beaten, we inform the client;
      - if another error - we inform the client.

    Thus, due to the use of console Git in this operation, we avoid the race with filling directly through Git, and we get hooks as a nice bonus.

    Where are the svn data of the repository stored?

    To represent the Subversion repository, you need a series of data that is either absent in Git (for example, data about where the file was copied from) or very expensive to get (for example, the revision number when the file was last changed). In order not to deal with their calculation every run, they are cached in the branches refs / git-as-svn / *. The same cache allows you to avoid breaking the compliance of Git commits with Subversion revisions due to force push operations. ;-)

    Known Issues and Limitations

    At the moment, we have to put up with the following restrictions:
    1. it is impossible to change svn properties by means of Subversion;
    2. The history of copying files is not saved.

    Svn properties

    The main trouble with svn properties is that some properties need to be kept in sync between Git and Subversion. To prevent this data from diverging, svn properties are generated based on the contents of files from the Git repository (for example, svn: ignore is generated based on .gitignore). When committing, the stored properties are checked for data in the repository. This imposes an important limitation: you need to correctly configure svn: auto-props, otherwise when adding files the user will have to bring them with his hands to the form that the server expects.

    Most evil feature: svn: eol-style. The main problem is that the default behavior of Git in the context of eol is broken and corresponds to the .gitattributes file with the contents:
    * text = auto eol = native 

    That is, with default settings, Git changes the contents of text files.

    After much suffering, a solution was found to the eol problem: add the .gitattributes file to the root of the Git repository, starting with the line:
    * -text

    This will require Git not to touch the line endings of the files until they explicitly ask for it.

    And what is the result?

    At the moment, the project is in a leisurely development and is operated in one of the Mail.Ru Group teams. As a result, people are free to use a tool suitable for their needs: designers use TortoiseSvn and upload changes directly to master, and programmers use Git and live in their cozy little branches. The situation as a whole became healthier, and colleagues stopped clenching their fists when someone nearby pronounced the words Git or Subversion.

    What needs to be done to poke a wand into a project?

    To start git-as-svn you need:
    1. Install Java 8.
    2. Download the latest build from .
    3. Unzip the archive.
    4. Start the server.
      java -jar git-as-svn.jar --config config.example --show-config

    As a result, a Git repository with one test commit will be created, accessible at the URL svn: // localhost / example / from under the user test with the password test. As a client, it is highly recommended that you use the client for Subversion 1.8+.

    Also popular now: