Signing Git Commits

What does it mean to sign a Git commit and why would you like to do that?

From Latin, signāre, or putting a mark.

As the word itself says, signing, putting a mark, ensures that the commit you made and the code contained can’t be tempered.
Git is cryptographically secure, but it’s not foolproof. In order to ensure the repository integrity, Git can sign tags and commits with a GPG key.

In this post, I’ll show you how to set up all of the necessary toolings in order to be able to sign your git commits. Aside from having the latest version of Git installed, you’ll need also the GnuPG. So let’s start.

GPG Introduction

GnuPG, also known as GPG, is a complete and free implementation of the OpenPGP standard. All of the details about OpenPGP are defined in RFC4880 (also known as PGP).
First of all, you need to download GPG, configure it and create/add your personal key.
On the following address https://www.gnupg.org/download/index.html and under “GnuPG binary releases” under windows section choose “Simple installer for the current GnuPG” and download the installer.

When downloaded, please install the application. The installation procedure is a simple one as no particular options are available.
Once installed you are ready to create a new key, which is the fundamental thing in getting to sign our commit.

In command prompt issue the following command gpg --full-generate-key At this point, you will be asked several questions you will need to answer before your key is going to be created. Check the following example:

At the end of the process you will be asked, in a pop-up window, for a password that needs to be assigned to this key, please provide one.

Once the key is created you need to let Git know about it. First issue the following command gpg --list-secret-keys --keyid-format LONG which will list the necessary information about the newly created key. You should see something like this.

Now copy the value that is highlighted in red (key id) and issue the following command git config --global user.signingkey 0F5CBDB9F0C9D2D3 (where 0F5CBDB9F0C9D2D3 is your key id).

This is necessary so that Git knows what key it should use in order to sign your commits.

However, we are still not ready to go and sign our first commit. What we are missing is to set the `gpg.program` setting in our global git config. To do so we first need to retrieve the path of our gpg executable. The easiest way to do so is to run the where gpg command. It will return you the path on where gpg was installed. Now we can set the configuration by running the git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe" command (obviously in case your path differs from this one, you should adjust it).

Also, before proceeding make sure that the git user.name and user.email are set. In case this was not yet initialized try with, git config --global user.name "Mario Majcica" and git config --global user.email your@yemail.com.

Now we are ready to sign our first commit. Initialize a new git repository, add a file and run git commit -S -m "signed commit". At this point you should be prompted for the password of your key, the one you have chosen during the creation of the key itself:

Once you enter your password, your commit will be made and it is going to be signed, e.g.

Let’s now verify that are signature is there. In order to achieve that issue the following command git log --show-signature -1 or a in a more kind of overview printout git log --pretty="format:%h %G? %aN %s".

You can learn more about Git and the available command regard signing commits here https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work.

Export/Import

Next step is to export our key. Why would we do that? Well, an example, so that you can import it on another machine of yours, or import it to services like Github who can then validate your signature.

Let’s first export our public key. To do so, use the following command: gpg --export -a 0F5CBDB9F0C9D2D3> publicKey.asc
Obviously, 0F5CBDB9F0C9D2D3 is my key id in this case, sobstitute this value with your key id.
This command will create a file called publicKey.asc in the current folder of yours. Edit this file with a text editor of choice. The content of it will be necessary information for your Github account. Now open your Github.com page and log in. Under the settings, you will find a menu called “SSH and GPG keys”. Open this menu then choose “New GPG Key”:

Now, copy the content of publicKey.asc and paste it in the page on GitHub, then just click “Add GPG Key”.
Once done, you should see your new key listed in the GitHub page “SSH and GPG keys” under the GPG Keys. I’ll now edit one of the projects in GitHub and push a signed commit. As you can see, it is now listed that the commit is verified.

In case you click on the Verified icon you will be able to see the details about the signature:

Before we move to the import part, let me show you a trick on how to automate this in a popular IDE, Visual Studio Code.
Now that we are all set up, we can instruct Visual Studio Code, to sign the commits that are made from the IDE. To do that, open the settings page in Visual Studio Code

then search for ‘git signing’ and the relevant setting should be listed:

The setting in question is ‘Enable Commit Signing’. Check it, then make a new commit. List your commit log and you’ll see that now also the commits made directly from Visual Studio Code are now signed.

