Repository Setup - Creating, Migrating, and Governing Forgejo Repositories

Status: Active Last Updated: 2026-08-26 Category: CI/CD - Forgejo Administration Prerequisites: forgejo-installation, user-management Time: 1-2 hours Tags: forgejo, repositories, migration, branches, templates, git

Summary

This article covers creating repositories in Forgejo (empty, from template, or migrated), setting default branches, configuring protected branches before CI runs, and the housekeeping settings โ€” visibility, LFS, and issue trackers โ€” that determine how smoothly Woodpecker can work with a repo.

๐ŸŽฏ What You'll Learn

By the end of this article, you'll be able to:


Context / Why This Matters

Woodpecker discovers pipelines by reading .woodpecker.yaml from your repo's default branch. That means repository configuration โ€” default branch, protection rules, webhook wiring โ€” directly controls what CI builds and when. Setting up repos consistently also makes org-wide automation (secrets, webhooks, templates) predictable instead of per-repo archaeology.


Implementation / Core Content

Creating a Repository

UI path: + โ†’ New Repository. Key decisions at creation time:

Via API:

curl -s -X POST "https://git.example.com/api/v1/orgs/acme-corp/repos" \
  -H "Authorization: token $FORGEJO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "api-service",
    "private": true,
    "default_branch": "main",
    "auto_init": false,
    "gitignores": "Go",
    "issue_labels": "Default"
  }'

Push existing code in:

cd my-project
git remote rename origin old-origin 2>/dev/null || true
git init -b main 2>/dev/null || true
git add -A && git commit -m "initial import" || true
git remote add origin git@git.example.com:acme-corp/api-service.git
git push -u origin --all
git push origin --tags

Default Branch

The default branch is what CI sees on every push-based trigger and what PRs target by default. Set it at creation, or change later: Repo โ†’ Settings โ†’ Branches โ†’ "Default Branch". Changing it does not move CI config expectations automatically โ€” make sure .woodpecker.yaml exists on the new default.

# Via API
curl -s -X PATCH "https://git.example.com/api/v1/repos/acme-corp/api-service" \
  -H "Authorization: token $FORGEJO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"default_branch":"main"}'

Convention for fogserv homelab projects: main as trunk, release/x.y branches cut per release line, feature branches named type/ticket-slug.

Migrating Repositories

Forgejo's built-in migrator copies git data plus optionally issues, PRs, labels, milestones, releases, and wiki.

UI path: + โ†’ New Migration, pick source type (GitHub, GitLab, Gitea/Forgejo, Git only, ...). For a GitHub source you'll typically need a read token if repos are private.

CLI alternative (server-side):

forgejo migrate \
  --auth-token "$GITHUB_TOKEN" \
  --repo-source url=https://github.com/acme/api-service \
  --repo-destination acme-corp/api-service \
  --issues --pulls --releases --lfs

Migration checklist:

  1. Create the destination repo first (or let the migrator create it).
  2. Enable LFS on both sides if the source uses it.
  3. After migration, verify: git log, open PR count, releases list.
  4. Re-point any external integrations (webhooks, badges) at the new URL.
  5. Keep the source read-only/archive it to avoid split-brain commits.

Protected Branches (Baseline)

Full policy discussion lives in branch-protection, but every repo should have, minimum, on its default branch:

Repo โ†’ Settings โ†’ Branches โ†’ Add New Rule, pattern main. Doing this before the first CI run prevents accidental direct pushes that bypass pipeline validation.

Repository Templates

Any repo can be marked as a template (Settings โ†’ check "Template"). Template contents include the file tree and optionally variables like {REPO_NAME} in filenames/content. Standardize your .woodpecker.yaml, Dockerfile, and linting config this way so new projects start CI-ready:

acme-corp/.repo-template
โ”œโ”€โ”€ .woodpecker.yaml
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ .editorconfig
โ””โ”€โ”€ README.md

New repo โ†’ "Use Template" dropdown at creation.

Housekeeping Settings Worth Reviewing Per Repo

Setting Recommendation
Merge style Allow squash + merge commit; disable rebase-only if history discipline is weak
Issues/PRs Disable unused units to reduce noise
Packages Enable if using Forgejo's container registry (OCI)
LFS Enable for binaries >~1MB; configure .gitattributes first
Archive Set ARCHIVE_UNITS or archive finished projects rather than deleting

Practical Examples

Example 1: Full setup of a new service repo

# 1. Create repo under the org
curl -s -X POST "https://git.example.com/api/v1/orgs/acme-corp/repos" \
  -H "Authorization: token $FORGEJO_TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"worker","private":true,"default_branch":"main","auto_init":false}'

# 2. Push code
git remote add origin git@git.example.com:acme-corp/worker.git
git push -u origin main

# 3. Add pipeline skeleton
cat > .woodpecker.yaml <<'EOF'
when:
  event: [push, pull_request]

steps:
  test:
    image: golang:1.22
    commands:
      - go vet ./...
      - go test ./...
EOF
git add .woodpecker.yaml && git commit -m "ci: add woodpecker pipeline" && git push

# 4. Confirm Woodpecker picked it up (see woodpecker-first-pipeline)

Example 2: Verify a migration integrity spot-check

git clone git@git.example.com:acme-corp/api-service.git && cd api-service
git log --oneline | wc -l                 # compare with source repo
git tag | tail -5                          # tags carried over?
ls .git/lfs 2>/dev/null && echo "LFS present"

Common Pitfalls & Troubleshooting

Problem Cause Fix
Push rejected pre-receive hook declined Branch protection blocks direct push Open a PR, or adjust rule; see branch-protection
CI never triggers on new repo Webhook not created / wrong default branch Re-enable app in Woodpecker or add webhook manually; see webhooks
Migration missing issues/PRs Options unchecked or source API rate-limited Re-run migration with options; use a token to lift rate limits
Default branch changed but CI still builds old one Pipeline file only exists on old branch Commit .woodpecker.yaml to the new default branch
Large push times out over HTTP Big files without LFS Enable LFS and git lfs migrate import --everything
Clone asks for password repeatedly HTTPS remote without credential helper Switch to SSH remote or store token via git config credential.helper

Next Steps / Ops Actions

Sources & Related Articles

External references consulted:

Related knowledge-base articles:

Change Log

2026-08-26

Choose Theme

Your selection is saved locally.

Neural Cacophony
Aperture v2
Flux v1
Mosaic Chaos
Nexus v1
Nexus Zest
Prism v2
Synapse