Github manual merge

Changes the copy button at the top of a pull-request to copy a git command to pull to a pr branch

  1. // ==UserScript==
  2. // @name Github manual merge
  3. // @namespace https://github.com/lordwelch/
  4. // @version 2.4
  5. // @description Changes the copy button at the top of a pull-request to copy a git command to pull to a pr branch
  6. // @license MIT
  7. // @author lordwelch
  8. // @match https://github.com/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com
  10. // @grant none
  11. // @run-at document-idle
  12. // ==/UserScript==
  13.  
  14. (async function() {
  15. 'use strict';
  16. console.log("script started");
  17. var pushState = history.pushState;
  18. var replaceState = history.replaceState;
  19.  
  20. history.pushState = function() {
  21. pushState.apply(history, arguments);
  22. window.dispatchEvent(new Event('pushstate'));
  23. window.dispatchEvent(new Event('locationchange'));
  24. };
  25.  
  26. history.replaceState = function() {
  27. replaceState.apply(history, arguments);
  28. window.dispatchEvent(new Event('replacestate'));
  29. window.dispatchEvent(new Event('locationchange'));
  30. };
  31.  
  32. window.addEventListener('popstate', function() {
  33. window.dispatchEvent(new Event('locationchange'));
  34. });
  35. window.addEventListener("load", function() {
  36. window.dispatchEvent(new Event('locationchange'));
  37. });
  38. function breakCheck() {
  39. if (document.getElementById('gh-manual-pull-fix') != null) {
  40. console.log("fix is already applied");
  41. return true;
  42. }
  43. if (document.getElementById('gh-manual-merge-fix') != null) {
  44. console.log("fix is already applied");
  45. return true;
  46. }
  47. var location = document.location.pathname.match(/\/([^/]+)\/([^/]+)\/pull\/(\d+)$/);
  48. if (location == null) {
  49. console.log("incorrect page");
  50. return true;
  51. }
  52. return false;
  53. }
  54.  
  55. function trimSuffix(str, suffix) {
  56. if (str.endsWith(suffix)) {
  57. return str.substr(0, str.length-suffix.length);
  58. }
  59. return str;
  60. }
  61. function trimPrefix(str, prefix) {
  62. if (str.startsWith(prefix)) {
  63. return str.substr(prefix.length-str.length);
  64. }
  65. return str;
  66. }
  67.  
  68. function FixForkInstructions(argument) {
  69. if (breakCheck()) {
  70. return;
  71. }
  72.  
  73. let location = document.location.pathname.match(/\/([^/]+)\/([^/]+)\/pull\/(\d+)$/);
  74. if (location == null) {
  75. return;
  76. }
  77. let upstreamPrNum = location[3];
  78.  
  79. let headObj = document.querySelector('.commit-ref.head-ref');
  80. let [downstreamOwner, headRepoRef] = headObj.title.split('/');
  81. let [downstreamRepo, downStreamBranch] = headRepoRef.split(':');
  82. let baseObj = document.querySelector('.commit-ref.base-ref');
  83. let [upstreamOwner, baseRepoRef] = baseObj.title.split('/');
  84. let [upstreamRepo, upstreamBranch] = baseRepoRef.split(':');
  85. let downstreamUrl = `https://${document.location.host}/${downstreamOwner}/${downstreamRepo}`;
  86. let upstreamUrl = `https://${document.location.host}/${upstreamOwner}/${upstreamRepo}`;
  87.  
  88. let localBranchName = `${downstreamOwner}/${downStreamBranch}-${upstreamPrNum}`
  89.  
  90. let fetch = `git fetch --force ${downstreamUrl} +${downStreamBranch}:${localBranchName}`
  91.  
  92. let pullInstructions = `git stash\ngit checkout ${upstreamBranch}\ngit fetch --force ${downstreamUrl} +${downStreamBranch}:${localBranchName}\ngit checkout ${localBranchName}`;
  93. let mergeInstructions = `git checkout ${upstreamBranch}\ngit merge ${localBranchName}`;
  94.  
  95. let clipboardButtons = document.querySelectorAll("clipboard-copy.js-copy-branch");
  96. for (const cButton of clipboardButtons) {
  97. cButton.value = fetch;
  98. }
  99. if (breakCheck()) {
  100. return;
  101. }
  102. }
  103.  
  104. function FixBranchInstructions(argument) {
  105. if (breakCheck()) {
  106. return;
  107. }
  108.  
  109. let headObj = document.querySelector('.commit-ref.head-ref');
  110. let [downstreamOwner, headRepoRef] = headObj.title.split('/')
  111. let [downstreamRepo, downStreamBranch] = headRepoRef.split(':')
  112. let baseObj = document.querySelector('.commit-ref.base-ref');
  113. let [upstreamOwner, baseRepoRef] = baseObj.title.split('/')
  114. let [upstreamRepo, upstreamBranch] = baseRepoRef.split(':')
  115. let downstreamUrl = `https://${document.location.host}/${downstreamOwner}/${downstreamRepo}`;
  116. let upstreamUrl = `https://${document.location.host}/${upstreamOwner}/${upstreamRepo}`;
  117.  
  118. var pullInstructions = `git stash\ngit checkout ${upstreamBranch}\ngit fetch --force ${downstreamUrl} +${downStreamBranch}:${downStreamBranch}\ngit checkout ${downStreamBranch}`;
  119. var mergeInstructions = `git checkout ${upstreamBranch}\ngit merge ${downStreamBranch}`;
  120.  
  121. let clipboardButtons = document.querySelectorAll("clipboard-copy.js-copy-branch");
  122. for (const cButton of clipboardButtons) {
  123. cButton.value = fetch;
  124. }
  125. if (breakCheck()) {
  126. return;
  127. }
  128. }
  129. async function fixManualMergeInstructions() {
  130. console.log("script running");
  131. if (breakCheck()) {
  132. return;
  133. }
  134. var location = document.location.pathname.match(/\/([^/]+)\/([^/]+)\/pull\/(\d+)$/);
  135. if (location == null) {
  136. return;
  137. }
  138. var upstreamOwner = location[1];
  139. var upstreamRepo = location[2];
  140. var upstreamPrNum = location[3];
  141. var refObj = document.querySelector('.commit-ref.head-ref');
  142. while (refObj == null) {
  143. await new Promise(r => setTimeout(r, 300));
  144. console.log("Waiting for pr to load");
  145. if (breakCheck()) {
  146. return;
  147. }
  148. location = document.location.pathname.match(/\/([^/]+)\/([^/]+)\/pull\/(\d+)$/);
  149. if (location == null) {
  150. continue;
  151. }
  152. upstreamOwner = location[1];
  153. upstreamRepo = location[2];
  154. upstreamPrNum = location[3];
  155. }
  156. if (breakCheck()) {
  157. return;
  158. }
  159. let [downstreamOwner, repoRef] = refObj.title.split('/')
  160. let [downstreamRepo, downStreamBranch] = repoRef.split(':')
  161.  
  162. if (downstreamRepo != upstreamRepo || downstreamOwner != upstreamOwner) {
  163. FixForkInstructions()
  164. } else {
  165. FixBranchInstructions()
  166. }
  167. }
  168. window.addEventListener('locationchange', fixManualMergeInstructions);
  169. fixManualMergeInstructions();
  170. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址