Git

Proper GIT commit messages

150 150 ioan.surariu

Whenever I contribute to an existing project I start off by reading the code repository history. It’s a way to understand the project evolution and how the code changed over time. Besides this it gives you an idea about how well the project is organized, which are the major bugs and bottlenecks etc. However, I could rarely find projects which maintain a clean history. The reasons are many, but one is that the commit messages are not properly formulated. In this article I’m going to exemplify my view about good commit messages in GIT.

One way to think about GIT commit messages is like fingerprints you leave on the code changes and they should be meaningful for someone who reads them after a year or more. The context it’s also important because it often happens to check how a particular class evolved over time and which were the commits which impacted that class. If it takes you more that a blink of an eye to understand it then this is a sign to reconsider the commit message. One good comparison is with traffic signs. If it takes more that a blink of an eye to understand the signs in a road-cross while you drive then the road designers should either simplify the signs or even change the road infrastructure. Otherwise the risk of accidents increases drastically.

Example of bad commit messages

fixed broken stuff
fixed broken stuff - part2

Well, it’s good you fixed something, but what exactly did you fix? The commit message should contains more details about what has been fixed. More, when we are in a hurry or lazy we don’t provide a new commit message in case we forgot something. We normally rely on IDE and use the same changelist with the same commit message for something we omitted previously.

Update API with 3345. Fix malformed request

Here it’s better. At least it seems there are more details. But what 3345 is? Did the API’s update fix a bug implicitly? Or are there two separate changes wrapped in a single commit? One with the API update and the other one with a fix for a some malformed request. But which request?

Proper GIT commit messages

I’ll stick with the examples above.

[FIX] Close server connection properly #788 [see details]

- close socket and return to the connection poll
- checks for null pointer exceptions
- unit tests for socket handlers

The commit message from above it’s more verbose and it offers a clear view about the changes. It’s not needed to be very technical to understand what the commit is all about. The first line states there is a fix for a bug related to server connectivity problem. At the end there is a reference to a GitHub issue (#788) and then it invites the reader to check for more details in case he wants to go deeper.

Those additional details are written on separate lines as a hyphen list. It’s actually the body of the commit message which is quite difficult to write with the -m option of git commit using the command line. You are better off writing the message into a text editor or your IDE.

It is commonly used to provide a GitHub or Jira ticket reference in case there is used such a platform for your project. Those references are automatically shortened and converted into links for easy navigation.

[IMPLEMENT] API support for image upload #3345

Now it’s clear that that the commit is about API extension to support images uploads. Similarly, it points to a reference (#3345) for more details about the feature. In this case there are no additional details, but this is perfectly fine. Notice that you could annotate the commit messages with something like [FIX], [IMPLEMENT], [FEATURE], [UPDATE] to make it clearer what is all about. There is no rule here, they work as tags and should be meaningful enough. You could pick whatever you want as long as they are widely adopted along the project and understood by everyone.

Use a linter. But be cautious

All I have written above are suggestions to make your code repository history more organized and clearer, but don’t get too obsessed with it. The point is to get better but not overcomplicate the development process. Try to discuss it before with your teammates or managers. In case they find it too cumbersome don’t insist. Try to improve your own commits messages and stick with that.

Some projects use tools to check the commit messages style before pushing them to the remote repository. Such tools could be relatively easy integrated with GIT or GitHub (see actions).

In general, these linters validate that your commits messages follow a predefined style, like:

  • the commit message title doesn’t exceed a max length
  • the title has no trailing whitespaces
  • second line is empty. Notice from my example above that there is a space between the title and commit message body
  • title doesn’t contains hard tab characters etc.

Multiple SSH keys for different remote GitHub servers on the same computer

150 150 ioan.surariu

You can use SSH protocol to connect and authenticate to remote GitHub servers. Using SSH keys you can authenticate to GitHub without providing your credentials every time you connect.

It’s common that you need to connect to different GitHub servers from the same computer simultaneously. It could be your personal account to github.com and the one from work, like work.github.com or any other remote GitHub server. Anyway, how to configure your SSH client to support this setup it’s not so straight forward. I’m describing below the steps to follow to accomplish this.

Generate a new SSH for your GitHub account

From Git Bash generate a new public/private RSA key using ssh-keygen as below. You need to provide the email address for your GitHub account.

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

When you’re prompted, enter a file name where you want to save the keys and a secure passphrase. Let’s say you generate a key for your personal GitHub account and name it id_rsa_personal. Public (id_rsa_personal.pub) and private (id_rsa_personal) keys are generated. Then upload them to your GitHub server.

More details about generating SSH keys and how to add new SSH key to your GitHub account here.

Add the new SSH keys to .ssh home folder

Copy your newly SSH keys to ~/.ssh folder. Assuming you generated a key for your personal account in GitHub and that you already have another one for your work account, you should have under ~/.ssh folder 4 files.

id_rsa_personal.pub
id_rsa_personal
id_rsa.pub
id_rsa

Create a SSH config file

If you don’t have it already create a ~/.ssh/config file and add the following to it. I still assume that you have 2 accounts, the personal one and the other for work. As shown below you need to provide the host addresses and usernames for your accounts. It is also important to specify the right SSH keys to be used for each account using IdentityFile property (highlighted below).

# Work account
Host work github.work.com
 HostName github.work.com
 IdentityFile ~/.ssh/id_rsa
 User work_user

# Personal account
Host personal github.com
 HostName github.com
 IdentityFile ~/.ssh/id_rsa_personal
 User personal_user

Check the connectivity and troubleshoot

In order to check the connectivity to your GitHub servers using SSH-RSA keys run the command below.

ssh -vT git@github.com

It runs in verbose mode just to provide you all the details in case you need to troubleshoot later. You need to specify the GitHub host, in my case github.com and git as username. Don’t use your GitHub account username, it won’t work. Just git as above.

If you get the message You've successfully authenticated, but GitHub does not provide shell access. then you’re all good. Your setup is correct and you could carry on to clone repositories or interact with your GitHub remotes using RSA keys.

In case the command returns git@github.com: Permission denied (publickey) then check once again your SSH config file and make sure the right RSA key is is used for your server.

OpenSSH_7.9p1, OpenSSL 1.1.1a  20 Nov 2018
debug1: Reading configuration data ~/.ssh/config
...
debug1: Host 'github.com' is known and matches the RSA host key.
debug1: Found key in ~/.ssh/known_hosts:4
debug1: rekey after 134217728 blocks
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: rekey after 134217728 blocks
...
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering public key: ~/.ssh/id_rsa_personal RSA SHA256:9lQpW+Fadq8+ORpWHFXsYJsD0p8r explicit
debug1: Server accepts key: ~/.ssh/id_rsa_personal RSA SHA256:9lQpW+Fadq8+ORpWHFXsYJsD0p8rv explicit
debug1: Authentication succeeded (publickey).
...
You've successfully authenticated, but GitHub does not provide shell access.
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 3488, received 2724 bytes, in 0.2 seconds
Bytes per second: sent 15908.8, received 12424.2
debug1: Exit status 1