How to do a fast-forward merge on GitHub?
Asked Answered
C

7

120

So one of my colleagues attempted to merge a branch using GitHub's "merge via fast-forward" option in the web-interface, to keep the history clean from bogus merge commits (the master branch into which they merged, had not progressed since the to-be merged feature-branch was started).

Funnily enough, this didn't work as expected: all the commits got new commit-hashes.

On closer inspection, it seems that merge-option is actually called "Rebase and Merge" and it really seems to do the equivalent of git rebase --force, changing the Committer information (both the person who did the merge, and the time when the merge happened).

It took me quite a while to confirm my suspicion that this is indeed the case, as I couldn't make the cmdline tools to show me the difference between the original commits on the feature branch and the seemingly-identical commits (with different hashes) on the master branch. (In the end, I found that gitk shows both Committer and Author of a commit; in the very end I found that I can also get this information via git log --pretty=raw)

So:

  • Is there a way to do a "proper" fast-forward merge (git rebase without the --force option) via GitHub's web-interface?
  • If not: why? (I can see merits in accountability; e.g. it answers the question who is responsible that a given piece of code ended up in master)
Crellen answered 9/3, 2020 at 9:6 Comment(0)
P
34

Based on GitHub's documentation and my own testing, it is not possible to do a fast-forward with the same commit hash.

The rebase and merge behavior on GitHub deviates slightly from git rebase. Rebase and merge on GitHub will always update the committer information and create new commit SHAs, whereas git rebase outside of GitHub does not change the committer information when the rebase happens on top of an ancestor commit. For more information about git rebase, see the "Git rebase" chapter from the Pro Git book.

https://docs.github.com/en/github/administering-a-repository/about-merge-methods-on-github

Phlegmy answered 14/9, 2020 at 16:8 Comment(2)
worth mentioning that you can open the pull-request and merge it from the command line and push it and github will close the PR as merged – Squirmy
Many people request the real fast-forward strategy. It is in the top 20 discussions in [GitHub community](Please upvote the discussion in GitHub community πŸ™). – Extravagant
E
97

Looks like GitHub does not support this – and this is a TERRIBLE affair. You basically CANNOT run an atomic, linear commit strategy (the best there is) using the GitHub UI.

Note that Bitbucket DOES support this, and has much more fine-grained options for setting up the PR landing/integration strategy. Namely the 'Rebase, fast-forward' option which does a --ff-only update of the target/mainline branch. It also has a 'Rebase, merge' option which lets you run a rebase on target (so that your commits are linear) but integrates using a merge commit (if you want to track that the commits are all part of one logical unit/PR).

Both of these options seem superior to GitHub's limited options of either using non-linear merge commits (GitHub's 'Merge pull request' option) or linear rebase ('Rebase and merge' option), which does achieve linearity but creates duplicate commits on the source branch, thus always requiring manual Hard Resets locally if you want to keep things clean and in sync.

So... time to switch your repo provider it seems!

Esma answered 15/12, 2020 at 23:6 Comment(5)
Okay I just understood the issue. This is horrible! – Quenchless
i bet they do this so github actions re-runs consuming your free minutes – Maxilliped
I can't believe github doesn't allow this, its crazy. Does anyone know if there are plans of implementing this in the near future? – Bluestone
Oddly, it allows it when there's a merge conflict, a magic rebase UI appears. – Introversion
Please upvote the discussion in Github community πŸ™ – Extravagant
E
72

It's possible to do a fast-forward merge via the command line and then push it to Github. The Github pull request CLI instructions do explicitly say to use git merge --no-ff, but it also appears to work with a fast-forward, which preserves the git commit hash and closes the open pull request:

$ git checkout master
$ git merge your-branch # the branch which has an open pull request
$ git push

At this point, Github will automatically detect that the branch was merged and the pull request will be closed. If you have the "pull request" page open in your web browser you will see it asynchronously change the state to: "X merged commit into master", "Pull request successfully merged and closed".

It is worth noting that this solution also makes it possible to use branch protection with a linear strategy. Create a PR from the development branch (your-branch or dev) to the protected branch (master) and then do a fast-forward merge using the command line. Such a merge to a protected branch will fail before creating the PR, but after creating the PR the ff merge will succeed and the PR will be closed.

