Vscode: Git commit message templates

Created on 17 Jun 2016  路  26Comments  路  Source: microsoft/vscode

The primary goal is to have awesome git messages through the power of templates + snippets.

We were looking to use git's commit templates for better git commit messages, similar to Angular's conventions. But we also love the super easy git integration directly in vs code.

We'd like to somehow combine the two. Currently, we can use our git commit template via the following steps:

  1. Stage the files in the git window using ctrl+shift+G and then the mouse (less than ideal, but that's a separate issue).
  2. Open up a command line quick-like with ctrl+shift+C and type git commit, which brings up the git commit msg editor.

According to #3876, we could conceivably set up vscode to be the default git commit editor when typing the git commit, but that still seems klunky - not to mention the fact that gitmode isn't available to install. I was thinking of giving a vscode extension a go which would allow for snippets within the git commit message. But perhaps there is a better solution that we're not seeing.

So...

  • Is there already a good solution for this that we're not finding?
  • If we make an extension, would we have access to the git message editor to use snippets and to read the default git message template?
  • If we make an extension, would it be possible to use the primary text editors of vs code?
feature-request git

Most helpful comment

VS Code version 1.17.0

You can achieve the same behaviour of opening a text file and entering whatever you want (and provably using local templates, didn't try that yet) to commit changes by setting VS Code as your default git editor.

git config --global core.editor "code --wait"

The --wait flag is now improved, allowing to terminate the calling process when the tab opened by git is closed.

PD: 'Code' command must be in your path

All 26 comments

Unfortunately there is no API around the git view, especially the message editor.

Thanks @joaomoreno. I was afraid that was the case (hence the question). Well, instead of an extension (unless someone can think of a different workflow), I guess I'll dive into trying to build vscode from source and look into at least implementing the template. Seems like it would be as straight-forward of a contribution as possible: hook the load event, load any existing message, if none, try loading the template file listed in .gitconfig. Worst case is I learn more about vscode's internals.

So I've got the code up and going, and I've had an initial grok of the overall code. Whew! 8-O

Here's a naive screenshot from just directly setting the input's value just after it is created/initialized:
01 super_naive_git_vs_code_message

So apparently, there are quite a few pieces that could be involved and I thought I would talk about it here. (I don't think I'm fully committed enough to start a PR, but maybe that would be more appropriate.)

EDIT: I'm adding to/editing this list in order to keep all of this reference information in a single place.

  • Git Service

    • Git and Repository

    • Wraps git CLI and current repository

    • [I]RawGitService

    • On node side, wraps Repository calls.

    • On browser side, wraps git channel client

    • IGitService

    • Wraps IRawGitService to expose desired interaction at the consumer level.

    • Browser implementation, GitService

    • Electron implementation, ElectronGitService



      • Thin wrapper used to locate git and instantiate the correct IGitChannel.


      • I am unsure why there are some extra implementations specific to electron browser as opposed to just the browser.



    • [I]GitChannel and GitChannelClient

    • Exposes git call methods to the client (browser).

    • gitApp

    • Where the service is instantiated on the node side.

  • ChangesView
  • GitAction

    • Base class to enable command-pattern actions which encapsulate git service calls in objects.

    • Many base and implementation classes in this file.

    • e.g. InitAction, BaseStageAction, StageAction, BaseUndoAction, UndoAction, etc.

    • Extends/implements [I]Action, which seems to also indicate that these actions are tied to a visual component, like a stage/undo button. But this is uncertain, as there are also workbench versions of these, such as WorkbenchStageAction

So according to other places like here and here, the accepted way to initialize the InputBox's value is simply setting it after creation as I did in the naive example:

this.commitInputBox.value = 'Hey, this is some test initial value.'

But this is only created once it seems, so I can't put it here. If we do a commit, then the input is cleared and it won't be recreated for the next commit.

Anyway, it's time to switch to something else for the time being. If y'all have another approach you're gonna take care of, or if you have thoughts on this approach for a possible PR, I'm all ears. I'm going to look at this again here in the near future.

Let's boil it down a bit. I've renamed the issue to better focus on what I think is that you want to achieve.

How will you manage the templates? Will you have a collection of them? How will you store them? How will you show a template picker, for when the user needs to type a commit message?

All those questions need to be answered before diving into the code.

@joaomoreno Whoa, slow your roll there cowboy! :horse_racing:

Judging by your questions, it is apparent that you did not read my link and are unaware that "commit templates" are already a thing in the basic configuration of git. So the "collection" and "storage" of them is done via the git CLI (Command Line Interface), using the git config mechanism. This git config mechanism has an inheritance structure, with a base global configuration that it usually stores in the user's profile or home directory and with a repository-level configuration that is stored with the repository directory itself. It uses the repository-level config for repo-specific things, as well as overriding any corresponding global configuration.

Because of this _already existing_ git CLI architecture, I spent my (unpaid ;) time and effort "diving into the code" to highlight the pertinent areas of the vs source code base. Git does the "managing", and there is no "template picker". The template is a file that you point your git repository at via git config.

Now snippets (which are not the same thing as _templates_ in vs and git parlance) could provide a more dynamic functionality for when the user wants to type a commit message, thus "picking" a "template" (in the more general sense of the term). But snippets don't seem very feasible in the near future without being a hack. But the _template_ is just a configuration setting that you would read to pre-populate the InputBox (if the template exists).

As an aside, this GitHub issue, and the words and such-like contained therein, is all about not diving into code but talking about it! :droplet:

This is awesome, I didn't realise nor know that a commit template was already a _thing_ in git. It does make things much easier, sorry for not realising this earlier.

I think we have all the knowledge and tools necessary to start a PR on this. Your research was right on point. The remaining question is to know when to actually ask git _what the template contents are_ and thus populate the input box. I suggest to do it on startup and after every commit. Possibly also every time the git view shows up... we'd have to see.

I'd be happy to review a PR, if you're still interested. 馃巻

PS: I didn't mean to put you down... I really appreciate your effort here and applaud your enthusiasm! 馃挴

Yes, I was thinking the same thing: the main question is to know when to populate the input box. This is why I also posted something on #6190. Whatever the workflow is for that is related to this. The basic workflow would be:

1) Check existing commit message.
2) If exists, then load the box with that.
3) If doesn't exist, then check for template, load that.
4) If none, then populate with a default template.

