Skip to content

Git Health - repository hygiene

Git Health looks at how a repository is used, not at the code inside it: stale branches, unreviewed merges, force-pushes to protected branches, oversized commits and similar hygiene signals.

  • It runs server-side against the Git provider using the project’s connected credential - no collector, no CI step. Every project with a credential is eligible. All four Git hosts are covered - GitLab, GitHub, Bitbucket Cloud and Azure DevOps Repos; a rule a host cannot answer (for example the delete-source-branch default on Bitbucket) is skipped, not failed.
  • Scans are queued and processed in the background; you can trigger one from the project or let the scheduled scans run them.
  • Each rule produces a finding with one of four states, and the per-project score is a weighted roll-up - a force-push weighs more than a naming nit.

Beyond branch protection itself, Git Health reads what a merge actually requires and what the protection still lets through:

  • Approvals - a merge request needs at least one approval, at least two, and its author cannot approve it.
  • Merge gates - merging needs a passing pipeline and resolved discussions.
  • Default branch pushes - no force push, and no direct push that skips a merge request. A protected branch can still let maintainers, or people named on the branch, push straight to it: that counts half, while developers being able to push counts nothing. An unprotected branch is reported once, by the branch protection rule; the two push rules wait until the branch is protected.
  • Tags - at least one tag is protected, so a released version cannot be moved or deleted. When a project tracks its releases by tag, the release protection rule checks those tags and this one stands down.

These are read on GitLab and GitHub; Bitbucket Cloud and Azure DevOps keep them in branch policies that are not read yet, so the rules are not applied there. Tag protection is read on GitLab only.

The pipeline rules also look for a static security analysis (SAST) step, container image scanning and a generated software bill of materials (CycloneDX or SPDX), next to secret and dependency scanning. Included files are read too, GitLab templates among them: GitLab’s dependency and container scanning templates produce a CycloneDX SBOM themselves. Merge request and issue templates are checked as files in the repository.

  • Project score and grade with the findings behind them, each explaining what was observed and why it matters.
  • Workspace view - which projects are covered, which have never been scanned (never scanned is reported as unknown, not as healthy).
  • The Administration area shows the same picture installation-wide.
  • Branch rule requires an issue key (GIT_BRANCH_RULE_REQUIRES_ISSUE_KEY, GitLab) - the project’s push rule (branch name regex) is read. It passes when the rule refuses a branch without an issue key (feature/add-login) and accepts one with it (feature/PROJ-123-add-login, or lower case feature/proj-123-...). The rule is judged by what it does to sample names, not by how it is written.
  • Sonar results on the merge request (CI_SONAR_MR_REPORT) - the pipeline writes SonarQube’s result to the merge request: a job that posts it to the description, or Sonar’s own merge request analysis (sonar.pullrequest.key). A pipeline without SonarQube is skipped here; the SonarQube rule reports that gap.
  • Issue keys in lower case count: bugfix/proj-123 names the issue as clearly as bugfix/PROJ-123 in the branch naming rule.
  • Release promotions - a merge request that brings a release/ branch into the default branch carries every issue of the release, so it is left out of the merge request title rule, as merge commits are left out of the commit rule.
  • Wildcard protection - a branch protected by a pattern (release/*) counts as protected, on the release branch rule and everywhere else.
  • Lock files are searched three folders deep (src/<layer>/<Project>/packages.lock.json), code folders first; a search the scan could not finish is skipped, never missing.

These rules no longer run. Findings from earlier scans stay in the history; the rule that answers the same question now is listed beside each one.

RuleReplaced byWhy
REPO_README_PRESENTCompliance DOC_README_EXISTSRepository documents are checked by Compliance; the same missing file was reported in both modules.
REPO_GITIGNORE_PRESENTCompliance REPO_GITIGNORE_EXISTSSame reason.
REPO_SECURITY_MD_PRESENTCompliance SEC_POLICY_EXISTSSame reason.