Earsplitting answered 1/4, 2021 at 14:40 Comment(9)
well, i was explicitely asking for how to do it "via GitHub's web-interface". (for completeness sake, it's good you mentioned that github explicitely acknowledges such merges) – Polyphyletic
Indeed, and when the master branch is protected this is not even possible. So it is more than a nuisance of having to perform these steps manually, sometimes these steps are not even possible. – Imelda
@m-d i, too, feared that branch protection would prevent me from using the suggestion in this answer. However, after some experimentation I have found that branch protection can coexist with this. – Maxia
@Earsplitting i'm glad you provided this answer for completeness. It made me try this CLI approach which I otherwise had assumed would be blocked by my branch protection. But it coexists with branch protection! My protection settings are: Require status checks to pass before merging, Require branches to be up to date before merging, and Include administrators ... yet I can push directly to the protected branch as long as the commit(s) that I am pushing are part of a PR where the status checks did indeed already pass. This is very good news for me. – Maxia
This solution works coexist with branch protection. To make it work, you must create a pull request first. – Maybe
This solution works beautifully, though it's irritating not to be able to use the web interface. I configured my repo to only accept rebase merges, then set branch protection on main to "require PRs", "require signatures", and "linear history". AFAIK, that makes it impossible for the web UI to merge PRs into the protected branch. Doing FF merges on the command line and then pushing, however, gets me all three of those. It even automatically closes the PR and (if configured) deletes the PR branch. – Irwin
I notice that the github web app now includes CLI merge instructions which tell you do to git merge xx and don't instruct you to use --ff-only so it would seem they actually recommend FF merge in this case (unless there is some configuration I'm not aware of that makes non-FF the default). Which makes it a bit odd that FF should not even be an option in the web app. – Justness
Am I correct in thinking that this approach could be dangerous, e.g. if you had local changes committed to your-branch (not yet pushed to remote), the merge command would merge those local changes into main? A safer approach would be to pull each branch and do a hard reset before attempting the merge, right? – Duane
and, in most cases branches such as uat and master are branch protected and rules such as 2 min approvals required are setup, so you usually can't do things in local – Discrown
P
34

Based on GitHub's documentation and my own testing, it is not possible to do a fast-forward with the same commit hash.

The rebase and merge behavior on GitHub deviates slightly from git rebase. Rebase and merge on GitHub will always update the committer information and create new commit SHAs, whereas git rebase outside of GitHub does not change the committer information when the rebase happens on top of an ancestor commit. For more information about git rebase, see the "Git rebase" chapter from the Pro Git book.

https://docs.github.com/en/github/administering-a-repository/about-merge-methods-on-github

Phlegmy answered 14/9, 2020 at 16:8 Comment(2)
worth mentioning that you can open the pull-request and merge it from the command line and push it and github will close the PR as merged – Squirmy
Many people request the real fast-forward strategy. It is in the top 20 discussions in [GitHub community](Please upvote the discussion in GitHub community πŸ™). – Extravagant
H
13

An alternative could be to setup a Fast Forward PR GitHub Action:

Merge pull request using fast forward only, if possible, moving base branch (target branch) to head branch (source branch). Comment success or failure messages on the pull request issue. The goal is to keep branches equal at the end of the merge.

Hjerpe answered 8/9, 2021 at 2:3 Comment(4)
as of 2021-11-15 i tried this and doesn't seem to work github.com/endre-spotlab/fast-forward-js-action/issues/… – Havener
have you resolved the issue ? @KimStacks – Perrin
@BryanLumbantobing Did you ever get FF Github Action to work? – Keil
no luck @CoreyBruyere – Perrin
F
4

Based on what others wrote, it doesn't look like GitHub supports this through their web UI. I haven't figured out how to do it either. It works for command line, like others mentioned (git merge --ff-only ...), but there doesn't appear to be a UI equivalent.

I apologise for mentioning a competing product, Gitea. Gitea has a very similar UI to GitHub, and the UI has the same three methods for merging a PR. However, the third one, labeled ("Rebase and merge"), unlike GitHub's, will automatically do a fast-forward merge if there is no need for rebasing. It just works. That's why it's not clear to my why you can't do it on GitHub.

Fisherman answered 20/7, 2021 at 12:1 Comment(0)
I
4

GitHub Rebase is broken as, unlike other serviceproviders (bitbucket, GitLab, etc) GitHub will surprisingly rewrite hashes on rebase even when it is not needed.

I use this workaround to keep signatures and linear Git History on GitHub (which is impossible if using WebUI only).

Workflow:

  1. Pull Request to main happens

  2. Dont Rebase with UI!

  3. Instead from terminal checkout main/master and git merge --ff-only <the pr branch> && git push

  4. Signatures kept, seems to work even on protected branches, and autocloses PR-branch.

Ilona answered 14/3, 2023 at 22:13 Comment(1)
This is almost identical to the answer from @Earsplitting ( https://mcmap.net/q/181618/-how-to-do-a-fast-forward-merge-on-github ) – Techno
E
0

As of October 31, 2023, this is not supported by GitHub. However, you can always leverage GitHub Actions to automate this for you and be in even more control. An example is available at https://github.com/samkit-jain/override-github-merge which I use daily in all my work repositories.

Extended answered 31/10, 2023 at 15:18 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.