This article is written by Ferdinando Santacroce, author of the book, Git Essentials.
(For more resources related to this topic, see here.)
Git is a powerful tool. In case you need to retain multiple versions of files—even if you may not be a software developer—Git can perform this task easily. As a Git user, in my humble career, I have never found a dead-end street—a circumstance where I had to give up because of a lack of solutions. Git always offers a wide range of alternatives even when you make a mistake; you can use either git revert to revert your change, or git reset if there is no need to preserve the previous commit.
Another key strength of Git is its ability to let your project grow and take different ways when needed. Git branching is a killer feature of this tool. Every versioning system is able to manage branches. However in Git, using this feature is a pleasure; it is super-fast (it does all the work locally), and it does not require a great amount of space. For those who are used to work with other versioning systems such as Subversion, this probably makes a difference.
In my career as a developer, I have assisted in situations where developers wouldn’t create new branches for new features, because branching was a time-consuming process. Their versioning system, on large repositories, required 5-6 minutes to create a new branch.
Git usually doesn’t concede alibis. The git branch command and the consecutive git merge operations are fast and very reliable. Even when you commit, git commit doesn’t allow you to store a new commit without a message to protect you from our laziness and grow a talking repository with a clear history and not a mute one. However, Git can’t perform miracles. So, to get the most out of it, we need a little discipline. This discipline distinguishes an apprentice from a good craftsman.
One of the most difficult things in software development is with regard to the sharing of a common code base. Often, programmers are solitary people who love instructions that are typed in their preferred editor, which helps them make working software without any hassles. However, in professional software development, you usually deal with big projects that require more than a single developer at a time; everyone contributes their own code. At this point, if you don’t have an effective tool to share code like Git and a little bit of discipline, you can easily screw up.
When I talk about discipline, I talk about two main concepts—writing good commits and using the right workflow. Let’s start with the first point. What is a good commit? What makes a commit either good or bad? Well, you will come across highly opinionated answers to this question. So here, I will provide mine.
First of all, good commits are those commits that do not mix apples and oranges; when you commit something, you have to focus on resolving one problem at a time (fix a bug and implement a new feature or make a clear step forward towards the final target) without modifying anything that is not strictly related to the task you are working on. While writing some code, especially when you have to refactor or modify the existing code, you may too often fall into the temptation to fix here and there some other things. This is just your nature, I know. Developers hate ugly code, even though they often are the ones who wrote it some time ago; they can’t leave it there even for a minute. It’s a compulsive reaction. So, in a matter of a few minutes, you end up with a ton of modified files with dozens of cross-modifications that are quite difficult to comment in a commit message. They are also hard to merge and quite impossible to cherry-pick, if necessary.
So, one of the first things that you have to learn is to make consistent commits. It has to became a habit, and we all know that habits are hard to grow and hard to break. There are some simple tricks that have helped me become a better committer day by day (yes, I’m still far from becoming a good committer).
One of the most effective tricks that you can use to make consistent commits is to have a pencil and a paper with you; when you find something wrong with your code that is not related to what you are working on at the moment, pick up the pencil and write down a note on a piece of paper. Don’t work on it immediately. However, remind yourself that there is something that you have to fix in the next commit.
In the same manner, when you feel that the feature you’re going to implement either is too wide for a single commit, or requires more than a bunch of hours to terminate (I tend to avoid long coding sessions), make an effort and try to split the work in two or three parts, writing down these steps on the paper. Thus, you are unconsciously wrapping up your next commits.
Another way to avoid a loss of focus is to write the commit message before you start coding. This may sound a little weird, but having the target of your actual work in front of your eyes helps a lot.
If you practice Test Driver Development (TDD), or even better, Behavior Drive Development (BDD), you probably already know that they have a huge side-effect despite their main testing purpose—they force you to look at the final results, maintaining the focus on what the code has to do, and not the implementation details. Writing preemptive commit messages is the same thing. When the target of your commit is clear and you can keep an eye on it every time you look at your paper notebook, then you know that you can code peacefully because you will not go off the rails.
Now that we have a clear vision of what makes a good commit, let’s move your attention to good workflows. Generally speaking, the sharing of a common way to work is the most taken-for-granted advice that you can give. However, it often represents exactly the biggest problem when you look at underperforming firms.
Having a versioning workflow that is decided with the help of common agreement is the most important thing about a development team (even for a team of one) because it lets you feel comfortable even in case of emergency. When I talk about emergencies, I talk about common hitches for a software developer—urgently fixing a bug on a specific software version, developing different features in parallel, and building beta or testing versions to let testers and users give you feedback.
There are plenty of good Git workflows out there. You can take inspiration from them. You can use a workflow as it is, or you can take some inspiration and adapt it to fit your project peculiarities. However, the important thing is that you have to keep on using it not only to be consistent (don’t cheat!), but also to adapt it when premises change. Don’t blindly follow a workflow if you don’t feel comfortable with it, and don’t even try to use the same workflow every time. There are good workflows for web projects where there’s usually no need to keep multiple versions of the same software and the ones that fit desktop applications better, where multiple versions are the order of the day. Every kind of project needs its perfectly tailored workflow.
The last thing I wish to suggest to the developers interested in Git is to share common sense. Good developers share coding standards, and a good team has to share the same committing policy and the same workflow. Lone cowboys and outlaws represent a problem even in software development, and not just in Spaghetti Western movies.
Resources for Article:
- Configuration [article]
- Maintaining Your GitLab Instance [article]
- Searching and Resolving Conflicts [article]