4 Easy Tips To Work Better With Git

Maybe they are quite trivial and only come from common sense, but sometimes it's useful to repeat. By the way, these are general purpose suggestions that can be used also with other versioning systems.

1. Use Tags To Label Versions

Every single release of your software that leaves your PC must have a commit tagged with the version number, this way:
git tag ver_1.02
Remember to push the tags to the remote repository with:
git push --tags
This will help you to understand which release you have to use to reproduce issues that testers or users find. It's also useful when you need to create a changelog from a previous release. But this is related also with the next point.

2. Write Meaningful Commit Messages

Explaining why you made a commit and which parts are involved can help other developers (and especially you, in the future) to quickly understand the change made without having to deal with differences in the code.

If you are using a bug tracking system, always mention the id of the issue that usually include detailed information on how to reproduce a particular bug. And this may help when that code will be changed in the future.

Besides, good written commit messages can help you to create a complete changelog, even with automatic tools.

For a quick reference about the style to adopt for commit messages, you can look here, while a more complete explanation can be found here.

3. Signal Particular Commits

When you work in a team, it's possible that someone does not respect the conventions about tabs/spaces, position of curly braces, etc. If you are a coding style nazi, you'll fix all of these as soon as you notice them.

The important thing is to not mix these kind of changes with modifications on the behavior of the code. Another good practice is to make clear in the commit message that you are just doing cosmetic changes.

A good way is to start the message with the word "[WHITESPACES]" or "[COSMETIC]". On some projects  I also use prefixes for changes on test cases and documentation.

4. Each Commit Should Leave The Repository In A Good Status

This means that your project must always build without errors, no matter which issue you fix. The repository is not your daily backup.

If for some reason this is not possible, for example because your modification needs someone else's work to be completed, it must be signaled in the commit message (see also previous point).

Conclusions

Following these suggestions is not a waste of time. Believe me, when you are in trouble you'll be grate to easily access all the information you need. The following infographic can help you to remember these tips (click for a larger version).



How To Recover Deleted Git Commits

