Doing my daily work routine I found myself pulling the latest changes from different branches many times per day so I thought it could be nice to automate that process.
I ended up doing this with a small script that run on nodejs.
This task can be achieved in many different ways using for example: bash, python, powershell, java etc.
Create file multi-pull.js
const execSync = require('child_process').execSync;
function nodeExec(cmd)
{
return execSync(cmd, { stdio: [0, 1, 2] });
}
// Change the branch names to reflect your branches
let branches = ["hotfix_1", "hotfix_2", "dev", "main", "feature"]
// Change this path to match your repo folder
const repo = `C:/repo/test`
console.log(`\n\rScript directory: ${process.cwd()}` );
try {
process.chdir(repo);
console.log(`Actual repo directory: ${process.cwd()}\n`);
branches.forEach(branch => {
console.log(`\n\r----- Cheking out ${branch} -----\n\r`)
nodeExec(`git checkout ${branch}`)
nodeExec(`git fetch`)
nodeExec(`git pull`)
});
}
catch (err) {
console.log(`chdir: ${err}`);
}
You can simply run the script in the terminal, with nodejs installed
node multi-pull.js
If we want to automate this even further we could set an alias for this
You don't know what an alias is? Please refer to this article: How to speed up Git terminal workflow with bash and other tasks
# Pull multiple branches
alias pmb='node multi-pull.js'
Then run it just typing
pmb
Script output
Script directory: C:\gitea\test
Actual repo directory: C:\repo\test
----- Cheking out hotfix_1 -----
Switched to branch 'hotfix_1'
Your branch is up to date with 'origin/hotfix_1'.
Already up to date.
----- Cheking out hotfix_2 -----
Switched to branch 'hotfix_2'
Your branch is up to date with 'origin/hotfix_2'.
Already up to date.
----- Cheking out dev -----
Switched to branch 'dev'
Your branch is up to date with 'origin/dev'.
Already up to date.
----- Cheking out main -----
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Already up to date.
----- Cheking out feature -----
Switched to branch 'feature'
Your branch is up to date with 'origin/feature'.
Already up to date.
A better approach
We can make this process slightly better.
Instead of adding new branches into an array we will read them from a json
file, so if we ever wanted to add or remove a branch/es we could do it without the need to touch the javascript file. I could have used yaml
instead of json
but I am not a fan of it since leaving spaces or tabs would end failing while reading the file.
Folder structure
branches.json
multi-pull.js
Create a file called branches.json
{
"branches":
[
{
"label": "hotfix_1"
},
{
"label": "hotfix_2"
},
{
"label": "dev"
},
{
"label": "main"
},
{
"label": "feature"
}
]
}
Update multi-pull.js
// Moudule imports
const path = require('path')
const fs = require('fs')
const execSync = require('child_process').execSync;
// Declare constant
const jsonPath = './branches.json'
const filePath = path.resolve(__dirname, jsonPath)
// Change this path to match your repo folder
const repo = `C:/repo/test`
function nodeExec(cmd)
{
return execSync(cmd, { stdio: [0, 1, 2] });
}
console.log(`\n\rScript directory: ${process.cwd()}` );
// Read json file
let jsonData = (path) => {
try {
return JSON.parse(fs.readFileSync(path))
} catch (error) {
console.log(`\n Unable to read from ${path}: ${error}`);
process.exit()
}
}
let data = jsonData(filePath)
// Loop branches and pull
try {
process.chdir(repo);
console.log(`Actual repo directory: ${process.cwd()}\n`);
data.branches.forEach(branch => {
console.log(`\n\r----- Cheking out ${branch.label} -----\n\r`)
nodeExec(`git checkout ${branch.label}`)
nodeExec(`git fetch`)
nodeExec(`git pull`)
});
}
catch (err) {
console.log(`chdir: ${err}`);
}