Version control the git way ...

Version 4

    What in the world is git?

    It would be a version control system written, originally by Linus Torvalds, and developed since then by a whole bunch of people at git-scm.

     

    Linus really?

    Yeah, have a look at youtube if you don't believe me.

     

    Why do we need git if we have subversion?

    Because, git offers quite a bit more functionality locally to the developer than svn.

     

    Oh, like what?

    Branching, commit amending, history rewriting ...

     

    But, svn does branching, what are you on about?

    Well, it does but all branches created in svn are created globally for everybody. In git, I can just create a quick local branch, make some changes, merge them then delete the branch.

     

    You have mentioned locally twice now, do you mean I commit without a server?

    Yes, git is a distributed version control system. You clone the entire repository down to your local machine, make your own commits to your own repository and when you are happy you can push back to a hub repository (like github) or get fellow developers to pull your changes from your repository. If you are confused by this then watch the youtube video as Linus explains it better than me...


    Ok... I have seen the video and got my head around distributed repositories. What did you mean by commit amending and history rewriting. That just sounds odd?

    True, it seems a little bizarre at first but once you down have your own clone of the repo, you have much greater control over the change history. As such, git allows you to amend any commit and even change around the order of commits. It is completely up to you. The only limitation is, once you have made your changes available to others by pushing or others pulling from your repository, you have a responsibility to keep your history in sync with their version. It can be done you just have to let people know that you are amending your history. Its a social thing people!

     

    Hmm... so I am curious where is this git repository?

    The teiid-designer git repository is available from github.

     

    Its a nice page and I can recognise some files listed there but what do I do?

    Make sure that you have git installed on your machine then in a terminal execute the following command. This will clone the repository into the directory teiid-designer and checkout the master branch.

     

    git clone https://github.com/Teiid-Designer/teiid-designer.git teiid-designer
    

     

    Right, I have the codebase but what do you mean by 'checkout the master branch'?

    Subversion has 'trunk' as the mainline development branch and git has 'master'. Conceptually, they are the same thing. However, the master branch is no more important than any other branch in your repository. Using 'git checkout <branch-name>' will checkout that branch.

     

    So, can you explain a little more about the commands?

    At this point, I will hand over to other people who write far better tutorials than me:

     

    Wow ... brain overload. Any words of advice?

    Yeah. Get familiar with the following (not necessarily installed by default since they require widget toolikits):

    • 'git gui' is a wonderful tool that allows you to see all your current codebase changes and commit them. It is a nice UI for controlling the 'git commit' command.
    • 'gitk' is the tool for understanding where you are in your repository. It list all the commits in the history and can display any and all the branches and tags in your repository.

     

    git-svn related issues

    I notice svn ids in commit messages. How did you migrate the repository from svn to git?

    There are a couple of ways to do it and it seems the first try always fails (for me anyway!). I used a really clever ruby script called svn2git (available here). This script will download each revision of the svn repository and add them into a git repository. This repository is clever in that it is a git repository and can still push commits back to svn if required. However, to ensure the latter works, you must include metadata!! See the command I used below.

     

    The svn2git may be available as a gem for your system but I found the one I had lacked the metadata switch hence using the latest version. This will take a while (mine took ~24 hours) so be prepared to leave it running on a machine ovenight!

     

    ruby -I /opt/nirvdrum-svn2git/lib /opt/nirvdrum-svn2git/bin/svn2git --metadata --authors authors-file.txt http://anonsvn.jboss.org/repos/tdesigner
    

     

    What is the authors file?

    This is a map of svn contributors. The git repository likes to include email addresses as well as names so this provides this information. I followed the Authors section on the svn2git page for generating this.

     

    So, I am still using the svn-git repository and wanted to commit back to the svn repository using this strange dcommit command. However, it generated the error 'Incomplete data: Delta source ended unexpectedly'?

    This threw me for a while and seems to be an oddity in git-svn. I was on a branch and assumed that git-svn would pick up on this and add the branch name to the url I was dcommitting to. It didn't so I had to use the following command instead. Note it is possible to clone from an anonymous read-only url and commit back to the secure committer-only url.

     

    git svn dcommit --commit-url https://svn.jboss.org/repos/tdesigner/branches/<branchname> --username <username>
    

     

    Reviewing branches from other people's forked repositories

    So using github, a developer, for example phantomjinx, has done some work and initiated a pull request from his forked repository. Github has the tools to review the new commits and commence discussions. For help on these have a look at https://help.github.com/articles/using-pull-requests. However, it can often be difficult to review a complex commit by just looking at it. Well, git can help by allowing the pulling of the branch (or even just the single commits) down to your local git repository. Here is how:

     

    • Add phantomjinx's repository to your git repository. Only needs to be done once.
      git remote add phantomjinx git://github.com/phantomjinx/teiid-designer
    • Fetch everything that phantomjinx has in his repository
      git fetch phantomjinx
      

     

    • Create a new branch of phantomjinx's work to review. In this case we will be reviewing phantomjinx's master branch but it could be another feature or topic branch
      git checkout -b pj-master phantomjinx/master

     

    • When the review is complete, the branch can be thrown away
      git checkout -f master
      git branch -D pj-master

    The anything else section

    What is gerrit?

    Since git's introduction, google came up with a really cool tool for allowing code reviews. This is gerrit. It is designed as the gatekeeper to the main git repository in that developers push to gerrit's url instead and their commits are displayed in a queue, allowing others to review them. Assuming the commit is good to go, the reviewer then submits it to the main git repository.

     

    Gerrit can even be set up to validate commits by building them using jenkins and running tests. Should a commit fail a test then this can be flagged to the committer who can amend the commit and repush a different version that does not fail the test.

     

    Is it hard to set this up?

    Getting the infrastructure right for this will require installation on a central server but once this is done, the workflow is pretty simple. You may want to have a look at this helpful page from Openstack on their installation.

     

    Displaying the branch in your terminal prompt

    Since git is, at its core, a set of terminal commands, it can be useful to know useful information about the repository without resorting to 'git status' each time. One effective method is to use the display prompt. The following code should be added to a bashrc (either ~/.bashrc or /etc/bashrc), in order to display the current branch and show, by colour, whether the repository is clean or contains modified files that have not yet been committed.

     

    # Git prompt
    c_cyan=`tput setaf 6`
    c_red=`tput setaf 1`
    c_green=`tput setaf 2`
    c_sgr0=`tput sgr0`
    
    parse_git_branch ()
    {
      if git rev-parse --git-dir >/dev/null 2>&1
      then
        gitver=$(git branch 2>/dev/null| sed -n '/^\*/s/^\* //p')
        echo -e "[$gitver] "
      else
        return 0
      fi
    }
    
    branch_color ()
    {
      if git rev-parse --git-dir >/dev/null 2>&1
      then
        color=""
        if git diff --quiet 2>/dev/null >&2
        then
          color="${c_green}"
        else
          color=${c_red}
        fi
        echo -ne $color
      else
        return 0
      fi
    }
    
    PS1='\[$(branch_color)\]$(parse_git_branch)\[${c_sgr0}\]\u@\h \[${c_red}\]\W\[${c_sgr0}\]\$ '
    

     

    terminal.png