Zurück zur Übersicht

Fabian Buch

21.03.2011

Utilizing Git to dive into huge code bases – Git SVN Tips

Unfortunately there are still projects not on dvsc like git. That’s especially true

for enterprise customers which are at least stuck on Subversion if not worse.

So the first thing I do on new projects I join:


   git svn clone -s svn-url

Or installing Git if I have to work on customer provided machines. That’s even more

important than the rest of a development environment like an IDE.

From experience I find it especially useful to experiment with new code basis

utilizing Git. Grown and big projects aren’t easy to understand architecturally and

implementation wise without digging deep. With the help of Git you can jump right

in, without fear and without messing everything up or having too much unrevertable

local changes. Just commit early and often! By doing it locally, in experimental

branches you can try and learn. Before you publish something to a wider audience

(svn) you can reorder, cherrypick and change everything or parts of it. Git is my

tool of choice to get my hands dirty with legacy code (new one too of course).

Some useful tips on how I use Git-SVN:

SVN history is linear, so you can’t use branches and merge the usual git-way without

thinking.

What often happens to me is that I implement a new feature, do some refactorings on

my way etc and an urgant bug report comes along. But I commited on master, don’t

want to push it to SVN yet since it’s not finished yet and might not be stable. What

to do? git svn dcommit would push all my local master commits to svn. The solution:


   git branch featureA
<tt>
      |svn                                | master
   ---o---o---o---o---o---o---o---o---o---o
                                          | featureA
</tt>

Now both branches featureA and master point to the latest commit. But we want master

to point to an earlier commit. Let’s say the last 10 commits aren’t in SVN yet and

the last 8 are experimental, so 2 could be pushed.


   git reset --hard HEAD~8

or


   git reset --hard sha-hash-of-commit-to-point-to

Now my master is in the state it was in 8 commits ago and my experimental changes

are still in featureA branch.

<tt>
      |svn    | master
   ---o---o---o---o---o---o---o---o---o---o
                                          | featureA
</tt>

I can continue with fixing that critical bug, commit and svn dcommit. Have a look on how your history look with gitk –all.

<tt>
                  | svn
       ---o---o---o master
      /
   ---o---o---o
               \---o---o---o---o---o---o---o
                                           | featureA
</tt>

Dcommit rebased 3 commits and especially if

there were some more upstream svn commits, I want to base my experimental stuff

ontop of this. So I do a


   git checkout featureA
   git rebase master
<tt>
                  | master
   ---o---o---o---o---o---o---o---o---o---o---o
                  | svn                       | featureA
</tt>

Even if I could live without the upstream changes on my featureA branch for now, I’d

need a rebase later anyway, so I can do it in advance. That’s because the history

wouldn’t be linear anymore by doing a three-way merge of my featureA into master without rebasing.

When I’m satisfied and with featureA and nothing changed in master I can


   git checkout master
   git merge featureA
   git branch -d featureA

And since it’s a fast-forward merge can continue to push it to SVN


   git svn dcommit
<tt>
                                              | master
   ---o---o---o---o---o---o---o---o---o---o---o
                                              | svn
</tt>

If something did change in master I just do another rebase before the merge.

If I come to the conclusion that my experimental branch was just for learning

purpose and only one or two useful refactoring or unit-test improving commits I take

only these to master and abandon the branch.


   git checkout master
   git cherry-pick sha-of-one-commit
   git cherry-pick sha-of-another

If I’m overall satisfied with the results of my experimental branch, but not with commit messages, how the commits are ordered and maybe their scope, I use git rebases interactive mode


   git rebase -i sha-after-this-commit

reordering commits, splitting commits, editing commit messages, squashing multiple commits together.

There are endless more possibilities to get a better grip on your code-base.