1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
# GitSyncer
GitSyncer is a tool for synchronizing git repositories between multiple organizations (e.g., GitHub and Codeberg). It automatically keeps all branches in sync across different git hosting platforms.
## Documentation
📚 **[Full documentation is available in the doc/ directory](doc/README.md)**
- [Architecture Overview](doc/architecture.md) - System design and components
- [API Reference](doc/api-reference.md) - Complete reference of all packages and functions
- [Configuration Guide](doc/configuration.md) - Detailed configuration options
- [Usage Examples](doc/examples.md) - Common usage patterns and workflows
- [Development Guide](doc/development.md) - Contributing and development setup
## Features
- Sync repositories between multiple git organizations
- Automatic branch creation on remotes that don't have them
- Batch sync multiple repositories with a single command
- Sync all public repositories from Codeberg to GitHub
- Sync all public repositories from GitHub to Codeberg
- Automatic repository creation on GitHub and Codeberg
- SSH backup locations with automatic bare repository creation
- One-way backup to private SSH servers (e.g., home NAS)
- Merge conflict detection with clear error messages
- Never deletes branches (only adds/updates)
- GitHub token validation tool
- Opt-in backup mode with --backup flag for resilient offline backups
## Installation
```bash
go build -o gitsyncer ./cmd/gitsyncer
```
## Configuration
Create a `gitsyncer.json` file:
```json
{
"organizations": [
{
"host": "git@codeberg.org",
"name": "yourusername"
},
{
"host": "git@github.com",
"name": "yourusername"
},
{
"host": "user@nas.local:git",
"backupLocation": true
}
],
"repositories": [
"repo1",
"repo2"
]
}
```
## Usage
### Sync a single repository
```bash
./gitsyncer --sync repo-name
# Include backup locations
./gitsyncer --sync repo-name --backup
```
### Sync all configured repositories
```bash
./gitsyncer --sync-all
# Include backup locations
./gitsyncer --sync-all --backup
```
### Sync all public Codeberg repositories to GitHub
```bash
# Dry run - see what would be synced
./gitsyncer --sync-codeberg-public --dry-run
# Actually sync all public repos
./gitsyncer --sync-codeberg-public
# With automatic GitHub repo creation
./gitsyncer --sync-codeberg-public --create-github-repos
```
### Sync all public GitHub repositories to Codeberg
```bash
# Dry run - see what would be synced
./gitsyncer --sync-github-public --dry-run
# Actually sync all public repos
./gitsyncer --sync-github-public
```
### Full bidirectional sync
```bash
# Sync all public repos from both Codeberg and GitHub
# This enables --sync-codeberg-public --sync-github-public
# --create-github-repos --create-codeberg-repos
./gitsyncer --full
# With dry run to see what would happen
./gitsyncer --full --dry-run
```
### List configured organizations
```bash
./gitsyncer --list-orgs
```
### List configured repositories
```bash
./gitsyncer --list-repos
```
### Show version
```bash
./gitsyncer --version
```
### The --backup Flag
The `--backup` flag enables syncing to backup locations configured in your `gitsyncer.json`. This is particularly useful when:
- Your backup server might be offline (e.g., home NAS)
- You want to control when backups happen
- You need to separate regular syncing from backup operations
Without `--backup`: GitSyncer only syncs between primary git hosts (GitHub, Codeberg, etc.)
With `--backup`: GitSyncer also pushes to backup locations marked with `"backupLocation": true`
```bash
# Regular sync (backup locations ignored)
./gitsyncer --sync myrepo
# Sync with backup enabled
./gitsyncer --sync myrepo --backup
```
## How It Works
1. GitSyncer clones the repository from the first configured organization
2. Adds all other organizations as git remotes
3. For each branch:
- Fetches from all remotes
- Merges changes from remotes that have the branch
- Pushes to all remotes (creating branches if needed)
## Branch Exclusion
You can exclude branches from synchronization using regex patterns in your configuration:
```json
{
"organizations": [...],
"repositories": [...],
"exclude_branches": [
"^codex/", // Exclude branches starting with "codex/"
"^temp-", // Exclude branches starting with "temp-"
"-wip$", // Exclude branches ending with "-wip"
"experimental" // Exclude branches containing "experimental"
]
}
```
Excluded branches will be reported during sync but not synchronized.
## SSH Backup Locations
You can configure SSH backup locations for one-way repository backups to private servers:
```json
{
"organizations": [
{
"host": "git@github.com",
"name": "yourusername"
},
{
"host": "paul@t450:git",
"backupLocation": true
}
]
}
```
### How SSH Backup Works
1. **Opt-in feature**: Backup locations are disabled by default. Use the `--backup` flag to enable syncing to them
2. **One-way sync**: Repositories are only pushed TO backup locations, never pulled FROM them
3. **Automatic repository creation**: If a repository doesn't exist on the SSH server, GitSyncer will:
- SSH into the server
- Create the directory structure
- Initialize a bare git repository
4. **Archive functionality**: Repositories that exist only on the backup location are considered archived and won't be synced to other organizations
5. **All branches and tags**: Every branch and tag is pushed to the backup location when `--backup` is used
### SSH Backup Example
```bash
# Configure your gitsyncer.json with an SSH backup location
# Backup locations are DISABLED by default to handle offline servers
# Sync without backup (default behavior)
./gitsyncer --sync myrepo
# Sync WITH backup enabled
./gitsyncer --sync myrepo --backup
# Sync all repositories with backup
./gitsyncer --sync-all --backup
# Full sync with backup
./gitsyncer --full --backup
```
The backup location path format is: `user@host:path/REPONAME.git`
- `user@host`: SSH connection string
- `path`: Base directory for repositories
- `REPONAME.git`: Automatically appended repository name
**Note**: The `--backup` flag is required to sync to backup locations. This allows GitSyncer to work normally even when backup servers are offline or unreachable.
## Example Workflows
### Sync specific repositories
1. Create repositories on all platforms (GitHub, Codeberg, etc.)
2. Add the repository name to your `gitsyncer.json`
3. Run `./gitsyncer --sync repo-name`
4. GitSyncer will:
- Clone from the first organization
- Push all branches to other organizations
- Keep them in sync going forward
### Sync all public Codeberg repositories
1. Ensure Codeberg is in your organizations list
2. Run `./gitsyncer --sync-codeberg-public`
3. GitSyncer will:
- Fetch all public repositories from your Codeberg account
- Sync each one to all other configured organizations
- Skip any that fail (e.g., don't exist on other platforms)
## Error Handling
- **Merge conflicts**: GitSyncer will detect conflicts and exit with an error message
- **Missing repositories**: Must be created manually on all platforms
- **Missing branches**: Automatically created on remotes that don't have them
## License
BSD 2-Clause License. See [LICENSE](LICENSE) file for details.
|