However, the export doesn’t end here. We need to export the private key in order to be able to import it and use it on another machine. To do so run the following command, gpg --export-secret-keys -a 0F5CBDB9F0C9D2D3 > privateKey.asc (where 0F5CBDB9F0C9D2D3 should be your key id). Store this file carefully and do not expose it to the public. It is protected by the password, still, however, in this case, the password itself becomes the weak link.

It is now time to import it. For that, it is sufficient to issue the following command gpg --import privateKey.asc. You do not need to import the public key, the private key always contains the public key. One last thing, if imported on another machine, you need to indicate the level of trust towards the newly imported key. You can easily achieve that with the command gpg --edit-key 0F5CBDB9F0C9D2D3 trust quit where 0F5CBDB9F0C9D2D3 is again the key id of the key on that machine. After you issue the command you will see the following screen:

and at this stage, you will be asked for a decision. Hit 5 to indicate you trust ultimately the given key and your job is done.
If the key already existed on the new machine, the import will fail to say ‘Key already known’. You will have to delete both the private and public key first (gpg –delete-keys and gpg –delete-secret-keys).

Conslusion

Aside from the commits, you can also sign tags. If you are not familiar with public key cryptography, check this video on YouTube, it is one of the simplest explanations that I heard.
Some of the useful commands in our case:
gpg --list-keys and gpg --list-secret-keys, both will list your keys, public and private ones and the trust state.
git config --list --show-origin will show you all of the git settings so that you can check if the necessary is already set.

To configure your Git client to sign commits by default for a local repository, in Git versions 2.0.0 and above, run git config commit.gpgsign true. To sign all commits by default in any local repository on your computer, run git config --global commit.gpgsign true.

To store your GPG key passphrase so you don’t have to enter it every time you sign a commit, I recommend using Gpg4win.

That’s all folks, don’t forget to sign your work!

Using Git with self-signed certificate at the user level

Introduction

Some time ago I wrote about Installing self-signed certificates into Git cert store.
With the advent of Visual Studio 2017 and updates of the Git client I noticed the limitation of this approach. Also, updates of Visual Studio brought updates to a git client and after each update, my self signed certificate was gone. As this fact annoyed me quite a bit, I looked for a better approach.

A better approach

In order to solve this issue, I needed to move my certificate authority file to a place where it will not be rewritten by installing a new version of Git client. I went moving it to my users directory, which on my PC equals to C:\Users\majcicam. So after adding my self signed certificate into ca-bundle.crt file that is located, again, in my case at C:\Program Files\Git\mingw64\ssl\certs, I moved it to the C:\Users\majcicam. You can read more about adding your self signed certificate into the ca-cert file in my previous post at Installing self-signed certificates into Git cert store.

After I moved my file, I needed to indicate to the Git client that he should use this file to verify certificates. This can be done by issuing the following command:

git config --global http.sslCAInfo C:/Users/majcicam/ca-bundle.crt

This command will add the new path into a Git global config file which is a place where all of the user wide settings are stored and it is not subjective to the installation of Git or a particular repository.

Note that I used a slashes in the path instead of back-slashes.

This means that now we can update our Git client and that these settings will be maintained. As a standard on Windows platform, it is located in your user folder, in my case the global config file is at C:/Users/majcicam/.gitconfig. You can verify the values of all the Git config files and their location by issuing the following command:

git config --list --show-origin

This simple trick should make your lazy developer life a bit easier.

Happy coding

Working with TFS in IntelliJ IDEA via VSTS Plugin

Recently Microsoft released a plugin for JetBrains IntelliJ IDEA in order to integrate this IDE with VSTS and TFS. Although Microsoft did a good job describing on how this plugin should be installed and described some basic settings, there are many non covered questions by the documentation provided. This is especially true when it comes to TFS and HTTPS. I will show you what is necessary in order to setup a connection for both Git and TFVC repositories on TFS.

Installing the plugin

In order to install the plugin, in the main screen of IDEA, choose Plugins from Configure menu:

2016-12-23-08_29_00

Once the plugin window opens, choose Browse repositories

2016-12-23-08_31_45-plugins

In browse repositories search for Visual Studio

2016-12-23-08_32_32-browse-repositories

If the Visual Studio Team Services plugin is not found, your connection may not be setup correctly. In case you are, as I am, behind a proxy, you need to click on HTTP Proxy settings button in the same screen (bottom left) and you will be presented with the following dialog

2016-12-23-08_30_10-http-proxy

