Another reason for supporting actual fast forward merges is that if a user has signed their commits, it will ensure those signatures are kept as part of the merge process. Right now the only solution for maintaining these signatures is to create a merge commit.
This obviously isn't an "answer" but apparently I have no other way of adding my feedback to this.
1 reply
A third reason for fast-forward merge is if the merge itself needs to contain a merge commit e.g. there are conflicts between the branches and the two can't be reconciled via a rebase, because they're concurrent branches of a project (say, 1.0 and 2.0).
Because Github's UI does not (as far as I know) support merging with conflict resolution, assuming you are not willing or able to disable branch protection you have to "double merge" the branch, with a completely useless and redundant second commit.
This is even more frustrating when you already
Require branches to be up to date before merging
so the fast-forward is valid by definition.
0 replies
The issue title is a bit weird.
I'd rather call it "Allow fast-forward merges".
The current "rebase and merge" is not a fast-forward merge. It is a rebase, something very different.
To me a good idea would be like this:
- Provide new option for fast-forward merge, if possible.
- Provide option to create an annotated tag. This allows to store date and message without polluting the history with an actual merge commit. The tag could be signed by github, or by the github user.
6 replies
Building on this, I'd want three options:
- options to fast-forward merge on a pull request itself (both
-ffand-ff-only) - option on a repository and/or branch to change the default merge type in pull requests
- option on a repository and/or branch to disable one or more merge types in pull requests
In general, I never want a merge commit when a fast-forward is possible.
I also have a repository or two where I'd like to enforce --ff-only (at least for merges to main/master). Alas, I can only do so currently by making GitHub PRs off-limits, which is a shame.
In general, I never want a merge commit when a fast-forward is possible.
I just want to note that I personally disagree with this. Instead I never want a merge commit when a PR has a single commit. Or when the head of the PR is a merge commit (which might be necessary to resolve conflicts).
But I do usually want a merge commit to recapitulate the task when the PR has multiple commits: IME it's common to want to keep the task logically sectioned, but the information of it being a unit should be retained. That's where merge commits show their worth. This is orthogonal to the PR being fast-forward-able.
Not to mention that this would finally allow the build once principle to be actually followed if you use or wish to use short_sha as a version tag.
Gitlab Flow would be possible as well which is a much more desirable branching/release strategy for bigger organizations.
I believe this option is available in TFS (AzureDevops Server). as mentioned by @donquixote another merge option is the best way to go about.
it is currently possible to do this via commandline but then you need to allow "people" to push to protected branches.
But I do usually want a merge commit to recapitulate the task when the PR has multiple commits
i would want to squash a pr with multiple commits to one, a branch should be named something like feat/* fix/* chore/* so when i name my branch it should already be clear what should be the one commit message coming from that pr, that makes it easy to really group features and fixes etc. into one single meaningful commit containing all changes made for this fix or feature etc.
As a workaround, here's two workflows that allow fast-forwarding either via commenting /fast-forward or applying the label fast-forward, inspired by the comments above. I wish GitHub allowed triggering workflows via reactions on PRs! Anyway,
- these will merge the commits with the same hashes as in PR and no merge commit
- all checks will run as expected
- the PR will be marked as merged with the message such as
your-repo-name (bot) merged commit 1234567 into main 10 minutes ago
You will need to set up an empty GitHub app for the purpose of generating access tokens. The default token that comes with a workflow, GITHUB_TOKEN, is not suitable as workflows using it cannot trigger other workflows. Here are some instructions to set up a GitHub app. I just named mine the same I named my repo, and you can also set up an avatar for it! So, you:
- set up the app with r/w repo permission (you might also want to add r/w workflow permission if you want to be able to merge PRs that change workflow files),
- add it to your repo,
- put its id and private key in
LOKSMITH_IDandLOCKSMITH_PRIVATE_KEYsecrets of your repo, - and create a file
.github/workflows/fast-forward.ymlwith one of the following (this assumes your main branch is calledmain):
Fast-forward via commenting `/fast-forward`
name: Fast-forward on: issue_comment: types: [created, edited] jobs: fast_forward: name: Fast-forward runs-on: ubuntu-latest if: | github.event.issue.pull_request && github.event.comment.author_association == 'OWNER' && contains(github.event.comment.body, '/fast-forward') steps: - name: Generate access token uses: tibdex/github-app-token@v1 id: generate-token with: app_id: ${{ secrets.LOKSMITH_ID }} private_key: ${{ secrets.LOCKSMITH_PRIVATE_KEY }} - name: Fetch repository uses: actions/checkout@v3 with: token: ${{ steps.generate-token.outputs.token }} fetch-depth: 0 - name: Checkout pull request run: hub pr checkout ${{ github.event.issue.number }} env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - name: Fast-forward & push run: | export PR_COMMIT=$(git rev-parse HEAD) git checkout main git merge --ff-only "$PR_COMMIT" git push origin main
Fast-forward via applying the label `fast-forward`
name: Fast-forward on: pull_request: types: [labeled] jobs: fast_forward: name: Fast-forward runs-on: ubuntu-latest if: github.event.label.name == 'fast-forward' steps: - name: Generate access token uses: tibdex/github-app-token@v1 id: generate-token with: app_id: ${{ secrets.LOKSMITH_ID }} private_key: ${{ secrets.LOCKSMITH_PRIVATE_KEY }} - name: Checkout pull request uses: actions/checkout@v3 with: token: ${{ steps.generate-token.outputs.token }} fetch-depth: 0 - name: Fast-forward & push env: PR_COMMIT: ${{ github.event.pull_request.head.sha }} run: | git checkout main git merge --ff-only "$PR_COMMIT" git push origin main
That's it!
0 replies
It would be really great for GitHub to execute on this feature request.
GitHub is nearly 15 years old, and there is still no way for a pull request merge to be fast-forward-only (linear history) AND preserve the same commits as pull request source branch.
Today, if you want to preserve commits in your development branch (and not squash them; squashing is great sometimes), you have two bad options
- merge commits. This is bad because linear history is an excellent risk reduction mechanism for a production build.
- rebase commits. These would be ok, except when github rebases the commits into linear history, the commit hashes change (they are new commits) even though the patch and metadata are identical. So your development branch itself constantly needs to be rebased on your production branch, because the commits being added to production are newly created by github rebase & merge.
What we need is a fourth option "Fast-forward merge", which requires linear history and only preserves (ie copies) commits from the PR source branch into the target branch.
Please, do this. Thanks!
1 reply
0 replies
This feature is a must and can be an advance option and selectable from the dashboard. I’ve been having to —ff-only on my own, as PRs from dev to main in GitHub is a source for headaches. It’s important, make it an experimental feature, let users have linear history please!
0 replies
Would be very useful to have this feature! We would use this to power a flow for merging commits from main to release. release is never be committed to directly, and ideally it is either strictly at or behind main but never ahead. We have a github action workflow that we run to sync commits from main to release, but unfortunately all three existing methods of merging (merge, squash, rebase) cause some kind of divergence in the history of main and release. The only true way we can keep the histories in sync is by merging main to release locally via git (which allows for an FF merge), and then push that branch, but then we lose the benefits of PRs and protected branches.
5 replies
We have a very similar setup with test, qa and prod branches. That worked absolutely fine on GitLab (which we're migrating from), and also works fine on competing self-hosted projects like gitea and forgejo. Have you found a workaround for your setup?
...but then we lose the benefits of PRs and protected branches.
This isn't strictly speaking true. You can leave the branch protection in place and, as long as there's a PR open that has its requirements met, still push a fast-forward to the protected branch. But yes, only through the CLI, and yes, it's annoying there isn't a "fast-forward merge" option in the web UI. I haven't tried it yet, but it seems combining require linear commit history with disabling merge, squash, and rebase merges might be a sort-of nice solution.
You can't disable all three. Good to know that pushing a fast forward works when the PR has it's requirements met, that might be a feasible workaround for us.
Hmm... I wonder if you can use/abuse requiring signed commits to clobber the UI entirely. Of course it is super annoying that we're having this conversation about using unintended consequences of GitHub features to compose the reasonable behavior of "I want linear history".
I'm about to take my business to a competitor. This is one of the most core parts of an effective git workflow. This needs to be worked on.
3 replies
I had absolutely no idea that this was the case for years and I'm actually quite surprised that Github is doing something non-'standard' here. I didn't actually believe it when I first read about it and had to try it myself. Sure enough, Github is performing full replays of history instead of doing fast-forwards, resulting in different commits. My own personal workflow isn't particular impacted by this but thinking back to professional settings this is starting to paint a picture as to why rebases were so inexplicably problematic when people used the Github UI to do them as opposed to on the command line.
2 replies
Update: still somewhat floored this isn't possible on GH two years later. This is making multi-stage releases via review PRs impossible.
It also breaks submodule workflows.
I have a repo with three submodules, all controlled internally. The submodules don't see much churn so it is almost always safe to assume that if a PR goes up it will be the only one and a rebase won't be required, which means the other repo can start using that commit id in dev branches.
But no, when the PR rebases it creates a new ID and now the submodule commit id in my other repo is wrong. Thanks GitHub.
Fortunately the commit is still in GitHub so the submodule can still update, but it checks out a commit that doesn't live on any branches. Yay.
It appears as if I can either
- merge with a merge commit <--> why would I want a merge commit that doesn't really tell me anything when there's no conflicts?
- rebase merge <--> clear to people who know git that it rewrites history
- squash merge <--> nice to have, but again, history is lost;
git branch -derrors/warns
"require linear history" doesn't work either for this purpose.
This forces me to merge on the command line (which, by the way, instructions-as-described in enterprise server 3.5 don't actually force a merge commit, but the button does); which I don't know how this plays with "disable pushes to master".
I could have sworn that historically there was some kind of option that would perform a ff-merge, perhaps I've gone insane though.
I guess I'll have to write a bot / app for our CI for this custom procedure? That feels dumb.
4 replies
I guess I'll have to write a bot / app for our CI for this custom procedure? That feels dumb.
Here's my attempt further up.
But I also want to note that if you merely don't have conflicts it doesn't mean that you can fast forward. To be able to fast-forward, your feature branch must be based on the last commit of your main branch. Unless you are willing to update your feature branch every time the main branch is updated, you can benefit from fast forwarding only when there's very few people developing very few feature branches on your project.
To be able to fast-forward, your feature branch must be based on the last commit of your main branch.
Yeah that's fine. The main thing here is people sometimes make one-commit PRs / features, and doing another merge commit on top of this is silly and confuses people unnecessarily (as much as I'd love to say people should just learn git and good practices, I can't force them to).
I'm fine with merge commits, but if it can be fast forwarded, I'd prefer that. Maybe I want a rebase merge, which is fine too, but that detaches the history for things like git branch -d and should be used with careful intent.
Which is the same reason single commit squash doesn't solve the "I don't want an extra merge commit" problem, because it's really a "I want git to keep track of the history, and I don't want useless merge commits." Because people are lazy and don't fill out the message box; I'd rather have (in order, assuming no conflicts) ff, (rebase + ff or merge (with appropriate message preferrably) or squash) dependent on the individual scenario. If there are conflicts what I'd really want people to do is ladder-tree-stitch merge, but nobody has time for that so any option other than ff as long as the intent is clear and it makes sense.
If teams work with narrowly scoped microservices and use trunk-based development with short-lived feature branches, then rebasing your branch prior to creating and merging your PR tends to be trivial. This also ensures you control what the commits look like and specifically ensure any merge conflicts are dealt with the way you want. I think at a minimum adding a Fast-Forward merge option on the UI is a must. Allowing that to be enforced would be nice to have after that.
As I see it, somebody trying to send pull request using the GitHub UI should be the one doing the rebase and GitHub could offer to do this automatically for them before they submit the pull request. If a merge could be done without a conflict, the rebase should result in perfectly identical state but with simpler history.
Rebasing your code to allow fast-forward should be the default and true merges should be reserved for special cases.
Generally if there are no conflicts, it is fairly trivial to rebase with main before commiting, and, in fact, the user interface already supports doing so automatically.
…On Fri, Jul 14, 2023 at 6:09 AM oakkitten ***@***.***> wrote: I guess I'll have to write a bot / app for our CI for this custom procedure? That feels dumb. Here's my attempt <#4618 (comment)> further up. But I also want to note that if you merely don't have conflicts it doesn't mean that you can fast forward. To be able to fast-forward, your feature branch must be based on the last commit of your main branch. Unless you are willing to update your feature branch every time the main branch is updated, you can benefit from fast forwarding only when there's very few people developing very few feature branches on your project. — Reply to this email directly, view it on GitHub <#4618 (reply in thread)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAANTD3OJECIVUXLNFGE7MDXQELF5ANCNFSM5AI3TFGQ> . You are receiving this because you are subscribed to this thread.Message ID: ***@***.*** com>
2 replies
It's mentioned elsewhere in this thread that the rebase merge in the web UI always rewrites the commits, even if a fast-forward were possible.
To do the rebase and merge from the command line: git pull --rebase origin main git branch -D main git branch -m main git push origin main
…1 reply
The command-line workaround has been discussed extensively here and elsewhere. This thread is a feature request for the GitHub web UI so this is not required. The situation being described is where the PR is already fast-forwardable and does not require a rebase. This can be done with one step:
git push origin origin/<branch>:<base>
My comment was more in reference to difficulties if there other commits the need to be rebased. The ui is able to handle this in the non-fast-forward case automatically, so it should be no difficulty to do so with fast forward. My example command was a demonstration that it is trivial to actually do, as long as there are no conflicts.
…On Sat, 15 Jul 2023, 17:47 Chris Copeland, ***@***.***> wrote: The command-line workaround has been discussed extensively here and elsewhere. This thread is a feature request for the GitHub web UI so this is not required. The situation being described is where the PR is already fast-forwardable and does not require a rebase. This can be done with one step: git push origin origin/<branch>:<base> — Reply to this email directly, view it on GitHub <#4618 (reply in thread)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAANTDY4VL2N3DWDX22PGE3XQMFY5ANCNFSM5AI3TFGQ> . You are receiving this because you are subscribed to this thread.Message ID: ***@***.*** com>
2 replies
I'm saying with little difficulty on THEIR part. The fact that they haven't done it is the problem, but it is certainly doable
…0 replies
I don't understand why this hasn't been implemented yet. Why should we need to do all these kind of workarounds for a simple thing that is already possible on the CLI? This feature needs to be added.
0 replies
What a mess! We ended up designing a completely different process, with no Pull Requests and no Peer Reviews. Based on a classic Open Source contribution workflow with the 👀👀-principle is based on paired programming and mob programming.
I've covered it in a blog post all the tools; a GitHub CLI extension and a handfull of generic callable workflows we developed are open source.
0 replies
+1 to adding this. I'm shocked there's features ADO supports that Github doesn't.
0 replies
0 replies
There is no way this issue still needs bumping and there is not even a single official mention of resolving it.... but sure go ahead add another shitty ai slop to the platform!
0 replies
The fact that so many people suggest workarounds drives me even more crazy. The kindness and willingness to solve our own problem as well as others is the heart of this platform.
The problem is that we, the people, don't like it when it is made so obvious that we absolutely don't give a sh1t about us.
Instead of leveraging more and more data experts to provide even more AI slop bs features everywhere, just give this job to 2 or 3 juniors that will be more than happy to help thousands of people with 3 of their work days.
Come on. Life is hard enough to have to fight with the number 1 platform that host OSS for such minor feature request.
0 replies
0 replies
All I can say is that you can tell Microsoft own Github now - and by that I mean: they don't give two hoots about the people that use the product... Market share is their only metric for concern.
0 replies
+1 - again, this is needed.
0 replies
2026 is here, still need to fast forward manually...
0 replies
I'm flabbergasted Github.com...
0 replies
13 replies
@syhe Yes it would always be better to have more then one option for authentication.
But the idea behind the GitHub App is that you don't need that much configuration overhead on the user side that you would have with a PAT. As only the repository owner needs to install the app, no one else.
Repository permissions are inherited from the user which wants to authorize the app for this browser extensions.
@simnalamburt No, sorry for that confusion. The user that wants to use that browser extension does not need to install the app. It is the repository owner which needs to install it, so this would also give the control of, if --ff merges can be used or not on the repository, back to the owner, not the one who installs this extension to the browser.
Edit1: In other words, with your current approach every user who has write access to a repository could create a PAT and use your browser extension to do a -ff merge on a PR in that repository, whether the repository owner would want to allow that or not. Even not a branch protection rule would prevent this, because the merge comes from a PR.
Edit2: While I also would like to have native support (or other possibilities) for --ff merge for PRs, I can also see others that don't want that, e.g. when a chosen git flow requires that --ff merges are not allowed on the master branch.
The existence of this extension does not cause repository owners to lose control. This browser extension does not enable users to do anything they could not already do. Anyone who can perform a fast-forward merge with this browser extension could already perform a fast-forward merge from the CLI without it. Even now, anyone with write permission can fast-forward merge from the CLI, and this cannot be prevented (GitHub does not block it). So there is no change to the repository owner’s level of control.
Separately, making ff-for-github work on top of OAuth would require a relatively complex implementation.
- In addition to Chrome Web Store review, the app would also need to be registered on the GitHub Marketplace and pass review there.
- Token lifetime management would become necessary; access tokens would need to be continuously refreshed using refresh tokens.
- Since a browser extension is a public client, it would need to be implemented using the authorization code + PKCE flow, in accordance with the official documentation: https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/best-practices-for-creating-a-github-app#client-secrets
- Users would no longer be able to simply install the extension and follow the instructions; they would also need to be separately instructed to install the GitHub App for each organization.
If more people request GitHub App support, I will implement it.
Yes, I was aware of these possibilities that someone can do the merge from the CLI or just use the REST API on their own in a GitHub Action or something else. But not all users know all of these possibilities.
I did not try to write a picture about security concerns.
What I tried to say was, that all people that have installed your extension and configured a PAT, then can see the button on every PR page and could easily do a --ff merge, where the user could already do a normal merge. But maybe the repository owner will not be aware of that this type of merge is now an easily possible way for the user of the GitHub Web UI and would want to restrict it?
On the other side without your extension, even if someone already know any of the other possibilities, it's still not that easy to do so like a single click on the PR page, which could be an argument for them to not do it at all.
But now, that Pandora's Box is opened, it's to late to reverse the situation. And I wouldn't want it either, because I still like your idea to have a browser extension for that.
I was only mentioning all this, because I would have liked to see better control over who can see or use the button and what other requirements are there to use the button (GitHub App support instead of PAT).
Some thoughts on your points:
- Are you sure that you would need to register it on the GitHub Marketplace? I already created my own (public) GitHub App (https://github.com/apps/auto-commit-action) for use in a GitHub Action, but I intentionally did not register it on the Marketplace and also don't have any review passed from there. My GitHub Action does function perfectly fine. Are there other requirements for the OAuth flow to create user access tokens?
- Yes, token lifetime management would be necessary in some way, but you would not need to persist it on disk, because the usage of the refresh token to regenerate the access token is also optional. You could just have the user to reauthorize again by doing the full OAuth flow again, when the token is expired or it isn't available in memory anymore. (Is there a RAM-only browser session storage?)
- Yes, this would be a good idea to do for a public browser extension.
- As I said, users of the extension would not need to do anything more than installing the extension to their browsers. The repository owner would be the one to install the GitHub App for the repository. So isn't this much simpler for the user than require to create a PAT?
Thank you for all the hard work on this.
- Not sure
- AFAIK without persisting refresh token, access token only lives for 8 hours
- I never have implemented it before
- No, users should install the extension and then they have to go through OAuth flow once more. Without it there's no way for chrome extension to get OAuth token
I haven’t tried it myself, and I don’t personally feel a strong need for it. I’m also busy, so I probably won’t implement it in the short term, but if you submit a PR, I’d be willing to review it.
So is github going to allow this or not?
0 replies
0 replies
So is github going to allow this or not?
No, at least not in the foreseeable future, unless there are major organizational changes.
Given everything that has happened (and is still happening) with GitHub over the last few weeks, they first need to figure out how to handle basic Git functions properly while keeping the cumulative uptime of their services above 90% (https://mrshu.github.io/github-statuses/).
The fiasco with merge queues rewriting history a few weeks ago suggests that internal PR operations may be far more chaotic than most of us assume, and why such functionality may be much harder to implement for them (although I don't buy this as a reason).
I suggest that we keep posting only our custom solutions here (and discussing them in a thread, example above: https://github.com/orgs/community/discussions/4618#discussioncomment-16396715), instead of repeatedly asking for updates from their side - there will be none, they have much larger issues to fix.
4 replies
You are correct to point out that internally there is a lot more going on than meets the eye. That is a valid thing to keep in mind.
But also, fast forward merging is literally the easiest possible form of 'merge' to perform. It isn't even a merge. It is 'point this branch at this existing commit ID'.
I could believe that they have some other internal reason not for doing this, but their absolute silence on the matter while people have brought up valid concerns for over a decade is astounding. Their platform is central to many open source projects and communities, and they can't be so open as to say why they won't implement the most basic of git's features?
Add the fact that there are third party solutions to this and the evidence grows against them. The problem can be solved. The feature can be implemented. But why could they never be bothered? They had great uptime for over a decade before recent changes. They could have done this a long time ago.
So while I think you are right to highly existing solutions and point out other more pressing issues, I won't be leaving them alone about providing the basic services their platform was built to provide.
I've been recently contacted by one of GitHub account managers trying to upsell us GitHub Enterprise and GitHub Advanced Security features. What I did is told him that given all the recent GitHub outages, we have decided to postpone any new investments into GitHub usage. And we also are not satisfied with the performance, quality and availability of the GitHub Actions recently.
We are not a very big organization, but I think this counts.
I suggest to press them all the ways possible, but without loosing focus which functionality is the most important. I don't say that FF merges are not important, but they definitely have a bigger fish to fry at the moment. To the point that I don't think that they are looking at these discussions anymore.