So, I'd like to hear if @sijad has done anything towards the code of that issue. Perhaps it would be better to merge the issues as "Improve git commit workflow" or similar.

It would be interesting to tackle this considering #6403 and #6614.

@joaomoreno I've looked at that a little bit. I am unsure what is meant by the "default git message" in #6403. I'll have to look at that. But if it means the git template, then what I've done so far should work for that. I don't know about #6614 though, that is a little out of my current scope (I think). If it involves getting commit information though, again, it should work.

Speaking of which, I've got the "pipeline" up and going, for lack of a better term. I've added commit information to the model and I have added a getCommitInfo all the way from the client(s) to the server. This ICommitInfo contains both the git.template (if it exists), and the previous commit message.

Basically, to get the template, the server has to execute the git command. When doing so, the client is expecting a status. So I had to add the commit info to the model, and implement the interfaces, etc. all the way. You can check out my latest commit [here](

At the moment, I am figuring out (in my spare time ;) how to parse the git template file (if it exists). After this, I will parse the previous commit message (if it exists), and then the contribution should be complete (without requirement creep).

As an aside, I would like to note overall, I think the contributing documentation is freaking awesome! That said, it is made a little more difficult without being able to actually debug the node server process, as the guide only speaks to debugging the client process and the host extension process, not the node server process - and I can't figure it out. But I'm doing it the good ol' fashioned way of log/console messages ;)

Also, I wanted to note that I've added some more moving parts to my previous comment for reference.
). So that should help anyone else, should they do this or something else that involves the git portion of vscode.

@joaomoreno After looking at the git commit documentation, it looks like that issue would require adding an option to the commit operation from the client and then interpreting it on the server.

I don't _think_ it necessarily is related to this issue, as this is more getting prior information. That issue is about passing a different argument to the commit operation.

I have the input box loading the template correctly now. I haven't thoroughly tested it just yet, but from the limited testing, it seems to be working. I also have the previous commit message being populated correctly. I "just" have to hook this up to the reset action (I think) and that _should_ take care of both this issue and issue #6190.

@bill-mybiz Great job.

In 34b7e140005213814d9cc6e9bde100d97754d96a, I've made it easier for you to debug the git world. Just flip the USE_REMOTE_PROCESS_SERVICE static to false and you'll be able to use the Developer Tools for debugging. Just don't commit that boolean change. 馃槈

I'm finding it hard to figure out what exactly is going on... maybe we can start creating that PR so I can review as you go along and we move the discussion closer to the changes themselves? 馃憤

@joaomoreno Thanks for the heads up :eyes: on the debugging. I will probably be looking into this tomorrow or Friday. I wanted to complete my train of thought for the changes on the previous commit message on the reset (I _think_ I'm almost done), and I will definitely get that PR rolling. I was committing things to that git branch, knowing that it was a little haphazard as I was learning, so it's no surprise if it's not easy to follow from the commit history. If the approach is all wrong overall when we do the PR, then no big. Now that I understand the overall architecture better, any alternative approach(es) should be easier to implement.

All right, I have it restoring the previous commit message after undoing the last commit as of my last commit, so this should address #6190.

I am unsure how pretty any of it is, but it works (from my testing on windows) and is relatively clean. I will go ahead and try to get a PR rolling.

@bill-mybiz Thanks for your hard work - this is awesome!

I can use a global template in my home folder just fine in code-insiders after configuring git like this:

> git config [--global or --local] commit.template ~/my-global-template.txt

Unfortunately, it looks like maybe the attempt to copy the git path handling by @joaomoreno in the merge doesn't work for local templates with a relative path.

For example, this doesn't work:

> git config --local commit.template my-local-template.txt

Notice the file is specified without a path, although using ./my-local-template.txt has the same problem. If I run git commit from the command line, git will open my text editor prepopulated with the local message in my-local-template.txt (which is in my repo's root folder). However, the git panel in vscode won't pick up the local template in the same way :( It's clear it knows there's a local setting, because it doesn't show the global template, but it isn't finding the local one correctly.

Anyway, thanks again for getting this going! Semantic commit messages are much easier to get right across different projects with a reminder of the corresponding project's expected format visible when writing them.

UPDATE: oops - I forgot to mention that I'm using Windows 8

@rob3c Thanks for letting us know about that issue. I'll make sure it gets fixed asap.

Fixed!

Thanks for all your efforts @bill-mybiz! 馃嵒 Also, thanks @rob3c for the keen eye. 馃憖

Verification:

  • Setup a git template file git config --global commit.template ~/template.txt
  • The contents of that file should be populated in the git view as the default commit message
  • You should be able to configure the setting globally and locally.
  • The path to the template can be absolute or relative or something like ~/template.txt, indicating that its rooted at the user's home directory.

@joaomoreno Thanks for addressing this so quickly! Unfortunately, I've downloaded today's Code Insiders update, and it's still not working when I try the same config commands as in my previous message:

# this template is in my repo root directory and is picked up correctly by the git-commit command.
# However, vscode still doesn't find it:
> git config --local commit.template my-local-template.txt

# same with this version using `./`, since paths are treated by git as relative to the repo root
> git config --local commit.template ./my-local-template.txt

Paths that use the home folder ~/ work great when specified globally or locally, but it's the templates stored in the repos themselves that still aren't being picked up correctly.

Or maybe this is landing tomorrow and I'm still just testing against the old code in today's update?

The next build will come on Monday 7AM CET.

Great - I look forward to it :) Is there an easy way to tell what commits made it into an Insiders build? Or do you just have to kinda guess based on recent commits vs when the notification pops up?

The Insiders build's About dialog displays the commit hash.

Thanks for the tip! Somehow I totally missed that when I checked there for the version number even though it's right there on the next line lol.

Waiting until today's update did the trick. The local templates are working perfectly, now :-)

  • _VS Code version 1.14.2_

The _commit message box_ is terrible and very limiting for such an important feature and renders
the integrated GIT unusable for me.

I prefer _Sublime_ instead to commit my changes as it opens a text file and let me enter a detailed
message in any format i wish.

VS Code version 1.17.0

You can achieve the same behaviour of opening a text file and entering whatever you want (and provably using local templates, didn't try that yet) to commit changes by setting VS Code as your default git editor.

git config --global core.editor "code --wait"

The --wait flag is now improved, allowing to terminate the calling process when the tab opened by git is closed.

PD: 'Code' command must be in your path

Was this page helpful?
0 / 5 - 0 ratings