Skip to main content

git-remote-gcs

PyPI version License Python 3.10+

Use Google Cloud Storage as a Git remote. This is a GCP equivalent of awslabs/git-remote-s3.

It provides a git remote helper that lets you use a GCS bucket as a serverless Git server — no VMs, no Secure Source Manager, just a bucket.

📦 PyPI: https://pypi.org/project/git-remote-gcs/ 💻 GitHub: https://github.com/Vicguin65/git-remote-gcs

Installation

macOS / Linux

pip install git-remote-gcs

That's it. pip installs the git-remote-gcs script to a directory that's typically already on your PATH (e.g. /usr/local/bin or ~/.local/bin).

Verify it works:

which git-remote-gcs

If which returns nothing, add your Python scripts directory to your PATH. Find it with:

python3 -m site --user-base

Then add <that-path>/bin to your shell profile:

# For zsh (default on macOS)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# For bash
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Windows

pip install git-remote-gcs

Important: Git on Windows uses its own shell and cannot find Python scripts on the normal PATH. You need to copy the executable into Git's directory. Run this from an Administrator PowerShell:

copy C:\Users\%USERNAME%\AppData\Roaming\Python\Python313\Scripts\git-remote-gcs.exe "C:\Program Files\Git\mingw64\libexec\git-core\git-remote-gcs.exe"

Note: Your Python version folder (e.g. Python313) may differ. Find the exact path with:

where.exe git-remote-gcs.exe

If that returns nothing, check python -c "import sysconfig; print(sysconfig.get_path('scripts', 'nt_user'))"

Verify it works:

git-remote-gcs
# Should print: Usage: git-remote-gcs <remote-name> <url>

Install from source

git clone https://github.com/Vicguin65/git-remote-gcs.git
cd git-remote-gcs
pip install .

On Windows, also run the copy step above after installing.

Prerequisites

  1. Google Cloud SDK — install from https://cloud.google.com/sdk/docs/install-sdk

  2. Authentication — run once per machine:

gcloud auth application-default login

Other auth methods also work: service account keys via GOOGLE_APPLICATION_CREDENTIALS, Workload Identity (GKE), or attached service accounts (Compute Engine, Cloud Shell).

  1. A GCS bucket (or create one):
gcloud storage buckets create gs://my-git-bucket --location=us-west1
  1. IAM permissions on the bucket. Minimum required:

    • storage.objects.create
    • storage.objects.get
    • storage.objects.delete
    • storage.objects.list

    The simplest way is the Storage Object Admin role on the bucket:

gcloud storage buckets add-iam-policy-binding gs://my-git-bucket \
  --member="user:you@example.com" \
  --role="roles/storage.objectAdmin"

Quick Start

Create a new repo

mkdir my-repo
cd my-repo
git init
git remote add origin gcs://my-git-bucket/my-repo

echo "Hello" > hello.txt
git add -A
git commit -m "initial commit"
git branch -M main
git push --set-upstream origin main

Clone a repo

git clone gcs://my-git-bucket/my-repo my-repo-clone

Branches

cd my-repo
git checkout -b feature-branch
touch new_file.txt
git add -A
git commit -m "new feature"
git push origin feature-branch

Team Setup

To give a colleague access:

1. Grant them IAM access to the bucket:

gcloud storage buckets add-iam-policy-binding gs://my-git-bucket \
  --member="user:colleague@example.com" \
  --role="roles/storage.objectAdmin"

Or grant access to a Google Group:

gcloud storage buckets add-iam-policy-binding gs://my-git-bucket \
  --member="group:devs@example.com" \
  --role="roles/storage.objectAdmin"

For read-only access (clone and pull only), use roles/storage.objectViewer instead.

2. They install on their machine:

pip install git-remote-gcs
gcloud auth application-default login
git clone gcs://my-git-bucket/my-repo

On Windows, they also need to run the copy step from the Windows installation section.

Access Control

Access is controlled entirely through GCS IAM. You can scope permissions per-repo using bucket prefixes and IAM conditions:

gcloud storage buckets add-iam-policy-binding gs://my-git-bucket \
  --member="user:dev@example.com" \
  --role="roles/storage.objectAdmin" \
  --condition="expression=resource.name.startsWith('projects/_/buckets/my-git-bucket/objects/my-repo/'),title=my-repo-access"

Multiple repos can share the same bucket with different prefixes:

gcs://my-git-bucket/repo-a
gcs://my-git-bucket/repo-b
gcs://my-git-bucket/team/project-c

Data Encryption

GCS encrypts all data at rest by default with Google-managed keys. For additional control, use Customer-Managed Encryption Keys (CMEK):

