macsAir Collecting frequent-committer miles

Work with Git Forges inside Emacs

I am excited to announce the first public release of Forge—v0.1.

Forge allows you to work with Git forges—such as Github and Gitlab—from the comfort of Magit and the rest of Emacs.

Usage

Forge comes with a manual. Here I will gloss over a few not entirely unimportant topics such as the creation of API tokens and won’t mention each and every available command.

To start using Forge in a certain repository visit the Magit status buffer for that repository and type f y ( forge-pull ). This adds an entry to the database and a new value to remote.<remote>.fetch , which instructs Git on how to fetch the pull-request references.

Then, and on each subsequent invocation, it asynchronously fetches API data and the pull-request references. Once that is done, issue and pull-requests are listed in Magit’s status buffer.

Most Forge commands do not work in a given repository until you have done the above, though some do. The ones that don’t will tell you to use forge-pull before trying to use them again.

Some of Forges commands are available from a dedicated popup on ' , but many commands are also available when point is on an appropriate section in a Magit buffer, just like is the case for many of Magit’s own commands.

Pull-request branches can be created ( b Y ) and checked out ( b y ) from Magit’s regular branching popup.

To visit an issue or pull-request in a separate buffer use RET while point is on that topic in the status buffer. Elsewhere you can use C-c C-v to do the same. Likewise use C-c C-w to visit an issue or pull-request using a browser.

In a buffer that is visiting a topic you can create a new post using C-c C-n or edit an existing post or metadata using C-c C-e .

Posts are edited in separate buffers. Like in buffers used to write commit messages you have to either confirm the message using C-c C-c or abort using C-c C-k .

Prior Art

Forge isn’t the first such package. Earlier implementations include magit-gh-pulls , magithub , and a quite few more, most of which you can find on my list of Git-relate Emacs packages.

Forge is quite similar to Magithub, especially when it comes to what features these packages provide and how the interface looks. While both packages are not part of Magit, they are both tighly integrated with Magit. They also both use my ghub library and Forge uses the graphql package, which was written by the author of Magithub. The two of us did collaborate but in the end I decided to go forward with my plan to implement Forge from scratch anyway. I hatched that plan long before Magithub was released and and by the time that happened I was already working on the low-level parts (in the form of ghub ) anyway. Nevertheless I think it was a fruitful collaboration, which I expect to resume shortly (I have been a bit quiet as of late).

Major Design Decisions

Users have to explicitly pull data from the API when they feel the time has come to do so. This is inspired by Git, which also does not fetch at random intervals and behind the users back.

Forge permanently stores all fetched data, like Git does. Originally I planned to store as much information using Git objects as possible but in the current version most data is stored in an SQLite database. The use of a database makes certain future changes more difficult. While I will try to keep breaking changes to a minimum, I have little hope that I can make it without any at all. In some cases it might even be necessary for users to discard the existing database.

While other packages are limited to just one forge—usually Github—Forge already supports Github and Gitlab. Three more forges—Gitea, Gogs and Bitbucket—are only partially support for now, meaning that their APIs are not supported yet (except “what is the ID of this repository”), but features that do not depend on data from the API are. Additionally Forge supports four semi-forges—Gitweb, Cgit, Stgit and Stht. Like a forge, a semi-forge provides a web interface to Git repositories. Unlike a forge it does not support issues and pull-request, and/or does not provide an API. But even without access to an API, Forge can still provide features such as “visit this commit/branch/… in a browser”.

Forge also fetches pull-request references using Git. I find it quite surprising that there aren’t more tools that take advantage of this easily accessible information. Forge fetches these refs even for the forges whose APIs are not supported yet. The user experience is much better when the API data is also available but even just being able to checkout and merge pull-requests using Magit is a big win.

Forge uses Github’s GraphQL API when possible (other forges do not have a GraphQL API (yet, in the case of Gitlab) and even for Github the REST API has to be used for some things). Using GraphQL makes fetching much faster. Even when using GraphQL the initial fetch still takes a few minutes though, if there are thousands of issues, but subsequent fetches are very fast.

PS

Writing Forge took much longer than expected. If I was to do it again I would probably implement many of the planned Magit features first and only write Forge once most of those features are done. I.e. I would be starting about now.

Forge doesn’t have all that many features yet (but the most important ones are there). While it should be fairly easy and quick to add a bunch of new commands now, I am going to focus on other things from the Magit roadmap first.





Comments on Reddit.