A Gitlab clone/pull utility for backing up or cloning Gitlab groups
Project description
Gitlabber
A utility to clone and pull GitLab groups, subgroups, group projects or personal user projects based on path selection
Purpose
Gitlabber clones or pulls all projects under a subset of groups / subgroups by building a tree from the GitLab API and allowing you to specify which subset of the tree you want to clone using glob patterns and/or regex expressions.
Installation
System Requirements
Python 3.11 or higher
Git 2.0 or higher
Network access to GitLab instance
Installation Methods
PyPI (recommended):
pip install gitlabberFrom source:
git clone https://github.com/ezbz/gitlabber.git cd gitlabber pip install -e .Optional: Install with secure token storage support:
pip install gitlabber[keyring]You’ll need to create an access token from GitLab with API scopes read_repository and read_api (or api, for GitLab versions <12.0)
Quick Start
# Install gitlabber
pip install gitlabber
# Clone all your GitLab projects
gitlabber -t <your-token> -u <gitlab-url> .
Usage
Arguments can be provided via the CLI arguments directly or via environment variables:
Argument
Flag
Environment Variable
token
-t
GITLAB_TOKEN
url
-u
GITLAB_URL
method
-m
GITLABBER_CLONE_METHOD
naming
-n
GITLABBER_FOLDER_NAMING
include
-i
GITLABBER_INCLUDE
exclude
-x
GITLABBER_EXCLUDE
Secure Token Storage: Gitlabber supports secure token storage using OS-native keyring (Keychain on macOS, Secret Service on Linux, Windows Credential Manager). This allows you to store your GitLab token securely and avoid passing it via CLI or environment variables.
Token Resolution Priority:
CLI argument (-t/--token) - highest priority
Stored token (from secure storage)
Environment variable (GITLAB_TOKEN)
Usage:
# Install keyring (optional, for secure storage) pip install gitlabber[keyring] # Store token securely (one-time setup) gitlabber --store-token -u https://gitlab.com Enter token: [hidden input] Token stored securely in keyring for https://gitlab.com ✓ # Use stored token automatically (no -t flag needed) gitlabber -u https://gitlab.com . # Override with CLI token if needed gitlabber -t <token> -u https://gitlab.com .Note: If keyring is not installed, gitlabber falls back to environment variables or CLI arguments (current behavior).
To view the tree run the command with your includes/excludes and the -p flag. It will print your tree like so:
root [http://gitlab.my.com] ├── group1 [/group1] │ └── subgroup1 [/group1/subgroup1] │ └── project1 [/group1/subgroup1/project1] └── group2 [/group2] ├── subgroup1 [/group2/subgroup1] │ └── project2 [/group2/subgroup1/project2] ├── subgroup2 [/group2/subgroup2] └── subgroup3 [/group2/subgroup3]To see how to use glob patterns and regex to filter tree nodes, see the globre project page.
Include/Exclude patterns do not work at the API level but work on the results returned from the API, for large Gitlab installations this can take a lot of time, if you need to reduce the amound of API calls for such projects use the --group-search parameter to search only for the top level groups the interest you using the Gitlab Group Search API which allows you to do a partial like query for a Group’s path or name
Performance optimization: For large GitLab instances with many groups and projects, use the --api-concurrency option to dramatically speed up tree building. This enables parallel API calls (default: 5 concurrent requests) which can provide 4-6x speedup in real-world scenarios. For example, building a tree with 21 subgroups and 21 projects can be reduced from ~96 seconds (sequential) to ~16-21 seconds (with --api-concurrency 5-10). The -c/--concurrency option controls parallel git operations (cloning/pulling), while --api-concurrency controls parallel API calls (fetching groups/projects). Both can be tuned independently based on your needs.
Cloning vs Pulling: when running Gitlabber consecutively with the same parameters, it will scan the local tree structure; if the project directory exists and is a valid git repository (has .git folder in it) Gitlabber will perform a git pull in the directory, otherwise the project directory will be created and the GitLab project will be cloned into it.
Cloning submodules: use the -r flag to recurse git submodules, uses the --recursive for cloning and utilizes GitPython’s smart update method for updating cloned repositories
Printed Usage:
usage: gitlabber [-h] [-t token] [-T] [-u url] [--verbose] [-p] [--print-format {json,yaml,tree}] [-n {name,path}] [-m {ssh,http}]
[-a {include,exclude,only}] [-i csv] [-x csv] [-c N] [--api-concurrency N] [-r] [-F] [-d] [-s] [-g term] [-U] [-o options] [--version] [--store-token]
[dest]
Gitlabber - clones or pulls entire groups/projects tree from gitlab
positional arguments:
dest destination path for the cloned tree (created if doesn't exist)
options:
-h, --help show this help message and exit
-t token, --token token
gitlab personal access token https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html
-T, --hide-token use an inline URL token (avoids storing the gitlab personal access token in the .git/config)
-u url, --url url base gitlab url (e.g.: 'http://gitlab.mycompany.com')
--verbose print more verbose output
-p, --print print the tree without cloning
--print-format {json,yaml,tree}
print format (default: 'tree')
-n {name,path}, --naming {name,path}
the folder naming strategy for projects from the gitlab API attributes (default: "name")
-m {ssh,http}, --method {ssh,http}
the git transport method to use for cloning (default: "ssh")
--fail-fast exit immediately when encountering discovery errors
-a {include,exclude,only}, --archived {include,exclude,only}
include archived projects and groups in the results (default: "include")
-i csv, --include csv
comma delimited list of glob patterns of paths to projects or groups to clone/pull
-x csv, --exclude csv
comma delimited list of glob patterns of paths to projects or groups to exclude from clone/pull
-c N, --concurrency N
number of concurrent git operations (default: 1)
--api-concurrency N number of concurrent API calls for tree building (default: 5)
-r, --recursive clone/pull git submodules recursively
-F, --use-fetch use git fetch instead of pull for updates (normal repositories with working tree)
--mirror create bare mirror repositories (for backups, automatically uses fetch)
-s, --include-shared include shared projects in the results
-g term, --group-search term
only include groups matching the search term, filtering done at the API level (useful for large projects, see: https://docs.gitlab.com/ee/api/groups.html#search-for-group works with partial names of path or name)
-U, --user-projects fetch only user personal projects (skips the group tree altogether, group related parameters are ignored). Clones personal projects to '{gitlab-username}-personal-projects'
-o options, --git-options options
provide additional options as csv for the git command (e.g., --depth=1). See: clone/multi_options https://gitpython.readthedocs.io/en/stable/reference.html#
--version print the version
--store-token store token securely in OS keyring (requires keyring package)
examples:
clone an entire gitlab tree using a url and a token:
gitlabber -t <personal access token> -u <gitlab url>
only print the gitlab tree:
gitlabber -p .
clone only projects under subgroup 'MySubGroup' to location '~/GitlabRoot':
gitlabber -i '/MyGroup/MySubGroup**' ~/GitlabRoot
clone only projects under group 'MyGroup' excluding any projects under subgroup 'MySubGroup':
gitlabber -i '/MyGroup**' -x '/MyGroup/MySubGroup**' .
clone an entire gitlab tree except projects under groups named 'ArchiveGroup':
gitlabber -x '/ArchiveGroup**' .
clone projects that start with a case insensitive 'w' using a regular expression:
gitlabber -i '/{[w].*}' .
clone the personal projects to username-personal-projects
gitlabber -U .
perform a shallow clone of the git repositories
gitlabber -o "\-\-depth=1," .
speed up tree building for large GitLab instances with parallel API calls (4-6x faster)
# Real-world example: 96s → 16-21s for instances with many subgroups/projects
gitlabber --api-concurrency 10 -t <token> -u <url> .
use both API and git concurrency for maximum performance
# API concurrency speeds up tree discovery, git concurrency speeds up cloning
gitlabber --api-concurrency 5 -c 10 -t <token> -u <url> .
store token securely for future use (one-time setup)
gitlabber --store-token -u https://gitlab.com
use stored token (no -t flag needed)
gitlabber -u https://gitlab.com .
**Performance Results:**
* Sequential (``--api-concurrency 1``): ~96 seconds
* With ``--api-concurrency 5``: ~21 seconds (**4.6x speedup**)
* With ``--api-concurrency 10``: ~16 seconds (**6x speedup**)
*Note: Actual speedup depends on your GitLab instance structure (number of groups, subgroups, and projects). Instances with many nested subgroups benefit most from higher concurrency values.*
Common Use Cases
Clone Specific Groups
# Clone only projects from a specific group
gitlabber -i '/MyGroup/**' .
Exclude Archived Projects
# Clone all non-archived projects
gitlabber -a exclude .
Debugging
You can use the --verbose flag to print Gitlabber debug messages
For more verbose GitLab messages, you can get the GitPython module to print more debug messages by setting the environment variable:
export GIT_PYTHON_TRACE='full'
Troubleshooting
GitlabHttpError: 503: make sure you provide the base URL to your GitLab installation (e.g., https://gitlab.my.com and not https://gitlab.my.com/some/nested/path)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(128) OR ERROR: The project you were looking for could not be found or you don't have permission to view it.: if you are using Git’s SSH method, follow the SSH Guide from Gitlab and ensure you have your SSH key in Gitlab for clone or use the HTTP method (-m http flag)
Known Limitations
Renaming, moving and deleting projects: Gitlabber doesn’t maintain local tree state (projects and groups). For that reason is does not rename move or delete local projects when they are modified on the server. When projects are moved or renamed, Gitlabber will clone them again under their new name or location. When deleted, Gitlabber will not delete the local project.
Folder naming strategy: Consecutively running Gitlabber with different values for the -n parameter will produce undesirable results. Use the same value as previous runs, or simply don’t change it from the default (project name).
If you’re going to clone a large number of projects, observe rate limits for gitlab.com, and for on-premise installations.
Branch Synchronization Issues
Gitlabber’s default pull behavior (git pull -v -- origin) may fail when you have a local branch checked out that no longer exists on the remote repository. This commonly occurs after:
Merging a merge request where the remote branch is automatically deleted
Manual deletion of remote branches
Error Example:
git.exc.GitCommandError: Cmd('git') failed due to: exit code(1)
cmdline: git pull -v -- origin
Workaround: Use the --use-fetch flag instead of the default pull behavior:
gitlabber --use-fetch -t <your-token> -u <gitlab-url> .
Links
Gitlabber tutorial by nsk
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gitlabber-2.1.1.tar.gz.
File metadata
- Download URL: gitlabber-2.1.1.tar.gz
- Upload date:
- Size: 242.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f2c005aaeedf3beee9d8ce6907c03bd857072690007491d78442715d1294129a
|
|
| MD5 |
a384971a12b8b0d1ebfa0c6d1b88a962
|
|
| BLAKE2b-256 |
e521b32ac5dbc7a3032e7830faf6da21b1d78ea52a1a6a1b97e56e24ad6107cf
|
File details
Details for the file gitlabber-2.1.1-py2.py3-none-any.whl.
File metadata
- Download URL: gitlabber-2.1.1-py2.py3-none-any.whl
- Upload date:
- Size: 36.9 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e6d439f50dec56db39036c115ca060d0cc331f7843491b27afadb6016a691595
|
|
| MD5 |
4c9ed3f5bea68575b6bee62a0b61fdc5
|
|
| BLAKE2b-256 |
53ae39aa6a47ef4bf3de5af1169047da86907be8ea3d6ef1f6768d01519c8422
|