gcloud storage buckets update gs://my-git-bucket \
  --default-encryption-key=projects/PROJECT/locations/LOCATION/keyRings/RING/cryptoKeys/KEY

Concurrent Push Protection

git-remote-gcs uses GCS generation-match preconditions to implement per-reference locking, preventing concurrent pushes to the same branch.

If a lock acquisition fails:

error refs/heads/main "failed to acquire ref lock at my-repo/refs/heads/main/LOCK.lock.
Another client may be pushing. If this persists beyond 60s,
run git-gcs doctor gcs://my-git-bucket/my-repo --lock-ttl 60 to inspect and clear stale locks."

Configure the lock TTL via environment variable:

export GIT_REMOTE_GCS_LOCK_TTL=120  # seconds, default is 60

Managing the Remote

Doctor — diagnose and fix issues

git-gcs doctor gcs://my-git-bucket/my-repo
git-gcs doctor gcs://my-git-bucket/my-repo --delete-bundle  # remove conflicting bundles
git-gcs doctor gcs://my-git-bucket/my-repo --lock-ttl 30    # clear locks older than 30s

Protect/unprotect branches

git-gcs protect gcs://my-git-bucket/my-repo main
git-gcs unprotect gcs://my-git-bucket/my-repo main

Protected branches cannot be force-pushed to or deleted.

Delete a remote branch

git-gcs delete-branch gcs://my-git-bucket/my-repo -b old-feature

Under the Hood

How it works

Bundles are stored in GCS as <prefix>/<ref>/<sha>.bundle.

Push:

  1. Acquire a per-ref lock using GCS generation-match preconditions
  2. Create a git bundle: git bundle create <sha>.bundle <ref>
  3. Upload the bundle to <prefix>/<ref>/<sha>.bundle
  4. Clean up the previous bundle for that ref
  5. Release the lock

Fetch:

  1. List all objects under <prefix>/refs/ to discover refs and SHAs
  2. Download the bundle for each requested ref
  3. Unbundle locally with git bundle unbundle

List:

  1. Scan <prefix>/refs/ for .bundle objects
  2. Extract ref names and SHAs from the object keys
  3. Read <prefix>/HEAD for the default branch

Storage layout

gs://my-git-bucket/my-repo/
├── HEAD                                    # default branch ref
├── refs/
│   ├── heads/
│   │   ├── main/
│   │   │   └── abc123...def.bundle         # branch bundle
│   │   └── feature/
│   │       └── 789abc...012.bundle
│   └── tags/
│       └── v1.0/
│           └── 345def...678.bundle

Debugging

# Verbose output
GIT_REMOTE_GCS_VERBOSE=1 git push origin main

# Or use git's verbosity flag
git -c transfer.verbosity=2 push origin main

Platform Compatibility

macOS Linux Windows
pip install Works directly Works directly Requires extra copy step
Auth gcloud auth application-default login Same Same
GUI clients Terminal-based Git only Same Same

Note: GUI clients like GitHub Desktop do not support custom remote helpers. Use the command line for push/pull/clone, then open the repo in your GUI for commits, diffs, and branch management. VS Code's built-in Git panel may work directly.

Comparison with Alternatives

Feature git-remote-gcs Secure Source Manager GitHub + Cloud Build Gitea on VM
Cost ~$0 (GCS storage) $1,000/mo Free (public) Free tier VM
Managed Yes (GCS) Yes Yes No
IAM integration Native GCP IAM Native GCP IAM Separate None
Setup time Minutes Minutes Minutes 30+ min
UI / PRs No Yes Yes Yes
Serverless Yes Yes N/A No

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

Inspired By

License

Apache-2.0

Metadata

Release files for git-remote-gcs 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for git-remote-gcs 0.1.2
File Size Uploaded
git_remote_gcs-0.1.2.tar.gz 20.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for git-remote-gcs 0.1.2
File Interpreter ABI Platform
git_remote_gcs-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 38.7 kB

Release files / git_remote_gcs-0.1.2.tar.gz

Download URL git_remote_gcs-0.1.2.tar.gz
Size 20.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ca642af6bea9368eebcc0ba42864b4296fa6efceaa83f2f54829b1e490279cbf
BLAKE2b-256 checksum
How to use checksums
eef3ac295df89396bc87769614950acad50007ff5c2d50699ac46d8b24c1ec2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Release files / git_remote_gcs-0.1.2-py3-none-any.whl

Download URL git_remote_gcs-0.1.2-py3-none-any.whl
Size 18.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6221e9c0275f98fe5dd4eadf7cf070a3cd16e9f60ca69aa448ca3041cd6b1c29
BLAKE2b-256 checksum
How to use checksums
5ec86078ede6b76913c1774b11299aadf139a304311205ff4ff19d163b8ba2a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.3

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page