From 201ad377384848c208dceb42d152115bbe38061a Mon Sep 17 00:00:00 2001 From: Jonathan Ling Date: Fri, 15 Oct 2021 00:32:11 -0400 Subject: [PATCH] Delete merged and squashed from other branches. (#11) This defaults to master currently, my change proposes that the script should take an argument and allow squashed branches to be pruned no matter where they were merged. --- README.md | 10 +++++++++- bin/git-delete-squashed.js | 12 +++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3a278ae..cf84c5f 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,24 @@ This is useful if you work on a project that squashes branches into master. Afte To run as a shellscript, simply copy the following command (setting up an alias is recommended). There's no need to clone the repo. ```bash -git checkout -q master && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base master $branch) && [[ $(git cherry master $(git commit-tree $(git rev-parse $branch\^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done +# Change $TARGET_BRANCH to your targeted branch, e.g. change from `master` to `main` to delete branches squashed into `main`. +TARGET_BRANCH=master && git checkout -q $TARGET_BRANCH && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base $TARGET_BRANCH $branch) && [[ $(git cherry $TARGET_BRANCH $(git commit-tree $(git rev-parse $branch\^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done +# OR you can put this function in a global git alias and call it like this +# `git delete-squashed` OR `git delete-squashed main` +git config --global alias.delete-squashed '!f() { local targetBranch=${1:-master} && git checkout -q $targetBranch && git branch --merged | grep -v "\*" | xargs -n 1 git branch -d && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base $targetBranch $branch) && [[ $(git cherry $targetBranch $(git commit-tree $(git rev-parse $branch^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done; }; f' ``` ### Node.js You can also install the tool as a Node.js package from NPM. (The package code is in this repo.) +Additionally, you can specify an alternate branch to check for squashed merges, as well. This is useful for different names of trunk branches like `main` or `develop`. + ```bash $ npm install --global git-delete-squashed $ git-delete-squashed +$ # Specify a different branch name like so +$ git-delete-squashed main ``` ## Details diff --git a/bin/git-delete-squashed.js b/bin/git-delete-squashed.js index 95f5055..ce42ba4 100755 --- a/bin/git-delete-squashed.js +++ b/bin/git-delete-squashed.js @@ -5,6 +5,8 @@ const childProcess = require('child_process'); const Promise = require('bluebird'); const DEFAULT_BRANCH_NAME = 'master'; +const RUN_WITH_NODE = process.argv[0].includes('node'); +const selectedBranchName = process.argv[RUN_WITH_NODE ? 2 : 1] || DEFAULT_BRANCH_NAME; /** * Calls `git` with the given arguments from the CWD @@ -28,20 +30,20 @@ function git (args) { git(['for-each-ref', 'refs/heads/', '--format=%(refname:short)']) .then(branchListOutput => branchListOutput.split('\n')) .tap(branchNames => { - if (branchNames.indexOf(DEFAULT_BRANCH_NAME) === -1) { - throw `fatal: no branch named '${DEFAULT_BRANCH_NAME}' found in this repo`; + if (branchNames.indexOf(selectedBranchName) === -1) { + throw `fatal: no branch named '${selectedBranchName}' found in this repo`; } }).filter(branchName => // Get the common ancestor with the branch and master Promise.join( - git(['merge-base', DEFAULT_BRANCH_NAME, branchName]), + git(['merge-base', selectedBranchName, branchName]), git(['rev-parse', `${branchName}^{tree}`]), (ancestorHash, treeId) => git(['commit-tree', treeId, '-p', ancestorHash, '-m', `Temp commit for ${branchName}`]) ) - .then(danglingCommitId => git(['cherry', DEFAULT_BRANCH_NAME, danglingCommitId])) + .then(danglingCommitId => git(['cherry', selectedBranchName, danglingCommitId])) .then(output => output.startsWith('-')) ) - .tap(branchNamesToDelete => branchNamesToDelete.length && git(['checkout', DEFAULT_BRANCH_NAME])) + .tap(branchNamesToDelete => branchNamesToDelete.length && git(['checkout', selectedBranchName])) .mapSeries(branchName => git(['branch', '-D', branchName])) .mapSeries(stdout => console.log(stdout)) .catch(err => console.error(err.cause || err));