This document outlines the contribution and development practices to ensure a clean and maintainable Git history.
When checking out a new branch from main to work on an issue, give it a name associated with the issue it is addressing
For example branch name: 123-user-management.
Work on your local branch and make as many local commits as needed.
All commits must be signed off to certify that the contributor agrees to the Developer Certificate of Origin (DCO).
This is a legal statement indicating that you wrote the code or have the right to contribute it.
When creating a commit, use the -s flag:
git commit -s -m "feat: add token validation logic"
This will append a Signed-off-by line with your name and email address, matching the information in your Git configuration.
Example:
Signed-off-by: Jane Doe <jane.doe@example.com>
If you forgot to sign off a commit, you can amend the last commit:
git commit --amend -s
Or for multiple commits, you can rebase and add the sign-offs:
git rebase -i HEAD~N # replace N with number of commits to edit
# Then mark each commit with 'edit' and sign off each one:
git commit --amend -s
git rebase --continue
We follow a linear commit history to keep the Git log clean and easy to follow. We should have one compound commit per feature/issue to make it easy to track the project history. This involves the following steps:
Before pushing your branch, always rebase on the latest main:
git fetch origin
git rebase origin/main
If there are any conflicts, resolve them and continue the rebase:
git status # See conflicted files
# Edit and resolve conflicts
git add <resolved-files>
git rebase --continue
Force push your rebased branch to update your pull request:
git push --force-with-lease
When ready to make a Pull request, do the following:
issue number
Add user management (#123)issue, and will also show up in the commit history Author: Jens Jelitto
Reviewers: Bar, Angelo
Issue: /link (if issue is attached)
Description: any additional content description
Once the review process is finished, finalize the PR:
squash and merge (NOT Merge commit!)To maintain clarity and traceability across contributions, all pull requests must adhere to the following:
gh label list for the current set rather than inventing new ones.gh api repos/LFDT-Panurus/panurus/milestones --jq '.[].title' for the current list).Fixes #123 or Closes #123 in the PR body, which GitHub links automatically on creation.
This ensures the PR is formally connected to the issue for proper project tracking and status updates.approve from the maintainers of the project before it can be merged.This ensures that all contributions are tracked, visible on the project board, and aligned with the roadmap.
Using the gh CLI, assignee/labels/milestone/project can all be set in a single gh pr create call:
gh pr create --title "Add user management (#123)" --base main \
--assignee @me \
--label "bug,hardening" \
--milestone "Q3/26" \
--project "Panurus" \
--body "Fixes #123
<description of the problem and how it was addressed>"
Note: GitHub’s Issue Type field (Bug/Task/Feature) does not exist on pull requests — only on issues (see below). There is nothing to set on the PR for it.
Before starting non-trivial work (a bug fix or a new feature), open a GitHub Issue describing the problem or the request — unless one already exists. The issue documents the problem, independent of whatever fix eventually lands; do not write it as if the fix is already known/in progress.
A well-formed issue includes:
Populate the same metadata fields as PRs — Assignee, Labels, Milestone, Project (Panurus) — plus one PR-issues don’t have:
Issue Type (Bug / Task / Feature): a GitHub-native field, distinct from labels. As of this writing, the gh CLI (gh issue create / gh issue edit) has no flag for it — it must be set via the GraphQL API:
# 1. Find the org's issue-type node IDs (one-time lookup, or if they change):
gh api orgs/LFDT-Panurus/issue-types --jq '.[] | {name, node_id}'
# 2. Get the issue's node ID:
gh api repos/LFDT-Panurus/panurus/issues/<N> --jq '.node_id'
# 3. Set the type:
gh api graphql -f query='
mutation {
updateIssueIssueType(input: {issueId: "<issue node_id>", issueTypeId: "<type node_id>"}) {
issue { id }
}
}'
Example creating a fully-populated issue in one command (Issue Type still requires the GraphQL follow-up above):
gh issue create --repo LFDT-Panurus/panurus \
--title "ttx: Transaction.appendPayload overwrites TokenRequest/Transient instead of merging" \
--body "<summary, impact, suggested fix direction>" \
--assignee @me \
--label "bug,ttx,hardening,testing" \
--milestone "Q3/26" \
--project "Panurus"
For larger features or workstreams, create a GitHub Epic to group related issues and provide overarching context. Each epic should include:
Don’t forget to populate the metadata (like Project, Milestone, and so on) for both epics, issues, and PRs.
Example Epic Template:
## Objective
This epic tracks the implementation of <feature/initiative name>, including all tasks required for completion.
## Task List
- #101
- #102
- #103
Github will replace #101 with the title of corresponding Github Issue and report the status as well.
Organizing work in epics ensures better visibility for contributors and maintainers, and helps align development with roadmap goals.
main.