In many Git tutorials it's written "never use git reset --hard". And there is a good reason: this command deletes commits, and, if you don't have pushed to a remote repository, your changes are lost (if you don't know where to find them).

A Little Story

This happened to me some year ago, when I was a Git newbie. There was a bug on a software so I created a new local branch starting from the master and started to fix it. In the meantime, a colleague of mine asked me for a quick workaround to continue his work. So I switched back to the master and added a couple of temporary commits.

After a week, the state of the repository was this:


The bug was fixed, the temporary commits could be removed and the branch merged to the master. Easy to say, easy to do, easy to mess.

My idea was to move to the master, delete the temporary commits and then merge the fix branch. Unfortunately when I run...
git reset --hard HEAD^^
...I was on the wrong branch. The good commits were gone. Panic!

Where Have They Gone?

What I've learned from this experience is that deleted commits are still there, at least until you run git gc or git prune. The problem is to find a way to bring them back. What I did at the time was to use grep to search for the commit message under the directory .git of the repository.

In this way I've discovered that in the directory .git/logs/refs/<branch-name>, in the logs are also recorded the hashes for every commit. With hashes it has been easy to checkout the second commit (going in a 'detached HEAD' state) and verify that nothing was missing.

At that point, I've created a new branch (with git checkout -b new_fix) and carefully executed the original plan, this time without surprises.
I love it when a plan comes together!
- John "Hannibal" Smith

Useful Git Commands: Stash

Tom knows best!
(Picture by dealingwith)
How wonderful would it be to do your job without interruptions? But unfortunately we live in a complex world and intermissions are part of the game.

A particular annoying disturbance is when you are in the middle of a big refactoring or adding a complex function to a software and someone comes to you asking to immediately fix a bug in the same code.

What you need is a function in your VCS to park your modifications, checkout the right version to modify, fix the bug and then return to your code, without copying files around the disk or make meaningless commits. What you need is git stash.

Simple and Powerful

To save your temporary work, you only need to type git stash. Use the flag --include-untracked to save also new files. When you need to go back to your previous situation, use git stash pop. You can stash how many commits you want and replay them in any order and potentially on top of different commits.

Stashing can be useful every time you need to save your partial work or obtain a clean workspace without losing your modifications, for example when pulling from a remote repository on a non-clean working tree. But it can also be used when you realize that you are working on the wrong branch: you have just to stash, checkout the right branch and then pop. Fast and easy.

In the man page you can find other options, such as the creation of a new branch starting from the commit at which the stash was originally created.

4 Things to Do Before Starting a New Project

Are you ready to put your hands on the keyboard?
(Image by courtesy of +Riccardo Esposito)
This is the situation: the Project Manager has written the specifications, everything is clear and you only have to do the kick start to you team of developers.

This point is where you can start to fail. If you let every programmer (that is lazy by definition) to take its own decisions, your project will be pure anarchy.

Here there is a short list of things to consider before starting to write code to have some chance to do the job in an acceptable amount of time and without losing your mental health.

1. Select a VCS and Lay Down the Rules for Commits and Branches

I suggest you to use Git. I have already explained the reasons in this post but, to make it short, Git is fast, cheap (not because it's free but in terms of disk usage) and extremely powerful.

Once you have chosen Git ;-) you have to set clear rules for commit and branches to avoid developers transform your repository in a landfill. You can take inspiration from this great post.

The rules should also cover commit comments because it's important that every change in the repository is correctly documented.

2. Define Coding Styles

Using the same code style is very important if many developers are working on the same project. Everyone should be able to understand and modify every piece of code without spending time to feel comfortable with indentation and names.

To improve the adoption of a style, you can institute a fine of 1 euro/dollar/pound for every line of code that is not correctly formatted and, from time to time, use those money to go to eat a pizza all together. If you are wondering how you can detect the author of each line of code, git blame is the answer.

3. Define the Style for the Technical Documentation

Every function should be preceded by a comment and Doxygen is a wonderful tool to collect all those comments and generate a document or a website for a quick reference.

Obviously not everything can be specified in a comment into source files. To write documents that can be easily managed by a VCS, I suggest Markdown and Multi-Markdown. The idea behind MD is to have an easy-to-write language to create HTML snippets that is also easy-to-read while MMD adds some features (such as tables) maintaining the same philosophy.

If you prefer a WYSIWYG editor, you can save your documents in odt format and use odt2txt in order to let Git show the differences between revisions; here is how to do (unfortunately this works only for diffing, merge is not allowed).

4. Chose a Decent Bug Tracker

Maybe now you are asking why is important to choose a BT before having written a single line of code. There are three main reasons:
  • first, you can use it also to assign development tasks,
  • second, soon there will be the need to change something in the original architecture; use the bug tracker host the discussions, and
  • third, don't let the Quality Assurance team choose for you ;-)
Speaking about bug tracking tools, I would like to tell you how much Redmine is great but unfortunately I've not (yet) had the opportunity to test it. In my company we're using Mantis and I can say that it's not so bad for medium-size projects.

Remember You Are Not Alone

All the above points are useless if they are not agreed by the development team. For this reason, rules should not be imposed from the top but discussed with everyone is involved in the project to make sure they understand the logic behind them.

It's important to keep an open mind in this phase because developers can suggest some improvement, based on their experience, to better adapt those rules to the specific project and the team.

OK, now you are ready for the kick start. Good luck!

Useful Git Commands: Blame

Blame! by PrinzKoks
How many times, looking a piece of shared code, have you thought "who the hell has written this?!?!" With other VCS all you can do is to scroll the list of changes made to that particular file and look at what is changed.

But Git provides you the blame command that eventually answers your question in a fast and easy way. And, most of the times, you will not like the answer.

You can see a whole file (or just some rows, with the flag -L) annotated with the author and the hash of the commit where each line has been added or changed. And you can also ignore changes in whitespaces with -w.

Sometimes it may be useful to detect if the same lines have been moved inside the file: the flag -M cover this requirement. But what if the lines have been moved from a file to another?

This is the purpose of the flag -C. If the move has been done in the same commit (typically during a refactoring session) the output shows also the file name where those rows originally were.

Check out the man page for all the other options.

Git Rulez

Every project developed by more than one person needs a versioning control system. And, in my opinion, it's a good idea to use a VCS for all non-trivial projects.

According to wikipedia:
Revision control, also known as version control and source control (and an aspect of software configuration management), is the management of changes to documents, computer programs, large web sites, and other collections of information.
In my developer life I've used three VCS:
  • CVS (Concurrent Version System)
  • Borland StarTeam
  • Git
And from the title of this post you should have understood that I believe the last is the best. It has a lot of features that help to manage big projects ran by hundreds of developers, since it was created by Linus Torvalds with the purpose to maintain the sources of the Linux kernel.

How It Works

Git is a distributed VCS, this means that when you clone a repository, you have the whole history and the all the branch tree in your PC. You can do your work offline on the repository and when you are done, push it to the remote repository. And it's not said that the remote repository you are pushing to is the main repository. It can be the repo of another developer that is working with you on a specific feature. In this way two or more persons can do their work without impacting the whole dev team.

Another difference with other VCS, is that Git does not track files but changes, even in different files. How many times your new features or bug fixes are made in a single file? Usually, adding a new feature means change several files; when you commit them, they remain together so it's easier to identify all the files changed and, if needed, revert the modification with just one command.

Moreover, this behavior lets you view an history of all the commits and lets you easily go in a well-known repository state even without having set a tag.

Branching

A Git book I've read says that books explaining other VCS talks of branching in the latest chapters. But in every Git book, you'll find branches treated within the first three or four chapters. Why this difference?

Simply because branching is a very powerful feature and in Git the creation a new branch is a very cheap operation. An with "cheap" I mean that there is no data duplication or hidden overhead. Simply two commits will have the same ancestor.

When you work with branches (in whatever VCS) a typical need is to do the same modification (for example an urgent bug fix) on different branches. Git provides the cherry-pick command to do exactly this: to replay a commit (i.e. the changes made to one or more files) in another branch.

Conclusions

This posts is only an overview of Git but I hope it's enough to make you understand how powerful this tool is. In the future I plan to write some posts about useful but almost unknown Git functions.