Why curl closes PRs on GitHub

Contributors to the curl project on GitHub tend to notice the above sequence quite quickly: pull requests submitted do not generally appear as “merged” with its accompanying purple blob, instead they are said to be “closed”. This has been happening since 2015 and is probably not going to change anytime soon.

Let me explain why this happens.

I blame GitHub

GitHub’s UI does not allow us to review or comment on commit messages for pull requests. Therefore, it is hard to insist on contributors to provide the correct message, using the proper language in the correct format.

If you make a pull request based on a single commit, the initial PR message is based on the commit message but when follow-up fixes are done and perhaps force-pushed, the PR message is not updated accordingly with the commit message’s updates.

Commit messages with style

I believe having good commit messages following a fixed style and syntax helps the project. It makes the git history better and easier to browse. It allows us to write tools and scripts around git and the git history. Like how we for example generate release notes and project stat graphs based on git log basically.

We also like and use a strictly linear history in curl, meaning that all commits are rebased on the master branch. Lots of the scripting mentioned above depends on this fact.

Manual merges

In order to make sure the commit message is correct, and in fact that the entire commit looks correct, we merge pull requests manually. That means that we pull down the pull request into a local git repository, clean up the commit message to adhere to project standards.

And then we push the commit to git. One or more of the commit messages in such a push then typically contains lines like:

Fixes #[number] and Closes #[number]. Those are instructions to GitHub and we use them like this:

Fixes means that this commit fixed an issue that was reported in the GitHub issue with that id. When we push a commit with that instruction, GitHub closes that issue.

Closes means that we merged a pull request with this id. (GitHub has no way for us to tell it that we merged the pull request.) This instruction makes GitHub closes the corresponding pull request: “[committer] closed this in [commit hash]”.

We do not let GitHub dictate how we do git. We use git and expect GitHub to reflect our git activity.

We COULD but we won’t

We could in theory fix and cleanup the commits locally and manually exactly the way we do now and then force-push them to the remote branch and then use the merge button on the GitHub site and then they would appear as “merged”.

That is however a clunky, annoying and time-consuming extra-step that not only requires that we (always) push code to other people’s branches, it also triggers a whole new round of CI jobs. This, only to get a purple blob instead of a red one. Not worth it.

If GitHub would allow it, I would disable the merge button in the GitHub PR UI for curl since it basically cannot be used correctly in the project.

Squashing all the commits in the PR is also not something we want since in many cases the changes should be kept as more than one commit and they need their own dedicated and correct commit message.

What GitHub could do

GitHub could offer a Merged keyword in the exact same style as Fixed and Closes, that just tells the service that we took care of this PR and merged it as this commit. It’s on me. My responsibility. I merged it. It would help users and contributors to better understand that their closed PR was in fact merged as that commit.

It would also have saved me from having to write this blog post.

Discussion

Hacker news

Addendum

In some post-publish discussions I have seen people ask about credits. This method to merge commits does not break or change how the authors are credited for their work. The commit authors remain the commit authors, and the one doing the commits (which is I when I do them) is stored separately. Like git always do. Doing the pushes manually this way does in no way change this model. GitHub will even count the commits correctly for the committer – assuming they use an email address their GitHub account does (I think).

22 thoughts on “Why curl closes PRs on GitHub”

  1. Codeberg has an extra function for manual merging. You can then enter the commit ID of the merge there.

    What I always find unfortunate when editing is that the GPG/SSH signature of the commit is removed (and particularly annoying if the maintainer who then merges it does not even sign it with his key).

    On the other hand, manual merging has the advantage that you can even sign the merge commit. And I think it’s nice that you make the style yourself and thus help contributors.

    And thanks for the explanation!

  2. Small note: In the workflow to force push the merge result, I believe you can replace clicking the merge button with pushing the merged commit to the main branch – and github will automatically detect that and make the PR purple, if I recall correctly. This doesn’t help with the extra CI job, but at least you don’t need to click a button.

  3. > That means that we pull down the pull request into a local git repository, clean up the commit message to adhere to project standards.
    >
    > And then we push the commit to git.

    Sounds like the “squash and merge” button/option, which allows you to edit the commit message, would accomplish the same thing (except without leaving the interface) with less steps/friction. I would love to learn why this option does not work for this project; perhaps I’m missing that from the article – do you mind expanding why?

    1. @Chris: two reasons:

      I dread editing a commit message and stay within 72 columns in a web form. Especially if it is a large one.

      But perhaps more: a PR can certainly end up more than a single commit, so just assuming that all commits would always be squashed is not the right thing. If there are separate changes they should remain separate commits, each with its own correct commit message.

  4. You may recall a long time ago when we were working on the curl push guidelines a big problem with those buttons was GitHub would take committer attribution rather than the actual person committing it. Then we couldn’t track who committed what. I’m not sure if they still do it that way. Github messing with committer/author attribution is a no go.

    I don’t think github is going to please everyone here but if there was a way for us to extend or automate one of their buttons with a script we could come in and do a transformation or something. Like if we had a custom button that could run our script server side to automatically do the attribution, squash, show a preview etc

    1. @Ray: I believe that attribution thing was a flaw that no longer occurs. At least I have not seen it recent in other repositories where I have used the merged button.

  5. You made a typo.

    «[…] typically contains likes like» -> «[…] typically contains lines like».

  6. I’m reminded of a saying my grandmother taught me, over 50 years ago.

    A foolish consistency is the hobgoblin of little minds.

  7. For something that’s supposed to make collaboration faster and easier, time and time again I’ve seen a lot of developers and projects fighting to get GitHub, and git in general, to do what they want.

    So much time and effort is spent on figuring out workarounds, then actively using those workarounds day-to-day, then trying to get contributors to understand and follow them, then sorting out problems when those workarounds end up failing in some way, then doing things manually, and so forth.

    It all makes self-hosting a VCS server, CI infrastructure, bug tracker, mailing lists, and so on look easier, cheaper, and more enjoyable for all involved.

  8. Why isn’t “squash and merge” a de facto standard in the industry, I don’t know.

    Each PR should represent a single change. As such, is reversible via reverts. Furthermore, not doing more than one change at a time.

    1. Sometimes though you want a stack of commits, each doing one thing and building on the last

      To squash that loses important context and modularity

  9. “We do not let GitHub dictate how we do git. We use git and expect GitHub to reflect our git activity” – 100% this! A tool is for people, not people for a tool.

  10. I would really like a Merged keyword or simply an API to associate PRs with commits, simply because I prefer rebasing locally. I use git from the command-line. I don’t want the github website/servers to perform git actions on my repos, it just needs to be a frontend to my repos. It also lets me sign the commits, which has to be done locally. Fortunately the “Allow edits by maintainers” works decently for me but sometimes you have to ask the contributor to enable it.

  11. Stumbled over this:
    “the commit messageS are correct” or “the commit message IS correct”

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.