Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ivan-degtiarenko/1e7a63671ff7db28dc07ac4b3750ec12 to your computer and use it in GitHub Desktop.
Save ivan-degtiarenko/1e7a63671ff7db28dc07ac4b3750ec12 to your computer and use it in GitHub Desktop.
TamperMonkey script to disable merge options on Github branches
// ==UserScript==
// @name Disable merge options on Github branches
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Avoid accidentally using the wrong merge option for specific branches. THIS SCRIPT NEEDS TO BE TWEAKED FOR YOUR PERSONAL NEEDS(more precisely "@match" column and "disabledBranchesByMethod").
// @author Ivan Degtiarenko
// @match https://github.com/<YOUR_ORGANIZATION>/<YOUR_REPOSITORY>/pull/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// @run-at document-start
// ==/UserScript==
const disabledBranchesByMethod = [
// ADD HERE: Branches for which "Create a merge commit" should be disabled. Example: ['branch-name-1', 'branch-name-2']
[],
// ADD HERE: Branches for which "Squash and merge" should be disabled. Example: ['branch-name-1', 'branch-name-2']
[],
// ADD HERE: Branches for which "Rebase and merge" should be disabled. Example: ['branch-name-1', 'branch-name-2']
[]
];
(function() {
'use strict';
// Use mutation observer as sometimes merge options widget loads later than the page.
var observer = new MutationObserver(function(mutations, obs) {
// Before this element is loaded function would spam errors to console.
if (!document.getElementsByClassName("merge-message")[0]) {
return;
}
let branchName = document.getElementsByClassName("gh-header-meta")[0].children[1].children[0].querySelector('.commit-ref').textContent;
let mergeMethodsEnabled = [true, true, true];
for (let i =0; i < 3; i++) {
mergeMethodsEnabled[i] = !(document.getElementsByClassName("merge-message")[0].querySelector('.select-menu-merge-method').children[0].children[i].disabled);
}
for (let i =0; i < 3; i++) {
mergeMethodsEnabled[i] = mergeMethodsEnabled[i] && (disabledBranchesByMethod[i].indexOf(branchName) === -1);
}
if (mergeMethodsEnabled.every(v => v === false)) {
// Restrictions are too strict, falling back to using repo restrictions only.
obs.disconnect();
return;
}
// Going in reverse order, so the last click would be the click on the top-most available option.
for (let i = 2; i >= 0; i--) {
if (mergeMethodsEnabled[i]) {
document.getElementsByClassName("merge-message")[0].querySelector('.select-menu-merge-method').children[0].children[i].click();
} else {
document.getElementsByClassName("merge-message")[0].querySelector('.select-menu').children[0].children[i].disabled=true;
document.getElementsByClassName("merge-message")[0].querySelector('.select-menu-merge-method').children[0].children[i].disabled=true;
// If disabled by branch-rule, add explanation note.
if (disabledBranchesByMethod[i].indexOf(branchName) !== -1) {
let child = document.createElement('span');
child.className='unavailable-merge-method';
child.textContent='Not enabled for this branch';
document.getElementsByClassName("merge-message")[0].querySelector('.select-menu-merge-method').children[0].children[i].children[1].appendChild(child);
}
}
}
// Once we successfully disabled merge options, observer can be removed to ease the load.
obs.disconnect();
});
observer.observe(document, {attributes: false, childList: true, characterData: false, subtree: true});
})();
@ue-cthompson
Copy link

Simple, but helpful. Thanks!
Line 31 was broken for me. Changing it as follow worked for me.

let branchName = document.getElementsByClassName("gh-header-meta")[0].children[1].children[0].querySelector('.commit-ref').textContent;

to

let branchName = document.getElementsByClassName("gh-header-meta")[0].children[1].children[0].querySelector('.commit-ref').textContent;

Not sure if this is helpful or not, but thought I'd share.

@sabasabo
Copy link

If you want to run the code when clicking on tabs, you can add the following code:
...
// @grant window.onurlchange
...

    const main = () => {
        // Use mutation observer as sometimes merge options widget loads later than the page.
        var observer = new MutationObserver(function(mutations, obs) {
        
        ...
        
        // Once we successfully disabled merge options, observer can be removed to ease the load.
            obs.disconnect();
        });

        observer.observe(document, {attributes: false, childList: true, characterData: false, subtree: true});
    }

    window.addEventListener('urlchange', (info) => main());
})();

@sabasabo
Copy link

sabasabo commented May 17, 2024

Also preventing duplicated 'Not enabled for this branch' messages:

                    // If disabled by branch-rule, add explanation note.
                    if (disabledBranchesByMethod[i].indexOf(branchName) !== -1) {
                        const mergeElement = document.getElementsByClassName("merge-message")[0].querySelector('.select-menu-merge-method').children[0].children[i].children[1];

                        if (!mergeElement.getElementsByClassName('unavailable-merge-method').length > 0) {
                            let child = document.createElement('span');
                            child.className='unavailable-merge-method';
                            child.textContent='Not enabled for this branch';
                            mergeElement.appendChild(child);
                        }
                    }

@sabasabo
Copy link

Fix for the error in line 31:

let branchNameElement = document.getElementsByClassName("gh-header-meta")[0].children[1].children[0].querySelector('.commit-ref');
            if (!branchNameElement) {
                // Refined GitHub disabled extension:
                branchNameElement = document.getElementsByClassName("gh-header-meta")[0].children[1].children[2]
            }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment