Code Monkey home page Code Monkey logo

fast-forward's Introduction

Fast Forward Pull Requests

This repository contains a GitHub action that merges a pull request by fast forwarding the target branch. The action is triggered when an authorized user adds a comment containing /fast-forward to the pull request.

Screenshot of a video demonstrating the action

The ability to fast forward a branch (the equivalent of doing git merge --ff-only) is needed to have an unmodified, linear history. More perspectives on the usefulness of fast forwarding are presented in this GitHub discussion.

Unfortunately, it is not currently possible to fast forward a branch using GitHub's web UX. GitHub's web UX allows the user to select from several different merge strategies, but none of the strategies fast forward the target branch even when fast forwarding is possible.

Screenshot of GitHub's Merge pull request options: "Create a merge commit", "Squash and merge", and "Rebase and merge"

The closest sounding merge strategy is Rebase and merge. But, it unconditionally rewrites the commits by changing each commit's committer field. That is, it does the equivalent of git rebase --no-ff. This results in the commits having a different hash, and destroys any signatures.

With a bit of work, it is possible to prevent GitHub from modifying the commits. Specifically, it is possible to push changes from a pull request directly to the target branch after any checks have passed. Consider:

$ # We can't directly push to main, because it is protected.
$ git push origin
...
remote: error: GH006: Protected branch update failed for refs/heads/main.
...
$ # We can create a PR, wait for the CI checks to pass, then push directly to main.
$ git push origin HEAD:workwork
$ git push origin

But, this approach isn't very convenient.

The fast-forward action improves the situation a bit by making it possible to fast forward directly from the web UX by posting a comment on the pull request.

See the GitHub Marketplace for other actions that do something similar.

Checking if Fast Forwarding is Possible

By default the fast-forward action checks if a pull request can be merged. It adds a comment to the pull request indicating if this is the case, or if the pull request needs to be rebased. When the target branch can't be fast forwarded, the action fails. If the target branch is protected, this prevents the branch from being merged, which is normally desired.

To run this check whenever a pull request is opened or updated, add .github/workflows/pull_request.yml to your repository with the following contents:

name: pull-request
on:
  pull_request:
    types: [opened, reopened, synchronize]
jobs:
  check-fast-forward:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      # We appear to need write permission for both pull-requests and
      # issues in order to post a comment to a pull request.
      pull-requests: write
      issues: write

    steps:
      - name: Checking if fast forwarding is possible
        uses: sequoia-pgp/fast-forward@v1
        with:
          merge: false
          # To reduce the workflow's verbosity, use 'on-error'
          # to only post a comment when an error occurs, or 'never' to
          # never post a comment.  (In all cases the information is
          # still available in the step's summary.)
          comment: always

Fast Forwarding a Pull Request

To actually fast-forward a branch, add .github/workflows/fast-forward.yml to your repository with the following contents:

name: fast-forward
on:
  issue_comment:
    types: [created, edited]
jobs:
  fast-forward:
    # Only run if the comment contains the /fast-forward command.
    if: ${{ contains(github.event.comment.body, '/fast-forward')
            && github.event.issue.pull_request }}
    runs-on: ubuntu-latest

    permissions:
      contents: write
      pull-requests: write
      issues: write

    steps:
      - name: Fast forwarding
        uses: sequoia-pgp/fast-forward@v1
        with:
          merge: true
          # To reduce the workflow's verbosity, use 'on-error'
          # to only post a comment when an error occurs, or 'never' to
          # never post a comment.  (In all cases the information is
          # still available in the step's summary.)
          comment: always

This workflow is only run when a comment that includes /fast-forward is added to the pull request. The workflow is careful to check that the user who triggered the workflow is actually authorized to push to the repository.

Disabling Comments

If you prefer to disable comments, you can set the comment input variable to false. The comment is also written to the comment output variable so it is possible to use it in a successive step. The format is a JSON document with a single key, body. Here's an example:

name: pull-request
on:
  pull_request:
    types: [opened, reopened, synchronize]
jobs:
  check-fast-forward:
    runs-on: ubuntu-latest

    permissions:
      contents: read
      # We appear to need write permission for both pull-requests and
      # issues in order to post a comment to a pull request.
      pull-requests: write
      issues: write

    steps:
      - name: Checking if fast forwarding is possible
        id: fast-forward
        uses: sequoia-pgp/fast-forward@v1
        with:
          comment: false
      - name: Display comment
        env:
          COMMENT: ${{ steps.fast-forward.outputs.comment }}
        run: echo "The comment is... $COMMENT"

This would display something like:

The comment is... {
  "body": "..."
}

Additional fields may be added to the JSON document in the future.

fast-forward's People

Contributors

nwalfield avatar

Stargazers

Claudine Allen avatar Neill Robson avatar Allen Rand avatar  avatar Matti Lamppu avatar Matti Lamppu avatar Richard Vodden avatar  avatar Maic Siemering avatar  avatar Nicolas Forgeot avatar Ricardo Almeida avatar  avatar Levi Bostian avatar Matt Travi avatar Cameron Smith avatar Dezső BICZÓ avatar Ryan Berckmans avatar Yesudeep Mangalapilly avatar Saul Rodriguez Alvarez avatar Zoltan avatar Giovanni Silva avatar Art Shendrik avatar  avatar Andrew Gallagher avatar Guillem Jover avatar

Watchers

 avatar Claudine Allen avatar

fast-forward's Issues

Add option for merging with a merge-commit or keep the merge strategy sets in the repository settings

Hi @nwalfield ,

Thanks a lot for this action.

In our repositories we'd like to use the semi-linear history as merge strategy.
From our point of view this strategy offer a couple of advantages we need.
This means we want to:

  • only merge fast-forward branches (so, check it while the PRs are open, and right before the merge);
  • always have a merge commit.

Using only github settings allows enforcing the second point, but not the 1st one.

I hoped that using this fast-forward action will cover these 2 points.
Unfortunately, while it does enforce the 1st point, the 2nd one is not met.

I see various ways for implementing this:

  • either add another option to force creating a merge commit (i.e. calling the git merge command with the --no-ff option);
  • or check the repository settings and use them to set the merge strategy. (IMHO, this option could be more tricky to implement than the previous one).

Do you think the is a legit feature request for this action?

Or maybe there is already a way of doing this - so I just misused the action. In such case could you shade some light on the way to set the action to run this way?

TIA,
Regards,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.