Git and our friction points and beginners mistakes
Introduction
A couple of days ago I posted an article talking about our migration from SVN to Git. During our first handful of days working with Git our team found several friction points hindering our daily work flow and we all did some things really wrong. But com’on after all we are learning, right?
In this post I want to share some of our findings.
Where is my blame feature?
Working with SVN and the Visual.SVN plugin for Visual Studio one can right click in any code file and call blame. A really handy feature. How can we do such a thing in with git without having to type a lot? First possibility is to use the git blame command. But this needs a lot of typing if the relevant file is located in a highly nested subfolder.
git blame /subfolder1/subfolder2/subfolder3/FileIWantToBlame.cs
not very wrist friendly I want to say.
Second way is to use gitk. Type gitk in the bash shell and right click on the file you want to blame and select “blame parent commit”. But this only works if the file has been modified otherwise it is not available in the list of changed files and thus cannot be accessed.
I wonder whether there is not a easy way to blame directly from within Visual Studio? Any suggestions…?
Help, I have merge conflicts
When merging or rebasing we might run into merge conflicts that cannot automatically be resolved by git. We can then just call git mergetool
<font face="Courier New"></p>
$ git mergetool </p>
</font></font></span>
merge tool candidates: tortoisemerge emerge vimdiff </p>
</font></font></span>
Merging the files: build.rb </p>
</font></font></span>
</p>
</span>
Normal merge conflict for ‘build.rb’: </p>
</font></font></span>
{local}: modified </p>
</font></font></span>
{remote}: modified </p>
</font></font></span>
Hit return to start merge resolution tool (tortoisemerge):
</font>
</blockquote>to manually merge the conflicting file with one of the suggested tools. If we want to permanently define which tool (e.g. tortoisemerge) we want to use we can do this by updating our configuration with
$ git config –global merge.tool tortoisemerge
now each time we type git mergetool the Tortoise merge tool is automatically opened.
Git reflog
A coworker called me this morning and said to me something like: “Yesterday night before leaving I committed all my changes to my working branch but this morning they are all gone…”. Digging a little bit deeper we found out that my coworker after committing to the local working branch pushed to the backup and as a first thing in the morning pulled from the backup.
Well I said, first of all you should not need to pull from your backup except in case where you lost your local repository due to e.g. a hard disk crash or the like. On the other hand if the backup repository would really be up to date then a pull should not have changed anything, right?
What can we do now? We analyzed the log but the last entry that showed up was about 4 hours earlier than the one that my coworker did before leaving… where did the about 3 other commits go?
After googling around we found out that git reflog might help in our situation and indeed this command showed us exactly what happened. We also found our missing commits. Hurray!
Using this command you get something similar to this
Now we can use git reset to go back to any desired point in the history (and thus undo “unwanted” changes). In our case I saved the day by using this command
git reset –hard HEAD@{5}
and my coworker was happy again….
Git and changing the database schema
When using Git as your SCM it is normal to work for quite a while – maybe for a couple of days – in a local branch and without ever pushing the changes to the origin. Usually we only push when a feature is done or a defect is completely resolved.
When implementing new features or user stories most often database schema changes are needed. We have an inhouse database schema and data migration tool that we use for this job. Each developer writes migration scripts as she is changing the schema or the (baseline-) data. Now these scripts have to follow a naming convention such as that they start with a 4-digit number and are sequential (without holes). In a distributed system it is now more difficult to maintain this numbering convention. Furthermore it is more likely that we will also have database schema conflicts.
We do not yet have a good solution for this scenario.
I’m in the wrong directory baby
This happened to me once: I was navigating to a sub directory of my local Git repository and didn’t realize that I was still in that sub directory when I did my next merge. Although I had used the –A option with git add I still had untracked files after the commit.
The problem was that the untracked files were in another branch of my repository in relation to my current location. Lesson learned: Always do your usual git operations in the root of your repository.
Backing up my local repository
Since we are going to work locally potentially for days without pushing to the origin (our central repository) we might well loose our work if we have a hard disk crash or our office is flooded. Thus we need some backup strategy. We decided to use backed up network folder to do the job. Each developer has a folder on our internal SAN which he attaches as a network folder (e.g. as a g-drive). Then we use the following command to copy a clone of our local repository to the network drive
git clone –mirror repoName g:/repoName.git
To make life easy we define an alias for the backup repository
git remote add backup g:/repoName.git –mirror
and we can now save our changes at any time by simply typing
git push backup
in the command shell.
The backups created with the –mirror options do contain all branches and their commits in the repo. We can do a git push backup and this will mirror all changes to all branches regardless of our current branch.