├── package.json ├── README.md └── index.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-branch-zip", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "bin": { 10 | "git-branch-zip": "index.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC" 15 | } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # git-branch-zip 2 | 3 | Checks out each branch in a git repo, finds the folder with the most changes from the last branch created, and zips it. 4 | 5 | Zips are placed in the `/tmp` folder. 6 | 7 | ### Installation 8 | 9 | ``` 10 | git clone git@github.com:StephenGrider/git-branch-zip.git 11 | cd git-branch-zip 12 | npm link 13 | ``` 14 | 15 | ### Running 16 | 17 | ``` 18 | git-branch-zip 19 | ``` 20 | 21 | Errors will be printed anytime a most-changed-folder cannot be determined. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { exec } = require('child_process'); 4 | 5 | async function run() { 6 | const branches = parseBranches(await safe('git branch -a')); 7 | 8 | for (let index in branches) { 9 | if (!index) { 10 | continue; 11 | } 12 | const branch = branches[index]; 13 | const previousBranch = branches[index - 1]; 14 | 15 | if (!branch || !previousBranch || previousBranch === 'master') { 16 | continue; 17 | } 18 | 19 | await safe(`git checkout ${branch}`); 20 | const changedFolder = await findChangedFolder(branch, previousBranch); 21 | if (!changedFolder) { 22 | console.error(`Unable to determine project folder for branch ${branch}`); 23 | continue; 24 | } 25 | 26 | try { 27 | await safe( 28 | `cd ${changedFolder} && zip -vr /tmp/\`basename ${branch.replace( 29 | 'remotes/origin/', 30 | '' 31 | )}\`.zip . -x "**/node_modules/*" "node_modules/*" "**/.git/*" "**/.next/*" ".DS_Store"` 32 | ); 33 | } catch (err) { 34 | console.error(`Failed to zip branch ${branch}:`, err.message); 35 | } 36 | } 37 | } 38 | run(); 39 | 40 | async function findChangedFolder(branch, previousBranch) { 41 | const diff = await safe(`git diff ${previousBranch}`); 42 | try { 43 | const [primary, secondary] = diff.match(/a\/(.*?)\//); 44 | return secondary; 45 | } catch (err) { 46 | console.error( 47 | 'Error finding project folder between', 48 | previousBranch, 49 | 'and', 50 | branch 51 | ); 52 | } 53 | } 54 | 55 | function parseBranches(str) { 56 | return str.split('\n').map((b) => { 57 | return b.includes('HEAD') || b.includes('*') ? null : b.replace(/\s/gi, ''); 58 | }); 59 | } 60 | 61 | async function safe(cmd) { 62 | const stdout = await new Promise((resolve, reject) => { 63 | exec( 64 | cmd, 65 | { 66 | maxBuffer: 1024 * 1024 * 10, 67 | }, 68 | (err, stdout, stderr) => { 69 | if (err) { 70 | console.error('err running command:', cmd); 71 | console.error(err); 72 | return reject(err); 73 | } 74 | if (stderr) { 75 | // console.error('Stderr running command:', cmd); 76 | // console.error(stderr); 77 | } 78 | resolve(stdout); 79 | } 80 | ); 81 | }); 82 | return stdout; 83 | } 84 | --------------------------------------------------------------------------------