Here you need to setup the necessary parameters (Auto detect proxy settings worked for me) and test your connection by clicking on Check connection button. Once done you will be prompted to enter an address that is behind the proxy so that internet connection can be verified. I used http://www.google.com/ for my test.

2016-12-23-08_30_38-check-proxy-settings

After confirming, you should see the following message

2016-12-23-08_30_48-check-proxy-settings

Now, back to Browse repositories screen, the Visual Studio Team Services plugin now should be found. Click on install and after the procedure finishes you will be asked to restart IntelliJ IDEA. Do so, restart the IDE.

2016-12-23-08_33_59-platform-and-plugin-updates

The plugin is now installed. In case this is not sufficiently clear, you can also follow the Microsoft guide Visual Studio Team Services Plugin for IntelliJ IDEA and Android Studio.

Be also sure that you have at least version v1.111.0 installed as I encountered issues with TFVC and previous versions of the plugin.

Importing the certificate

In case you are not accessing TFS through SSL connection you can skip this part. For Visual Studio Team Services plugin to connect to the TFS via https, that is using a self-signed certificate, no matter if you do intend using Git or TFVC, you need to import the certificate in the IntelliJ IDEA certificate store. To do so, export your certificate in the Base-64 encoded X.509 format. You can read about this in one of mine previous posts, Installing self-signed certificates into Git cert store.
Once you exported your certificate and let’s say saved it in C:\temp folder under the name tfs.cer, you need to open the command prompt and position yourself under the folder containing keytool.exe application. You can find it in the IntelliJ IDEA install folder, which in my case is C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.3.1\jre\jre\bin.

Once there you will then execute the following command

keytool -keystore "C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.3.1\jre\jre\lib\security\cacerts" -importcert -alias TFS -file "C:\temp\tfs.cer"

You will be then prompted for the keystore password. If you haven’t changed it, the default password is

changeit

After typing the password you will see the details about the certificate you are trying to import, and again you will be prompted to confirm that you trust this certificate. Type yes and you are done. Your screen should look like this

2016-12-27-11_16_12-administrator_-c__windows_system32_cmd-exe

Visual Studio Team Services plugin and Git

Before we even start, we need to be sure that a Git client is installed on our machine. From the Welcome screen choose Configure then Settings.

2016-12-29-15_08_58

In the settings window move to Version control -> Git pane and test the path to your Git client

2016-12-27-10_17_37-default-settings

In case all is good you should get back the version of your Git client

2016-12-29-15_09_41-git-executed-successfully

If this is not the case, or the path is wrong (change it and try again) or the Git client is not present on your machine. You can install Git for windows and you will find the necessary here.

In case you are using the https connection with TFS and it is based on a self-signed certificate do not forget to add that certificate into the Git cert store. This is something different then adding it to the Java cert store that I described in the previous chapter. You will need to do both of these steps. As I already described this procedure in detail, you can follow my other blog post Installing self-signed certificates into Git cert store.

Once the Git client is installed and certificate is imported, we can continue setting up the Visual Studio Team Services plugin. Get back to the welcome scree of IntelliJ IDEA and in the version control drop down choose Team Services Git

2016-12-23-08_34_54-welcome-to-intellij-idea

At this point a new dialog will be presented to you.

2016-12-27-11_05_09-checkout-from-team-services

Move to the Team Foundation Server tab and specify the address of your TFS server, then click connect. You will now be prompted for the credentials and if everything is ok, you will be show the list of available repositories

2016-12-27-11_18_08-checkout-from-team-services

You are now able to clone the repository of your choice and start working with it directly from IntelliJ IDEA.

Visual Studio Team Services plugin and TFVC

Before starting with TFVC, as for Git, we need an external tool. The tool in question is TF command line tool. It ships with the Microsoft Team Explorer Everywhere 2015 and you can download it here.
The file we are interested in is TEE-CLC-14.0.3.zip. Download it and unzip it in a folder of your choice. You should end up with something similar to this.

2016-12-27-12_15_39-tee-clc-14-0-3

Now, open the command prompt, move into the folder where you have extracted the TF command line tool and run the following:

tf eula /accept

If command succeeded and you haven’t received any error, you are good to go.

2017-01-02-09_01_28-administrator_-c__windows_system32_cmd-exe

Now back to IDEA. Open the settings panel.

2016-12-29-15_08_58

