Allow force pushing of protected branches with granular permissions
Problem to solve
As a repo owner/creator, when rewriting history, I must unprotect a protected branch in order to force push it or delete it.
Repository owners/creators, potentially other broader groups as configured.
Quoting from the relevant documentation on protected branches:
By default, a protected branch does four simple things: - it prevents its creation, if not already created, from everybody except users with Maintainer permission - it prevents pushes from everybody except users with Maintainer permission - it prevents anyone from force pushing to the branch - it prevents anyone from deleting the branch
This proposal concerns itself with the last two.
As there are good arguments against force-pushing as a practice, or branches like master ever being deleted, I'd like to address those:
Rewriting history is an extraordinary activity, and it is fair to require extraordinary measures to perform it. Also, the fact that git supports an operation does not mean that gitlab can't require manual intervention to perform it.
In some cases rewriting history cannot be avoided, for instance when sensitive information was improperly committed and pushed. In the current system, force pushing for a purpose like rewriting history requires briefly opening up a protected branch such as master, allowing it to be pushed or merged by anyone with access to the repo. A repo owner is justified feeling uncomfortable with this procedure and as though the permissions settings are not feature-complete.
It should be possible for an appropriately privileged user to perform an emergency force-push, while still preventing normal users from doing normal pushes or merges. Manual intervention, if required to discourage bad git practices, should not involve disabling any other functionality of gitlab as it does currently.
I see three possible solutions here, listed in order of complexity:
- Always allow the repo owner/creator to perform any action on a branch regardless of protected status. Basically a "super-maintainer" privilege level for the owner/creator. No UI changes. Not ideal but conceptually simple.
- Add a manual "temporarily enable force pushing/deleting" button to protected branches. When a privileged user needs to perform a force push to a protected branch, or delete it for recreating later, they can push this button to temporarily allow the procedure. This maintains the manual intervention step, to discourage users from bad git practices. This button could be visible to maintainers, or only to the repo owner/creator.
- Add a new category of permissions to protected branches. Ideal but a larger change. The new list of permission categories for protected branches would be:
- allowed to merge
- allowed to push
- allowed to force push/delete
The default value for this new category could be "No One", to establish permissions identical to the current system. However, I personally think a new entry of "Repo Owner/Creator" should be added, and this should be the default. For one-person or small-team projects that are common on gitlab, the repo owner/creator is typically the ultimate authority, and the person who needs to disable branch protection or reconfigure permissions when a force push is necessary. It seems reasonable to allow this person/account powers they do not currently have out of the box, such as the ability to create a new personal repo, push an initial commit, and then immediately force-push a different version of that commit, without requiring them to change the default permissions.
Permissions and Security
No changes to permissions for the actual branch protection screen are necessary; if you can edit that screen, you can enable/disable these other permissions as expected. From the git API, the appearance would be identical to the current protected branch behavior when a user does not have the force push permission, and identical to the current unprotected branch / normal git behavior when the user does have it.
https://docs.gitlab.com/ee/user/project/protected_branches.html is the only page I know of.
As this is a permissions/security change, I understand it would have stringent testing requirements. No changes to the other two permissions categories should occur because of this change, and if a new user category of "Repo Owner/Creator" is added (in any of the 3 options), no other user categories should have these "superpowers".
What does success look like, and how can we measure that?
- A user with the highest possible level of repo permissions can perform any git operation on a protected branch without ever disabling branch protection.
- For the repo owner/creator, force-pushing a protected branch works, assuming permissions are configured correctly and any manual steps have been performed.
- For non-privileged users, force-pushing or deleting protected branches is forbidden as currently.