vendredi 13 avril 2012

Experience and advanced usage of Git

Why I moved from SVN to Git

I Dislike about Subversion :

  • pollution of deep directories (.svn)
  • slow (most operations access the network)
  • cannot check history or diffs offline
  • does not track mergeinfo (old SVN version currently installed in my company) so repeated merges from the same branch are painful
the Confluence team experienceThe moral of this story is that until Subversion improves, be very careful about merging copies and renames from one branch to another.

I like in Git :

Randal Schwartz introduction
  • Distributed development (works for Linux !)
  • Large file counts
  • Handles complex merges
  • Making trial branches
  • Very fast
  • Robust
  • Pure java library
  • native Eclipse plugin
  • Lets you choose between merge and rebase to publish/hide intermediate commits
But with Git :
  • no history of individual files (does not track explicitely renames)
  • does not handle permissions or ownership

Moving from SVN to Git 

See this other post for the details.

Basic Git usage

My Favorite Git tools

  • Gitblit  is an open-source, pure Java stack for managing, viewing, and serving Git repositories.
    It's designed primarily as a tool for small workgroups who want to host centralized repositories.
    Really simple to configure and use (it took me 30 minutes to setup, and I created 20 repositories since, with users, groups ...)
  • Gource : a fun way to get a graphical view of the history. Almost useful to show to a non technical guy who worked on what

Some advanced usage I really like

Interactive rebase 

rebase -i allows you to rewrite your local history, switch or delete commits ... do this before you push !

Stash 

And never lose your local changes before you checkout or pull.

Find the faulty commit with bisect

  1. write a shell/batch file to test your project / reproduce the issue, for instance
    mvn clean install -DskipTests -o
    mvn test -Dtest=SpringMockTest -o
  2. Clean up your workspace (git stash for instance)
  3. Identify the first and last commits you want to test (either by their sha or tag name) using gitk or git log
  4. Tell git bisect about these boundaries :
    git bisect start HEAD v1.2 -- # HEAD is bad, v1.2 is good
  5. Start git bisect (and go take a coffee if you have a lot of commits to test) :
    git bisect run myShellTest

Filter-branch and modify the past

This allows to modify the history of a repository, for instance to delete files which should not be there.

2 use cases at least :
  • remove sensitive data (passwords) from the history
  • reclaim space by removing zip files, libraries which clutter the repository

Scenario to remove files :

git filter-branch --index-filter 'git rm --cached --ignore-unmatch MyFileName' --prune-empty -- --all

To remove folders :

git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch MyFolder' --prune-empty -- --all

Note : use simple quotes ' on Linux/Mac but double quotes " on Windows ! (See this post)
Ex on Windows :
git filter-branch --index-filter "git rm -r -f --ignore-unmatch */lib/*.jar" --prune-empty -- --all

You can then push it and force the update with
git push origin master --force


To clean up the space locally :
git reflog expire --expire=now --all
git gc --aggressive --prune=now


The complete documentation I used is on GitHub