and move to Version Control -> TFVC pane. In the select path to executable field, enter the exact path to the tf.cmd command file located in TF command line tool folder.

2016-12-29-16_09_38-default-settings

Once done, press the test button and you should see the following message

2016-12-27-12_29_32-tfvc-command-line

Confirm all of the open windows and get back to the IDEA welcome page. Now you are ready to choose Team Services TFVC (Preview) version control.

2017-01-02-08_58_59-welcome-to-intellij-idea

At this point, same as for Git, you will be prompted about the connection towards your TFS. The following dialog will be shown.

2016-12-27-11_05_09-checkout-from-team-services

Move to the Team Foundation Server tab and specify the address of your TFS server, then click connect. You will now be prompted for the credentials and if everything is ok, you will be shown the list of available TFVC repositories.

2016-12-27-13_18_30-checkout-from-team-services

You can now create a new workspace directly from IDEA and start working with your TFVC repositories.

Troubleshooting

There are a couple of common issues you may encounter in following what I just described. I will tell you about the most common ones and how to overcome those.

In case you see the message in the following screenshot

2016-12-27-11_05_28-checkout-from-team-services

You are probably facing some issues with the certificate. Make sure that you exported/imported the certificate correctly.

During the test of the TF command line utility, you may encounter the following exception

2016-12-27-12_28_41-tfvc-command-line

In may case it turned out to be a problem with allocating the heap memory from TF process. I could clearly see in the log file the following:

2016-12-22 13:14:08,949 [ 17642] INFO - ugin.external.commands.Command - 167680800(ns) - elapsed time for add -noprompt -?
2016-12-22 13:15:46,592 [ 115285] INFO - lugin.external.ToolRunnerCache - getRunningToolRunner: toolLocation={0}
2016-12-22 13:15:46,592 [ 115285] INFO - lugin.external.ToolRunnerCache - getRunningToolRunner: slow version - null
2016-12-22 13:15:46,592 [ 115285] INFO - alm.plugin.external.ToolRunner - ToolRunner.start: toolLocation = C:\Utils\TEE-CLC-14.0.3\tf.cmd
2016-12-22 13:15:46,592 [ 115285] INFO - alm.plugin.external.ToolRunner - ToolRunner.start: workingDirectory = null
2016-12-22 13:15:46,592 [ 115285] INFO - alm.plugin.external.ToolRunner - arguments: add -noprompt -?
2016-12-22 13:15:46,716 [ 115409] INFO - ugin.external.commands.Command - CMD: Error occurred during initialization of VM
2016-12-22 13:15:46,717 [ 115410] INFO - ugin.external.commands.Command - CMD: Could not reserve enough space for 2097152KB object heap
2016-12-22 13:15:46,731 [ 115424] WARN - ugin.external.commands.Command - CMD: parsing output failed
com.microsoft.alm.plugin.external.exceptions.ToolBadExitCodeException: KEY_TF_BAD_EXIT_CODE
at com.microsoft.alm.plugin.external.tools.TfTool.throwBadExitCode(TfTool.java:109)
at com.microsoft.alm.plugin.external.commands.Command$1.completed(Command.java:155)
at com.microsoft.alm.plugin.external.ToolRunner$ListenerProxy.completed(ToolRunner.java:289)
at com.microsoft.alm.plugin.external.ToolRunner$ProcessWaiter.run(ToolRunner.java:327)

A workaround for this issue is to modify the tf.cmd file by specifying a lower -Xmx parameter. By default it is set to 2014MB however a 1024MB also worked well for me.

Another issue with this version of Visual Studio Team Services plugin is in changing in between the Team Services TFVC (Preview) and Team Services Git, or viceversa. You can read more about it here, TfsAuthenticator hangs the IDE.

No matter the issue, you can always find more information about it in the log file. The log file is located in my case in C:\Users\majcicam\.IdeaIC2016.3\system\log. Adapt this path to your case. The log file name is idea.log.
Visual Studio Team Services Plugin settings can be found in vsts_settings.xml file under C:\Users\majcicam\.IdeaIC2016.3\config\options folder.

Useful links

On visualstudio.com you can read more about this topic and see some useful how-to video.

  1. Installing Visual Studio Team Services Plugin for IntelliJ IDEA and Android Studio
  2. Using Visual Studio Team Services Plugin for IntelliJ

With all of these information I do hope you can get on going with the plugin and boost your productivity.

Happy coding.