https://github.com/nieomylnieja/gitsync
Git manager which keeps specified files in sync across multiple repositories
https://github.com/nieomylnieja/gitsync
cli git github go repository-management synchronization
Last synced: 10 months ago
JSON representation
Git manager which keeps specified files in sync across multiple repositories
- Host: GitHub
- URL: https://github.com/nieomylnieja/gitsync
- Owner: nieomylnieja
- License: mit
- Created: 2024-07-10T08:18:52.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-14T14:25:02.000Z (11 months ago)
- Last Synced: 2025-03-26T08:47:35.135Z (10 months ago)
- Topics: cli, git, github, go, repository-management, synchronization
- Language: Go
- Homepage:
- Size: 62.5 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# gitsync
`gitsync` helps manage multiple git repositories which share the same files
(or parts of them) and helps keep them up-to-date and in sync.
This project was born out of the need to manage multiple repositories which
shared the same development files, like linter configs, CI/CD scripts, etc.
Why not use submodules?
- They won't be sufficient if there are slight differences between root and
synchronized files and If the tool does not support merging multiple
configs.
- Some tools depend on their config files being in specific places,
like in the root of the repository.
While this can be solved by linking, the solution is not platform-agnostic.
What I ended up doing was:
- Define a _root_ repository, which would serve as a staple for other
repositories to follow.
- Update linter configs, CI/CD scripts, GH workflows, etc. at the _root_
first and only then propagate these changes manually to all the other
_synchronized_ repositories.
However, with a growing number of repositories I had to govern, it started
to become more and more painful and time consuming to do that by hand.
Enter `gitsync` 😉
## Install
Use pre-built binaries from
the [latest release](https://github.com/nieomylnieja/gitsync/releases/latest)
or install
with Go:
```shell
go install github.com/nieomylnieja/gitsync/cmd/gitsync@latest
```
It can also be built directly from this repository:
```shell
git clone https://github.com/nieomylnieja/gitsync.git
cd gitsync
make build
./bin/gitsync ./go.mod
```
### Requirements
The following programs must be installed and available in the `$PATH`:
- `git`
- `diff` (GNU version)
- `gh` (GitHub CLI)
## Usage
`gitsync` ships with two commands:
1. `sync` - interactively creates a patch and applies it to the synchronized
repositories' files.
2. `diff` - shows the differences between the root and synchronized files in
unified format.
```shell
gitsync -c config.json [diff|sync]
```
If the `-c` (config file path) flag is not provided,
`gitsync` will look for a `gitsync.json` file in either
`$XDG_CONFIG_HOME/gitsync/config.json` or
`$HOME/.config/gitsync/config.json`.
### Sync
`sync` performs the following steps:
1. Clones the repository (if not yet cloned) into `storePath`
(see [config](#config-file)).
2. Fetches the latest changes from the root repository.
3. Interactively creates a patch between the root and synchronized files.
- The user can choose to skip hunks.
- The user can choose to permanently ignore hunks, by:
- Adding `regex` rules to the `ignore` field in the config file.
- Choosing `i` option in the prompt, which will add `hunk` rules to the
`ignore` field in the config file.
- Manually adding `hunk` rules to the `ignore` field in the config file.
4. Applies the patch to the synchronized repository.
5. Commits the changes to the index.
6. Pushes the changes to the remote repository.
7. Creates a pull request (currently only GitHub is supported).
### Diff
`diff` runs the same as `sync`, but instead of applying the patch it simply
prints it.
### Config file
The config file is a JSON file which describes the synchronization process.
```json5
{
// Optional. Default: $HOME/.local/share/gitsync or $XDG_DATA_HOME/gitsync.
// Path to the directory where the repositories will be cloned and stored.
"storePath": "~/.config/gitsync",
// Required. Configuration of the root repository.
// Follows the same format as syncRepositories[].
"root": {
"name": "template",
"url": "https://github.com/nieomylnieja/go-repo-template.git"
},
// Optional.
"ignore": [
// If neither 'repositoryName' nor 'fileName' is provided,
// the rule will apply globally.
// If both are provided, the rule will apply only to the specific repository file.
{
// Optional. Name of the repository to which the ignore rule applies.
"repositoryName": "go-libyear",
// Optional. Name of the file to which the ignore rule applies.
"fileName": "golangci linter config",
// Optional. List of regular expressions used to ignore matching hunks.
// Note: This regular expression is passed to 'diff -I ' and thus follows
// BRE (basic regular expression) rules, you may need to escape some characters, like '+'.
// Ref: https://www.gnu.org/software/grep/manual/html_node/Basic-vs-Extended.html.
"regex": ["^\\s\\+local-prefixes:"]
},
{
// Optional. Hunks to be ignored are represented with lines header and changes list.
// Either enter it manually or use the 'i' option in the sync command prompt.
//
// Ref: https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html.
"hunks": [{
// Optional. If lines are not provided the changes will be matched anywhere within the file.
"lines": "@@ -3,0 +4,2 @@",
// Required.
"changes": [
"+ skip-dirs:",
"+ - scripts"
]
}]
}
],
// Required. At least one repository must be provided.
"syncRepositories": [
{
// Required. Name of the repository, must be unique.
"name": "go-libyear",
// Required. URL used to clone the repository.
"url": "https://github.com/nieomylnieja/go-libyear.git",
// Optional. Default: "origin/main".
"ref": "dev-branch"
},
{
"name": "sword-to-obsidian",
"url": "https://github.com/nieomylnieja/sword-to-obsidian.git"
}
],
// Required. At least one file must be provided.
"syncFiles": [
{
// Required. Descriptive name of the file.
"name": "golangci linter config",
// Required. Relative path to the file in both root and synchronized repositories.
"path": ".golangci.yml"
}
]
}
```