Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
M

multi-gitter

> DevOps
Open source

Update multiple repositories in with one command

1.2K stars0 likes0 views
WebsiteGitHub

About

Update multiple repositories in with one command

multi-gitter allows you to make changes in multiple repositories simultaneously. This is achieved by running a script or program in the context of multiple repositories. If any changes are made, a pull request is created that can be merged manually by the set reviewers, or automatically by multi-gitter when CI pipelines have completed successfully.

Are you a bash-guru or simply prefer your scripting in Node.js? It doesn't matter, since multi-gitter support any type of script or program. If you can script it to run in one place, you can run it in all your repositories with one command!

Some examples:

  • Syncing a file (like a PR-template)
  • Programmatic refactoring
  • Updating a dependency
  • Automatically fixing linting issues
  • Search and replace
  • Anything else you are able to script!

Demo

Example

Run with file

$ multi-gitter run ./my-script.sh -O my-org -m "Commit message" -B branch-name

Make sure the script has execution permissions before running it (chmod +x ./my-script.sh)

Run code through interpreter

If you are running an interpreted language or similar, it's important to specify the path as an absolute value (since the script will be run in the context of each repository). Using the $PWD variable helps with this.

$ multi-gitter run "python $PWD/run.py" -O my-org -m "Commit message" -B branch-name
$ multi-gitter run "node $PWD/script.js" -R repo1 -R repo2 -m "Commit message" -B branch-name
$ multi-gitter run "go run $PWD/main.go" -U my-user -m "Commit message" -B branch-name

Test before live run

You might want to test your changes before creating commits. The --dry-run flag provides an easy way to test without actually making any modifications. It works well when setting the log level to debug, with --log-level=debug, to also print the changes that would have been made.

$ multi-gitter run ./script.sh --dry-run --log-level=debug -O my-org -m "Commit message" -B branch-name

Install

Homebrew

If you are using Mac or Linux, Homebrew is an easy way of installing multi-gitter.

brew install --cask lindell/multi-gitter/multi-gitter

Manual binary install

Find the binary for your operating system from the release page and download it.

Automatic binary install

To automatically install the latest version

curl -s https://raw.githubusercontent.com/lindell/multi-gitter/master/install.sh | sh

From source

You can also install from source with go install, this is not recommended for most cases.

go install github.com/lindell/multi-gitter@latest

Token

To use multi-gitter, a token that is allowed to list repositories and create pull requests is needed. This token can either be set in the GITHUB_TOKEN, GITLAB_TOKEN, GITEA_TOKEN environment variable, or by using the --token flag.

GitHub

How to generate a GitHub personal access token (classic). Make sure to give it repo permissions.

GitLab

How to generate a GitLab personal access token. Make sure to give to it the api permission.

Gitea

In Gitea, access tokens can be generated under Settings -> Applications -> Manage Access Tokens

Config file

All configuration in multi-gitter can be done through command line flags, configuration files or a combination of both. If you want to use a configuration file, simply use the --config=./path/to/config.yaml option. You can also specify this flag multiple times, where later files override configs set in earlier files. Multi-gitter will also read from the file ~/.multi-gitter/config and take and configuration from there. The priority of configs are first flags, then defined config file and lastly the static config file.

All available run options

…

All available merge options

…

All available status options

…

All available close options

…

All available print options

…

Usage

  • run Clones multiple repositories, run a script in that directory, and creates a PR with those changes.
  • merge Merge pull requests.
  • status Get the status of pull requests.
  • close Close pull requests.
  • print Clones multiple repositories, run a script in that directory, and prints the output of each run.

Usage of run

This command will clone down multiple repositories. For each of those repositories, the script will be run in the context of that repository. If the script finished with a zero exit code, and the script resulted in file changes, a pull request will be created.

When the script is invoked, these environment variables are set:

  • REPOSITORY will be set to the name of the repository currently being executed
  • DRY_RUN will be set =true, when running in with the --dry-run flag, otherwise it's absent
…

Usage of merge

Merge pull requests with a specified branch name in an organization and with specified conditions.

…

Usage of status

Get the status of all pull requests with a specified branch name in an organization.

…

Usage of close

Close pull requests with a specified branch name in an organization and with specified conditions.

…

Usage of print

This command will clone down multiple repositories. For each of those repositories, the script will be run in the context of that repository. The output of each script run in each repo will be printed, by default to stdout and stderr, but it can be configured to write to files as well.

When the script is invoked, these environment variables are set:

  • REPOSITORY will be set to the name of the repository currently being executed
…

Example scripts

general

Clone all repositories locally while maintaining their group folder structure

#!/bin/bash

# This script should be used with the print command.
mkdir -p ~/multi-gitter/$REPOSITORY
cp -r . ~/multi-gitter/$REPOSITORY

Replace a file if it exist

#!/bin/bash

REPLACE_FILE=~/test/pull_request_template.md # The file that should replace the file in the repo, must be an absolute path
FILE=.github/pull_request_template.md # Relative from any repos root

# Don't replace this file if it does not already exist in the repo
if [ ! -f "$FILE" ]; then
    exit 1
fi

cp $REPLACE_FILE $FILE

Replace text in all files

#!/bin/bash

# Assuming you are using gnu sed, if you are running this on a mac, please see https://stackoverflow.com/questions/4247068/sed-command-with-i-option-failing-on-mac-but-works-on-linux

find ./ -type f -exec sed -i -e 's/apple/orange/g' {} \;

go

Replace all instances of empty interface with any

#!/bin/bash

gofmt -r 'interface{} -> any' -w **/*.go

Fix the ioutil deprecation

#!/bin/bash

gofmt -w -r 'ioutil.Discard -> io.Discard' .
gofmt -w -r 'ioutil.NopCloser -> io.NopCloser' .
gofmt -w -r 'ioutil.ReadAll -> io.ReadAll' .
gofmt -w -r 'ioutil.ReadFile -> os.ReadFile' .
gofmt -w -r 'ioutil.TempDir -> os.MkdirTemp' .
gofmt -w -r 'ioutil.TempFile -> os.CreateTemp' .
gofmt -w -r 'ioutil.WriteFile -> os.WriteFile' .
gofmt -w -r 'ioutil.ReadDir -> os.ReadDir ' . # (note: returns a slice of os.DirEntry rather than a slice of fs.FileInfo)

goimports -w .

Fix linting problems in all your go repositories

#!/bin/bash

golangci-lint run ./... --fix

Updates a go module to a new (patch/minor) version

#!/bin/bash

### Change these values ###
MODULE=github.com/go-git/go-git/v5
VERSION=v5.1.0

# Check if the module already exist, abort if it does not
go list -m $MODULE &> /dev/null
status_code=$?
if [ $status_code -ne 0 ]; then
    echo "Module \"$MODULE\" does not exist"
    exit 1
fi

go get $MODULE@$VERSION

Upgrade Go version in go modules

#!/bin/bash

go mod edit -go 1.18
go mod tidy

node

Updates a npm dependency if it does exist

#!/bin/bash

### Change these values ###
PACKAGE=webpack
VERSION=4.43.0

if [ ! -f "package.json" ]; then
    echo "package.json does not exist"
    exit 1
fi

# Check if the package already exist (without having to install all packages first), abort if it does not
current_version=`jq ".dependencies[\"$PACKAGE\"]" package.json`
if [ "$current_version" == "null" ];
then
    echo "Package \"$PACKAGE\" does not exist"
    exit 2
fi

npm install --save $PACKAGE@$VERSION

Simple replace using node

const { readFile, writeFile } = require("fs").promises;

async function replace() {
  let data = await readFile("./README.md", "utf8");
  data = data.replace("apple", "orange");
  await writeFile("./README.md", data, "utf8");
}

replace();

Do you have a nice script that might be useful to others? Please create a PR that adds it to the examples folder.

Bitbucket Cloud

note: bitbucket cloud support is currently in Beta

In order to use bitbucket cloud you will need to create and use an App Password or Workspace Token. The app password or workspace token you create needs sufficient permissions so ensure you grant it Read and Write access to projects, repositories and pull requests and at least Read access to your account and workspace membership.

You will need to configure the bitbucket workspace using the org option for multi-gitter for the repositories you want to make changes to. You will also need to configure the authentication method using the auth-type flag e.g. multi-gitter run examples/go/upgrade-go-version.sh -u your_username --org "your_workspace" --auth-type app-password

Example

Here is an example of using the command line options to run a script from the examples/ directory and make pull-requests for a few repositories in a specified workspace, using app password authentication.

export BITBUCKET_CLOUD_APP_PASSWORD="your_app_password"
multi-gitter run examples/go/upgrade-go-version.sh -u your_username --org "your_workspace" --repo "your_first_repository,your_second_repository" --platform bitbucket_cloud -m "your_commit_message" -B your_branch_name --auth-type app-password

Here is an example of running the script using workspace token authentication.

export BITBUCKET_CLOUD_WORKSPACE_TOKEN="your_workspace_token"
multi-gitter run examples/go/upgrade-go-version.sh -u your_username --org "your_workspace" --repo "your_first_repository,your_second_repository" --platform bitbucket_cloud -m "your_commit_message" -B your_branch_name --auth-type workspace-token

Bitbucket Cloud Limitations

Currently, we add the repositories default reviewers as a reviewer for any pull-request you create. If you want to specify specific reviewers, you will need to add them using their UUID instead of their username since bitbucket does not allow us to look up a UUID using their username. This article has more information about where you can get a users UUID.

We don't support specifying specific projects for bitbucket cloud yet, you should still be able to make changes to the repositories you want but certain functionality, like forking, does not work as well until we implement that feature. Using fork: true is currently experimental within multi-gitter for Bitbucket Cloud, and will be addressed in future updates. Here are the known limitations:

  • The forked repository will appear in the user-provided workspace/orgName, with the given repo nam

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Goautomationclicommandlinedeveloper-tools

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
CategoryDevOps
PricingOpen source

> Related tools

D
Docker
容器化平台,标准化应用交付
G
GitHub Actions
GitHub 原生 CI/CD 工作流
N
Nginx
高性能 Web 服务器与反向代理