A fix for Gitlab squash commit message composition

06.07.2021
Martin Friedel
gitlab

Bitbucket has it, GitHub has it. You are merging a pull request / merge request that consists of several commits and want to squash them. Often you want to have access to all the messages from all the commits to assemble into a decent commit message for the squashed version.

If you use automated semantic versioning it is essential to do this, because it generates a new version number for your project based on the commit messages. You prefix what happened in the commits with a standard set of terms like "feat:" for a feature or "fix:" for guess what. The algorithm can then determine, which digits in the version number have to be increased, depending on what the commit contained. In many projects we like to work this way, so this squash message assembly is very important to our process.

But GitLab does not have this feature, so you only get a drop down to choose one of the existing ones. The issue has been open since January 2019, but still unresolved Issue 26303

So what to do?

A bookmarklet to the rescue

If you are not familiar, in the early Netscape versions Brendan Eich added a URL handler javascript: to mean that instead of being a URL for a link, the text after the colon should be executed as JavaScript. This was used inside of links sometimes, but for our purpose the important fact is that you can use it in a bookmark. This is called a bookmarklet, a portmanteau of bookmark and applet I guess. This has been around for decades, but still works.

Simply create a new bookmark, call it something like "Gitlab: assemble squashed commit message" and paste the following code into the URL field of the bookmark:

javascript:(function() {$(".merge-request-tabs-container a")[1].click();setTimeout(() => { $(".tab-pane.commits .text-expander").click(); setTimeout(() => { let all = ""; $(".commits-row .content-list li .commit-detail .commit-content").each( (i, n) => { all += $(n).find(".item-title").text() + "\n"+$(n).find(".commit-row-description").text() }); $(".merge-request-tabs-container a")[0].click(); setTimeout(() => {$(".modify-message-button").click();setTimeout(() => {$("#squash-message-edit").val(all)}, 200)}, 200)}, 200)}, 200)})()

Save the bookmark and go to the merge request you want to squash the commits in. Stay on the overview, leave it all as it is and click on your bookmark. A few things will happen quickly, then you should be back on the overview and your commit message should contain all the combined messages for you to look through and clean up.

This is by no means brilliant code, it simply gets done, what we need. It switches over to the tab with the commit list, collects all the commit messages into a variable and switches back to the overview and pastes the result for you. The way it is built, it might break and have to be adapted, because it relies on class names inside the GitLab HTML which could change with newer versions. We will try to update this page if it breaks at some point.

This was tested with GitLab 13.11.3 on Chrome and Firefox and was working.