Git offers a large variety of features from the basic to the mind-blowing ones. Yet we find many tweaks along the way that make the development process smoother and faster. In this matter I would like to share with you valuable knowledge I have gained since my first touch with Git.

Have you ever wondered how you can make Git fit your needs? Have you ever asked yourself how it would be to have Git at your fingertip and use it seamlessly? I’m not saying I’m giving this to you but at least I can show you the way towards Git mastery. For other cool micro-improvements to your programming flow, you can also check out our “Actionable tips” article.

Here is my guide to using Git the pro’s way. Please note that this is my own perspective and not all the approaches below may suit you. Try picking up the ones that answer your demands. I’ve previously written an article covering Git tips and tricks, so consider that your Git 101… and now let’s move to the big leagues.

We are going to cover the following:

  1. Setting up the environment
    1. Coping with typos
    2. Customised formats
  2. Preparing the commit
    1. Partially adding files
    2. Pre-commit hooks
  3. Finding a bug’s root cause
    1. Blame
    2. Bisect
  4. Undoing changes
    1. Commit changes
    2. Undoing… anything
  5. Aliases

Let’s start.

1. Setting up the environment


These are basically the first steps to take in order to tune your Git experience so that it will become quicker and sharper.

1.1 Coping with typos

Typos are always very annoying. Rewriting the entire command due to a typo has happened to me many times before. Moving the cursor back to only correct the mistyped word is quite cumbersome work. Anyway, it would be nice to have an auto correct feature, wouldn’t it?

Fortunately, Git has this built-in, we just need to turn it on!

Yes, you’ve just done the magic. Don’t believe me? Let’s try it:

How cool is that?

1.2 Customised formats

As you continuously work with Git, you may want to speed the process up, to make it prettier, more concise. By default, Git comes with oversized outputs for its commonly used commands like git status  and git log .

Let’s take a look at how the standard git status  command looks like:

We should rapidly learn how to stage, unstage or revert the changes for a file. Why not get rid of all those useless things, in order to have a better look at what really matters? And let’s also save some space:

Much better!

The git log  command output can be modified as well, according to your wishes. The subject is already covered in the previous Git Tips and Tricks article so you can take a quick look there in the “Log. Prettier format” section.

2. Preparing the commit


Let’s go further and see what tricks we can use when being about to commit the changes.

2.1 Partially adding files

You may have encountered this case: A bunch of files were changed, but you want those changes organised in several concise commits, rather than one big messy commit. Why split the changes into multiple commits? Well, not only will you make your life easier, but your code reviewing colleagues will also be charmed.

Interactive staging is a nice feature Git offers, helping you easily craft your commits to include partial file changes. If you run the  git add command with the  -i or  --interactive  option, you’ll go into an interactive shell mode:

While most of the commands are quite straightforward, I think we can use the example of  patch, which gives you the possibility to individually stage pieces of a file. This way, you can include one change to a certain commit and another change to a different one, even if the two changes have been made to the same file.

From the interactive prompt, you can type  5 or  p . Or you can use the  -p or  --patch option to accomplish the same thing:

There’s a lot of options at this point. By typing  ? you can see an explanation of each of those:

Most of the time you will use  y or  n to decide for a hunk, but sometimes splitting the current hunk into smaller ones or leaving the hunk undecided until later can also be helpful.

If you stage a hunk and let other(s) unstaged, you’ll see the file in both the staging area and the working tree. That’s because the file is only partially staged:

One more thing is worth mentioning here. If you use the  add -p command to an untracked file you will get the following:

However, if you first use  add -N or  add --intent-to-add, you can overcome that:

More than that, the patch mode can be used for partially resetting a file  git reset -p, checking it out git checkout -p or stashing it  git stash save -p. Did we mention how easy it is sometimes to use interactive consoles for everything but the kitchen sink?

2.2 Pre-commit hooks

It might have happened to you: You accidentally commited and pushed some debugging code. Even if it’s not something that necessarily causes trouble, it’s simply not recommended to have debugging code in production. What if a script would run every time you made a commit? A script which would tell you if you have any stray pieces of debugging code?

You’ve guessed it! Git offers you the possibility to execute a custom script at specific events. One of them is the pre-commit, when you can prevent the commit from happening if certain conditions are not met. In order to accomplish that, you need to create the file  pre-commit in your repository’s  .git/hoooks/ directory with the following content:

I must note that the above is not my original work, I took it from here and adapted it to my needs. I recommend you to try something similar: Start from a basic working version, then change it (over time), according to your own needs.

3. Finding a bug’s root cause


So you have a piece of code causing you trouble… Where is it? Who wrote it? Could it be Colonel Mustard, in the lounge, with the spanner? As much as we enjoy whodunits, we have much more effective tools in Git.

3.1 Blame

Git has a built-in tool that helps you blame the culprit of a bug. I’m joking. Even though you can find out who introduced a specific change, the commit hash is more important. Therefore, you have access to the context of the change. Let’s take a look:

So you find the commit hash, the author and the timestamp for each line of the specified file. What could happen, though, would be to get the wrong culprit. Maybe someone innocently removed whitespaces or simply moved the code around from other places. So does the real culprit get away? Of course not. We can use the following options to ignore whitespace changes

or to ignore moving text

or to ignore moving text into other files

Depending on the situation you can choose to use one of or combine them.

3.2 Bisect

We discussed above about finding the author of a specific change. At that point, we supposedly know where the bad code is. Now, let’s make it more interesting. We only know that a bug has been introduced, but nothing more. Don’t worry, Git will help us again, with one of its superpowers:  git bisect .

You specify a “good” commit, a “bad” one, then Git takes care of the rest. Well, almost. Git runs a binary search within the commit range delimited by the good and the bad commit. The only thing you need to do is to tell Git if the currently presented commit is good or bad. The process continues until the range is narrowed to a single commit, the one introducing the bug. It’s that easy and it looks like this:

Don’t forget to initially specify both the good and the bad commits, otherwise Git can’t help you out.

4. Undoing changes


Here at Algotech Solutions, we’ve seen a lot of projects. Inevitably, during the lifecycle of a project, there are cases when changes have to be reverted. Whether you need to revert changes that a certain commit has introduced or more complex ones like a faulty rebasing, there is always a way to get out.

4.1 Commit changes

You can undo commit changes in several ways using:

  • A “safe” revert that creates a new commit containing the reverted changes:
  • A checkout specifying the version that a certain file will be brought to:
  • An interactive rebasing where you are able to remove unnecessary commits:
  • A hard reset that removes all the commits applied on top of a specified one:
Depending on your need, you may use one of the above to revert unwanted changes. More details can be found in the Git Tips and Tricks article, in the “Revert. Undo commit changes” section.

4.2 Undoing anything

The git reflog  command comes to get you out of trouble by reverting all kinds of harmful operations. Most of the times, these are faulty rebases or a branch deletions. You can basically go back in time at any moment during your Git operations history. First let’s see how the history looks like:

Now all you have to do is to run a checkout in order to move to the desired state of the source code. Further details can be found in Git Tips and Tricks article, “Reflog. Revert operations” section.

5. Aliases


One other tip that is worth mentioning is using aliases for no other reason than writing less. A simple example for a commonly used command is having an alias git co  for the command git checkout . For more details about how to set up Git aliases and not only please check our dotaliases repository on GitHub.

Conclusion


There is no such thing as doing it the right way. We all have our own needs and preferences. But at least we can try to help each other out by sharing our knowledge. This is what I’ve done here, by presenting my way of dealing with Git issues. I hope you enjoyed.

If you enjoyed this article please take a moment and share it with your friends: