Git: 5 useful pills

Hi everybody! I know that Git at first looks like a mighty beast to tame, but once you grasp the basic concept it could eventually become your numer #1 ally. I am going to show you some advices that I wish I had at the beginning of my dev journey, but that no one has ever told me.

For the ones who does not know what it is, that’s a distributed versioning tool that was made by Linus Torvalds in 2005. The name comes from the american slang, and it means…Well…Check it out. The original idea was to create a simple tool to ease the Linux Kernel development.

How to install Git? Well, if you are using Linux it is really easy:

sudo apt-get install git

Otherwise, if you are using Windows, you have to install Git for Windows. Simple as that.

This is not a quick start guide or a tutorial, just a bunch of pills for the ones who already know how to use it. But let’s start.

#1: Create your shortcuts to reduce typing

That might sound trivial, but it’s not. When you are developing and you are using Git, you will type a lot. The less you type, the faster you accomplish your tasks.

I like to use the following shortcuts:

  • co: checkout
  • ci: commit
  • br: branch
  • st: status
  • l: log
  • rh: reset hard, erase the word you made since the last committed word
  • last: show the last commit

Open your terminal or prompt, and cut and paste the following:

git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.st status
git config --global alias.l log
git config --global alias.rh "reset --hard"
git config --global alias.last "log -1 HEAD"

#2: How to use merge properly

Git Flow is a widely used workflow that allows you to add some constraints to your Git projects. Here you can find a very nice guide.

One thing that might happen is that you mess up merging your branches, in a way that when you show graphically your branches (for example using Git tool integrated in PyCharm) things are all messed up.

A simple yet powerful advice is the following: keep your branches separated even when they are gone! This keeps everything well organized and easy to read. I find it useful even when me and my coworkers did a series of unfortunate commits, to find the “right spot” to rollback.

How to do that? Use the --no-ff option while merging. For example, if you are merging yourbranch to develop, use the following:

git co develop
git merge --no-ff yourbranch

There are different opinions about this, everyone has its own approach, anyway in my opinion this is the cleanest way to work.

#3: Learn to use reset –hard

Again, this could looks a bit trivial, but a lot of times I meet people asking me how to throw away all the uncommitted work. This is easy as that:

git reset --hard

Be careful! This literally throws away your work! If you used that command and you realize that you should not have done that, I have bad news for you…Your work is gone forever.

#4: Using rebase interactive

There is a whole new world behind that command, so we won’t show all options and details about it! This could require a whole series of posts itself. The idea is that it allows you to rewrite the history. Cool, isn’t it?

Every time you think to edit something in the past, your mind should immediately go to rebase interactive. The most common scenario is that you are working on your un-pushed branch with a lot of commits, but before pushing them to the remote server (thus writing them on the rock!) you want to do some house keeping. That is a good practise, and I wil show you how to do it.

First of all, be sure to switch to your branch, that now we will call it yourbranch:

git co yourbranch

Then, you can use the following command to edit your last commits. You have to specify how many of the latest commits you are going to edit, starting from the HEAD (that is the last one). In this case, consider only the last three commits.

Please notice an important thing: that will not work if you have some merge commits of some commits of another branch into the range you will specify! If you see more rows than the one you specified in your range, you probably are in this situation.

git rebase -i HEAD~3

After that, will open up a screen showing you the last three commits and some information below. Use the vim syntax to navigate. You can do several things replacing the default pick keyword, that just leaves the commit as it is without touching it, with one of the following:

  • f: or fixup, you delete the commit message but the word is put inside the upper commit message.
  • s: or squash, it’s like fixup but after git will open up a new window telling you to specify the new commit message.
  • r: or reword, will only edit the commit message without touching your work. After you have done with that screen, will open up a new window telling you to specify the new commit message.
  • d: or drop, will drop the commit and the associated work as well.

Please note that there are other keywords, but these are the ones you will have to use the most. You can do much more things with rebase! For example, swapping rows you can swap commits order. In order to do that, be careful to swap “atomically created” commits.

After saving this file with :wq! and editing the eventual other screens that might open up (if you have done squash or reword, for example), you can check your logs and then push to the remote.

git push

If you already had pushed this will show you an error, so you must rewrite the remote history. Be 100% sure about what you are doing, this is really dangerous!

git push -f

#5: Resolve merge conflicts

You are not working alone. You and your coworker started your own branches from develop, working on different features. But then, your coworkers merge his branch with develop before you. When it’s your turn, you checkout to develop git co develop and you perform your git merge --no-ff yourbranch, but the terminal will notice you that you have some conflicts (damn it!). How you can solve this situation in the correct way without messing things up?

Before watching the solution, let’s think about why this is happening! Git is super useful as it usually takes care autonomously of edits coming from different lines (such a good guy!). For example, if you and your coworkers did an edit of the README.md, but you edit line #1 and your coworker let’s say line #5, Git automatically knows it and solves for you the issue. The problem is when you and your coworkers did an edit on line #1. How can Git automatically give the priority to you or your coworker? It cannot. This is when a conflict shows up.

Luckily, Git provides us all the tools we need to solve this situation. If that happens to you, start solving the issue with:

git mergetool

It might look intimidating at first, but it’s easier than you think. It will open up three side-by-side views of the same file (the one with conflicts, and does that for each file that has a conflict!), so after running git mergetool you will find three columns:

  1. Left column, there is your version of the code, or the local one you are merging.
  2. Middle column, there is the original code, before anyone modified it (neither you or your coworker).
  3. Right column, there is the remote version, that is the edit that your coworker did.

Now it’s up to you ti decide what to do. In the center column you will find all the conflicts, and they are reported using <<<<<<<, ======= or >>>>>>> . So you want to find into your middle column all the occurrences of ======= to solve your conflicts. Let’s see an example.

Left screen (hello_world.py):

print('Hello')
print('Left')
print('World')

Right screen (hello_world.py):

print('Hello')
print('Right')
print('World')
print('!')

Middle screen (hello_world.py):

print('Hello')
<<<<<<<
print('Left')
=======
print('Right')
>>>>>>>
print('World')
print('!')

This is telling you that there was a conflict, and tells you “graphically” that the code between <<<<<<< and ======= comes from the left version, while the code between ======= and >>>>>>> comes from the right version.

Now you can solve the conflict deleting those placeholders and leaving only the version that you want to keep in the final version (the decision is yours!).

For example, the middle column might end up looking like the following if you decided to keep the left version of the conflict part:

print('Hello')
print('Left')
print('World')
print('!')

Or like the following, if you decided to keep the right version of the conflict part:

print('Hello')
print('Right')
print('World')
print('!')

Once you have done solving the conflicts, save the files, exit the editor. Now checking the status you will hopefully see that all conflicts are gone, so you have to add files, create the merge commit, and push it:

git st
git add .
git commit -am "Merge branch 'yourbranch' into 'develop'"
git push

And remember: when things get critical…

Funny joke by xkcd about git versioning system
An awesome comics about Git, made by xkcd

Conclusions

I think that you already knew some pills, but I hope that you learned something new reading this blog post. I hope you enjoyed, please write in the comments if you want to share some tricks with us.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Website Built with WordPress.com.

Up ↑

%d bloggers like this: