Screenshot from Control Freak rejecting a foxtrot merge.
bit-booster monster

Control Freak - Commit
Checkers and Jira Hooks
for Bitbucket

Documentation
 
September 2020
 

Table of Contents

About The Cloud Version ! (Feb 2024)

Here is a quick 6 minute video showing how to use Control Freak for Bitbucket Cloud:

        youtube.com/watch?v=zWzvsm3OFvk

The cloud version of Control Feak is based on Pull Request Tasks. Control Freak automatically creates these tasks on every pull-request. To use Control Freak (and have it block merges) you must enable the "[x] No unresolved pull request tasks" option under:

<Repository> --> Settings --> Branch restrictions --> [add/edit branch restriction] --> Merge settings.

Control Freak works best with Bitbucket Premium, because the '[x] No unresolved pull request tasks' merge check, while useful, is not enforced under the "Standard" and "Free" plans (the merge button remains clickable). The merge check becomes mandatory on Bitbucket Premium.

It's also important to add a connection to your Jira instance using the "Connections" tab on Control Freak's settings page. Control Freak is not able to re-use the existing Jira connection and requires its own API key.

Introduction

Control Freak - Commit Checkers and Jira Hooks for Bitbucket allows Bitbucket admins to define and encourage consistent git policy across all projects and repositories within their Bitbucket and Bitbucket Datacenter installations.

Advantages

  • Global Git policy configured in one place
  • Branching Model binds rules to branch groups
  • Improved performance
  • Compatible with Fork-Based Workflows

The add-on accomplishes this through independent rule groups. Admins can define Jira policy, branch naming policy, rebase policy, commit authorship policy, etc. The add-on also includes rules to help prevent common nuisances in git repos such as foxtrot merges, empty commits, or accidental multi-rewrite pushes.

A master ruleset is defined once through the global config screen. By default the policy is enabled for all normal non-empty repos, but per-project and per-repo kill switches are available. A subset of the rules can also be overridden per-project or per-repo.

Problem

Bitbucket comes with many powerful configuration options and add-ons to help enforce repository policy (e.g., branch permissions, hooks, merge checks). But setting these up for each newly created repository is repetitive and error-prone, and not everyone with the "Create New Repository" permissions is always aware of their organization's preferred setup.

Control Freak solves this problem by allowing admins to define a global default that is applied to all repositories. Projects and repos where the global settings are inappropriate can opt-out or override to suit their own needs. This results in more repositories that comply with the organization's preferred setup, thanks to this "opt-out" approach rather than Bitbucket's out-of-the-box "opt-in" approach.

Installation Requirements

  1. Install this add-on using Bitbucket's "Manage Add-Ons" page, or from our Atlassian Marketplace page: https://marketplace.atlassian.com/plugins/com.bit-booster.bb.hooks
  2. You must be using version 5.11.0 of Bitbucket Server (or Data Center) or newer.
  3. Optional: to enable the online Jira checking for the Jira Git Policy, your Jira administrator must connect Jira to your Bitbucket instance via the “Application Link” feature of Jira.
     

    If you have more than one Jira instance connected to your Bitbucket instance this add-on will query all Jira instances registered via "Application Links". Control-Freak queries the primary Jira link as well as any secondary links for pertinent Jira tickets.

    (Note: versions older than v2020.09.21 of Control-Freak were limited to only querying the Primary Jira link, but this was fixed in v2020.09.21 to allow querying of all Jira application links).

Enabling Your Global Git Policy

The very top of the global config screen includes the enable/disable control:

Enabled For:
Regular
Repos
Regular
Forks
Personal
Repos
Personal
Forks
Empty
Repos

By default Control Freak is enabled for regular repositories and regular forks, and disabled for all other types. Note: repositories can also be moved between the personal and project areas of Bitbucket. After a move, the configured policy will apply to all new commits, but older commits are grandfathered. The repository types are:

  • Regular Repos - These are regular repositories created using the "new repository" function within a project.
  • Regular Forks - These are forked repositories created using the "fork repository" function where a project is chosen as the target location for the new fork.
  • Personal Repos - These are repositories created using the "new repository" function within a user's personal area in Bitbucket.
  • Personal Forks - These are forked repositories created using the "fork repository" function where a user's personal area is chosen as the target location for the new fork.
  • Empty Repos - Any repository without any commits is considered an empty repository. Disabling the global policy for empty repositories helps admins importing repos from other sources (e.g., Github or after a svn2git conversion), since the git policy is likely to complain about many of the imported commits. After an initial import the policy is enabled for all subsequent commits, since the repository is no longer considered empty.

General Policy

Authorship Policy

Authorship policy inspects the "Author" and "Committer" metadata for each incoming commit, and accepts or rejects the commit based on the selected rules. The user's email address and display name (as recorded in the commit metadata) must match exactly the values stored in Bitbucket to satisfy these rules. By default all three of these rules are disabled.
Authorship Policy:

  • Author must be a valid Bitbucket User - If enabled, all new commits arriving via push (or via merge if coming from a fork) must contain author values that match existing records inside Bitbucket's user database.
    remote: -----
    remote: Commit eafef78364395ce7 rejected: bad author metadata.
    remote: Author "Admin <admin@bit-booster.com>" does not exactly match
    remote: a Bitbucket user record. The closest match is:
    remote:
    remote:     "Administrator <admin@example.com>"
    remote:
    remote: To see the bad commit's metadata:
    remote:
    remote:     git show -s --pretty=fuller eafef78364395ce78a097134e8f8d6
    remote:
    remote: Please have a Bitbucket admin edit the corresponding user record
    remote: so it matches your settings. Alternatively, adjust your own config
    remote: and adjust the problematic commit(s).
    remote: Like so:
    remote:
    remote:     git config --global user.name "Administrator"
    remote:     git config --global user.email admin@example.com
    remote:     git commit --amend --reset-author
    remote:
    remote: Adjusting author metadata in older commits is difficult.
    remote: Detailed instructions here:  https://bit-booster.com/author.html
    remote: -----
    
  • Committer must be a valid Bitbucket User - If enabled, all new commits arriving via push (or via merge if coming from a fork) must contain committer values that match existing records inside Bitbucket's user database.
    We recommend enabling this rule!
    remote: -----
    remote: Commit 3188d70b921955e5 rejected: bad committer metadata.
    remote: Committer "G. Sylvie Davies <sylvie@bit-booster.com>" is not known to Bitbucket.
    remote: To see the bad commit's metadata:
    remote:
    remote:     git show -s --pretty=fuller 3188d70b921955e560800eab04128b
    remote:
    remote: Please have a Bitbucket admin create or adjust a Bitbucket user record
    remote: to match your settings. Alternatively, adjust your own config and amend
    remote: the problematic commit(s) so they match a known user.
    remote: For example:
    remote:
    remote:     git config --global user.name "Known User"
    remote:     git config --global user.email known.user@example.com
    remote:     git rebase --force-rebase
    remote:
    remote: Note: the rebase will drop unpushed merges. Usually that's fine.
    remote: -----
    
  • Committer must be current logged-in user - If enabled, all new commits arriving via push (or via merge if coming from a fork) must contain a committer value that exactly matches the email address and display name of the current logged-in Bitbucket user performing the operation.
    remote: Commit 3188d70b921955e5 rejected: bad committer metadata.
    remote: "G. Sylvie Davies <sylvie@bit-booster.com>" does not match your.
    remote: credentials. You are logged in as:. "Administrator <admin@example.com>".
    remote: To see the bad commit's metadata:
    remote:
    remote:     git show -s --pretty=fuller 3188d70b921955e560800eab04128b
    remote:
    remote: Have "G. Sylvie Davies <sylvie@bit-booster.com>" push their own commits.
    remote: Or use the following git commands to adjust the committer metadata:
    remote:
    remote:     git config --global user.name "Administrator"
    remote:     git config --global user.email admin@example.com
    remote:     git rebase --force-rebase
    remote:
    remote: Note: the rebase will drop unpushed merges. Usually that's fine.
    

Tag Pushing Policy

By default most companies allow tag creation/deletion via Bitbucket UI, REST, and "git push". Unfortunately, allowing tag management through "git push" makes it nearly impossible to permanently delete tags. New tags propagate out to team members naturally via "git pull" and "git fetch", but tag updates (moves) and tag deletes do not. This leads to an undesired scenario where all deleted tags come back from the dead whenever any team member runs "git push --tags". By default Control Freak allows all tag pushes.
Allow Tag Pushes:

  • Never. Tags managed exclusively through Bitbucket UI / REST.
    remote: -----
    remote: PUSHED TAG CREATES/EDITS ARE NOT PERMITTED!
    remote: Sorry, you cannot create tag "1.2.3" via git push.
    remote: Please create tags using Bitbucket's web UI instead.
    remote:
    remote: To reset your tags to match Bitbucket's (if 'origin' is Bitbucket):
    remote:
    remote: git fetch --prune origin "+refs/tags/*:refs/tags/*"
    remote: -----
    
  • Tag deletes allowed. Tag edits and creations rejected.
    remote: -----
    remote: PUSHED TAG DELETES ARE NOT PERMITTED!
    remote: Sorry, you cannot delete tag "signed_tag" via git push.
    remote: Please delete tags using Bitbucket's web UI instead.
    remote:
    remote: To reset your tags to match Bitbucket's (if 'origin' is Bitbucket):
    remote:
    remote: git fetch --prune origin "+refs/tags/*:refs/tags/*"
    remote: -----
    
  • Yes, allow all tag pushes (default).

    All pushes involving tags are allowed with this setting.

Block Large Files

By default git itself has no inherent limit for file sizes, and users sometimes push extremely large files into Bitbucket (often by accident). Since these files will exist forever in the repository's history (even if later commits delete them), many teams prefer to reject pushes that contain large files. Enable this control to block pushes of new large files. Note: all previously accepted large files are grandfathered, and moves/renames to those files are not blocked.

Our implementation has one weakness: if a large binary file is pushed that happens to be byte-identical to a file already present in the repository's history (including dead or unreachable branches), our logic cannot block the push. But such pushes do not increase the repository size, thanks to git's de-duplication logic under the hood.

Large File Policy

remote: -----
remote: Push rejected. Files larger than 8000000 bytes are not permitted
remote: in this repository. The following file is too large:
remote:
remote:   path/to/bigFile.jar (8722752 bytes)
remote:
remote: You can push large files to this repository using 'git lfs':
remote:   git lfs track <path>
remote:
remote: -----

Block Empty Commits

Empty commits contain no delta or patch (no changes to any files or directories), and so they are essentially pointless noise. It's rare for developers to explicitly create and push empty commits (e.g., "git commit --allow-empty"), although they can be used to re-trigger CI builds. Sometimes squashes cause empty commits. We recommend blocking empty commits, but by default Control Freak allows them.
Block Empty Commits On:        
remote: -----
remote: Commit rejected. Empty commits not allowed on "master".
remote:
remote: Commit 78cf7dce4519e9d3 is an empty commit.
remote:
remote: A rebase will remove empty commits:
remote:
remote:   git rebase
remote:
remote: If the rebase complains that origin/master is up to date,
remote: you can use the --force-rebase flag.
remote: -----

Block Multi-Rewrites

This setting keeps developers safe from a pair of dangerous git commands (a.k.a. "git footguns"). One day we'll write a blog post about this, but here's a very brief explanation of the two dangerous commands:
  1. git push --mirror
    This is a highly destructive command for making origin (upstream) exactly match the developer's local clone. When run by accident it can cause total git carnage (hundreds of branch deletes and force-pushes all at once). This command has no warning -- the fury is unleashed immediately.
  2. git push --force (when push.default=matching)
    Before Git v2.x the default behaviour with "git push --force" was to act roughly similar to "git push --mirror" (thanks to the so called "push.default=matching" default configuration). Also, before Git v2.8 "git push" would print a confusing warning message that has likely caused thousands of developers to accidentally preserve this dangerous behaviour on their workstations (even past Git v2.9+).
Control-Freak detects these pushes and blocks them. We suspect Control Freak has prevented large outbreaks of developer confusion, embarrassment, and wasted time repairing damaged repositories across the roughly 500 companies that use Control Freak as of Q4 2019 thanks to this feature (and the fact it is enabled by default). Control Freak Default: Yes - Enabled.
Block Multi-Rewrites:
Prevent "git push -f" disasters if
push.default=matching
     
remote: -----
remote: Push rejected. Multiple history rewrites
remote: in a single push not allowed.
remote:
remote: Is your "push.default" config is set to "matching"?
remote: Try setting it to "simple" instead.
remote:
remote: Trying to mirror a repo? In that case, disable
remote: "Control Freak" for this repository.
remote: (Repository Settings -> Control Freak)
remote: -----

Foxtrot Policy

We wrote a long blog post about Foxtrot merges. Here's the shorter version: default "git pull" behaviour often creates a merge object that swaps the mainline for the feature branch in the git history, making historical analysis of mainlines difficult. Try to get developers to use "git pull --rebase" instead of regular "git pull". But in case they forget, enable this control across all branches to keep mainlines safe from nuisance foxtrot merges. Control Freak Default: Foxtrot Merges Blocked On All Branches.
Block Foxtrot Merges On:        
   
remote: -----
remote: Commit rejected. Foxtrot merges not allowed on "master".
remote:
remote: Commit f4294cff03e5654f contains a foxtrot merge.
remote: A rebase will repair the problem:
remote:
remote:   git rebase
remote:
remote: Alternatively, redo the merge in the opposite direction.
remote: -----

Branch Naming Policy

Controls how new branches get named. This control checks branches created via "git push", Bitbucket Web UI, Bitbucket REST, and even new branches created from the Jira Web UI.

Note: configure the branching model by clicking: [Repository] --> Settings --> Branching Model.

New Branch Names
Must Match:


remote: -----
remote: Push rejected branch name: "abc".
remote: New branches must comply with the repository's branching model.
remote: Allowed names: bugfix/*, feature/*, hotfix/*, release/*
remote: -----
remote: -----
remote: Push rejected branch name: "abc".
remote: New branch names must contain a Jira ticket.
remote: -----
remote: -----
remote: Push rejected new branch: "ABC-1"
remote: Your Bitbucket instance does not have an application link to a Jira instance.
remote: Please configure your Bitbucket instance.
remote: (Or disable the Jira branch check of this global hook.)
remote: -----
remote: -----
remote: New branch names must contain a Jira ticket, but Bitbucket
remote: cannot access Jira to see if "[ABC-1]" exists.
remote: Your Bitbucket account is missing OAUTH credentials into Jira.
remote:
remote: Use this URL to set that up:
remote: http://localhost:7990/bitbucket/plugins/servlet/applinks/oauth/login-dance/authorize
remote: -----
remote: -----
remote: Push rejected new branch: "ABC-1".
remote: ticket "ABC-1" does not exist in Jira.
remote: -----
remote: -----
remote: Push rejected branch name: "ABC-1"
remote: New branches must satisfy the configured branch regex.
remote: Failed Regex: (.*xyz)
remote: -----

Branch Pushing Policy (a.k.a. Protected Branches)

Bitbucket already supports Protected Branches out-of-the-box, so why re-invent the wheel with Control Freak? Three reasons:
  1. Bitbucket does not give admins a way to configure and enforce these policies globally. (Bitbucket's highest level-of-granularity for these controls is per-project).
  2. Bitbucket's implementation of the "Always Require Pull Requests" control has a loophole: only existing branches are checked. Developers can push unreviewed work by pushing a new branch.
  3. Control Freak uses safer defaults for these controls: force-pushes and deletes to develop, master, and release/* are disabled immediately when a Bitbucket administrator installs Control Freak.
Block Branch Deletes On:        
Block History Rewrites On:
Block "force pushes" 
       
Always Require Pull-Requests:        
remote: -----
remote: Push rejected.
remote: You are not allowed to delete branch "master".
remote: -----
remote: -----
remote: Push rejected.
remote: History rewrites not allowed on "release/ABC-1".
remote: -----
remote: -----
remote: Push rejected. Direct pushes not allowed on "release/ABC-1".
remote: This branch can only be modified through pull requests.
remote: -----
remote: -----
remote: Push rejected new branch "release/v1.2.X".
remote: Commits on the new branch MUST arrive via pull-request,
remote: and the starting-point (2e633566324f9087e93c49b9b0c5fc35601d5add)
remote: for this new branch has never passed through a pull-request.
remote: -----

Pull Request Policy

The controls below only apply to pull-requests. Direct pushes do not trigger these controls, and so to properly enforce these policies on a given branch, you must also set the Always Require Pull-Requests control.

Rebase & Squash Policy

These settings are used to enforce specific structural constraints on the branch-to-be-merged before it can be merged. The final merge itself will not necessarily be a "--ff" or "--squash" merge, since the underlying merge mechanics are controlled by the merge strategies Bitbucket is configured to use, and not by Control Freak.

For all practical purposes, "Require Fast-Forwardable Merges" is equivalent to enforcing a rebase-before-merge policy on the selected branches (especially if foxtrots are blocked). We recommend setting the "--ff" merge strategy as your default strategy if enabling this control. Set the "--ff" merge strategy per-project in Bitbucket and enjoy the resulting extra clean git commit history. Note: we do NOT recommend setting "--ff-only" as the default strategy, since that makes it impossible to merge pull-requests that span long-lived branches. We think "--ff" is the better choice.

Notice that both of these controls say "Merges-between not blocked." This is important, since it essentially allows admins to partition branches into two sets: long-lived and short-lived. The selected branches become the long-lived branches, and rebases/squashes between them are not required (and hopefully disallowed via other controls above).

Require Fast-Forwardable Merges Into:
Merges-between not blocked  
       
Require Squashed Merges Into:
Merges-between not blocked  
       
Merge issues

There is 1 issue preventing you from merging this pull request.

  • Control Freak: [master] only permits fast-forward merges - you must rebase [TKT-123]
Merge issues

There is 1 issue preventing you from merging this pull request.

  • Control Freak: [master] only permits merges from squashed branches, but [TKT-123] has 2 commits

Approval Policy

Bitbucket natively provides similar functionality (via the "Minimum Approvals" merge check as well as the default reviewers feature), but Bitbucket's features cannot be configured or activated globally. Control Freak lets admins define a default global Approval Policy, and further enhances these checks to better account for self-approvals and read-only users.

Regarding self-approvals, out of the box, Bitbucket does not allow the user that created the pull-request to approve it, but that user might not be the same user who authored the commits. Administrators can check the "Ignore self-approvals" control here to further restrict the set of users who are allowed to approve the pull-request. Note: self-approvals are still permitted, but they don't count towards clearing the vote threshold (they become non-binding informational votes, similar to a +1 in Gerrit).

Control Freak examines the GIT_AUTHOR_EMAIL value inside each commit on the pull-request to determine if votes should be categorized as self-approvals or not. Control Freak also examines the GIT_COMMITTER_EMAIL value inside each commit. This means users that rebase or amend other people's work will also have their approvals on the pull-request ignored. This control works best if Authorship Policy is active with the "Committer must be current logged-in User" setting, otherwise users can circumvent Approval Policy by using coworker metadata in their commits instead of their own.

Read-only users can be a problem in organizations that allow some repositories to be "public" within their on-prem Bitbucket instance. Read-only users can contribute positive pull-request reviews to these "public" repositories, and Bitbucket's native "Minimum Approvals" merge-check allows those reviews to count towards clearing the threshold. Control Freak can be configured to either count such read-only reviews or ignore them.

All of the Approval Policy controls provided by Control Freak require co-installation of our paid PR-Booster plugin.

Approval Policy

Approval Policy Applies To        
Merge issues

There is 1 issue preventing you from merging this pull request.

  • Control Freak: Pull requests into [master] require at least 1 approval (from users with write access). (Note: currently ignoring 1 approval from a user with commits on the source branch).

Disapproval Policy

Controls whether pull-requests with "needs-work" reviews are allowed to merge. Essentially establishes a "Gerrit" style of code review, with "needs-work" reviews equivalent to a -2 vote in Gerrit. Unlike the Approval Policy (above), Control Freak does not offer an ability to ignore self-disapprovals since self-disapprovals should be taken seriously. Enabling disapproval policy requires co-installation of our paid PR-Booster plugin.

Disapproval Policy
Disapproval Policy Applies To        
Merge issues

There is 1 issue preventing you from merging this pull request.

  • Control Freak: Pull requests into [master] with 1 or more 'Needs Work' reviews (from users with write access) are not allowed to merge.

Jira Policy

We call this section Jira Policy, but it could also be called "Commit Message Policy", since many of the controls here can be used without Jira. The top-level control ("Apply Jira Policy Against") specifies the branches that will be protected by this section. Branches that fall outside the selected choices are ignored and their commit messages are free to contain anything.

Notice also how this top-level control says "Merges-between not blocked." This is important, since it allows commits to merge back and forth between master, develop, production, and release/* branches (assuming those are the protected branches) without re-triggering additional Jira checks. Only when merges and pushes transition a commit from an unprotected branch to a protected branch do the Jira checks get triggered. Commits that exist only on a developer's workstation are always considered unprotected.

Current StatusActive  Edit pending...
Apply Jira Policy Against
Merges-between not blocked
       
   

General Rules (No Connection To Jira Required)

The "reference at least one Jira ticket" here is an offline check. It does not check if any identified tickets actually exist in Jira. As long as some text within the commit message looks like a Jira ticket (e.g., "TKT-123"), then the check is satisfied. The "Advanced Settings" below further specify exactly how Control Freak should look for these Jira tickets within the commit message (e.g., within brackets or not, first-line or anywhere, etc), but the underlying regex itself is hard-coded to "[A-Z][A-Z0-9]*-\\d+" and cannot be changed.

The 2nd control, "Match regex," checks that all commit messages satisfy the supplied regular expression, and has nothing to do with Jira.

Note: the "ignore submodule updates" exemption, when enabled, ignores commits that contain exclusively submodule updates. If a commit contains a mix of regular edits and submodule updates, then all checks under Jira Policy are applied.

Commit Messages Must
Jira Policy Exemptions


(requires PR-Booster add-on).

Quick Note: Ignoring Clean Rebases / Cherry-Picks

By default the "Ignore clean rebases and cherry-picks" Jira exemption is enabled. This helps in situations where Jira online checks were initially satisfied (e.g., valid-status, valid-assignee), and the commits themselves have not been modified in any way, but for various reasons a rebase or cherry-pick is now required. As long as the rebase or cherry-pick is clean (the underlying patch is unchanged) this exemption allows the commits through, even if Jira status or assignee has now changed (e.g., perhaps the ticket is now "Closed" but the git commit needs to be back-ported to an older release through a cherry-pick).
  • The rebase detection is limited to a quick check of the local branch compared to the upstream branch (e.g., "feature/TKT-123" rebased and then pushed to "origin/feature/TKT-123"). A rebase that is subsequently pushed as a brand-new branch will not be detected and will trigger all the normal Jira checks (e.g., "feature/TKT-123" rebased and then pushed to "origin/feature/TKT-123-rebased"). Any conflict resolutions during the rebase will also make the push ineligble for this exemption.
  • The cherry-pick detection only works if the cherry-pick is done with the "-x" option ("git cherry-pick -x <commit-id>"). In other words the commit-message must contains the text "(cherry picked from commit <commit-id>)" in order for the cherry-pick exemption to work. In case you are wondering, yes, PR-Booster does its cherry-picks using the "-x" option.

Ticket Checks (Require A Connection To Jira)

These are the standard online checks that Jira commit checkers are expected to do. Since v2020.09.21 Control-Freak queries the "Primary Jira" application link as well as all secondary application links.

Quick Note: Concerning Multi-Jira Environments

Control-Freak maintains an internal mapping of Jira project affinities against the application links to minimize network traffic. This means that if a given Jira instance returns valid data for a given ticket (e.g., MYPROJ-123), all subsequent Jira ticket queries against that project will only ever be sent to that same Jira instance. For example a later query for MYPROJ-234 would only be sent to the same Jira instance that returned valid data for MYPROJ-123 - all other Jira application links would be ignored in this example. Control-Freak assumes a company would never run two distinct MYPROJ Jira projects in parallel on two different Jira instances.
Jira References Must


Invalid statuses:

Project Whitelist (Requires A Connection To Jira)

A given "git push" might refer to several Jira tickets, but sometimes organizations want the Jira validation checks to only apply to a subset of those tickets. The Project Whitelist gives organizations a way to specify that subset. For example, a commit message might say:
"ABC-323 - fix for downstream problem in XYZ-2832"
If the whitelist only contains project "ABC" then only the "ABC-323" ticket will have the online checks applied (e.g., match JQL, match assignee, valid status, etc). The "XYZ-2832" ticket will be ignored. This control is normally left blank at the Global level and overridden with specific projects at the Project and Repository levels. If the whitelist is empty (the default), then the "Ticket Checks" are applied to all Jira tickets found in the pertinent commit messages.

Jira Project Whitelist
Limit Jira checks to these projects

Advanced Settings (No Connection To Jira Required)

Look for Jira References
Only Check Jiras In Brackets
"[TKT-8, TKT-9] UTF-8 bugs in TKT-5"

Jira Project Blacklist
Ignore these Jira imposters
remote: -----
remote: Commit 347f2a9089f5b39a rejected.
remote: It does not reference a Jira ticket in its commit message.
remote: Note: Jira references must be in the first line of the commit message.
remote:       Also, they must be in brackets, e.g., [TKT-123].
remote:
remote: To see the commit message:
remote:
remote:   git show -s 347f2a9089f5b39a
remote:
remote: To edit the commit message:
remote:
remote:   git rebase --interactive
remote:
remote: (Mark the commits to edit with 'reword' in the dialog).
remote: -----
remote: -----
remote: Commit messages on "master" must reference valid Jira tickets,
remote: but Bitbucket cannot access Jira to see if "[ABC-1]" exists.
remote: Your Bitbucket account is missing OAUTH credentials into Jira.
remote:
remote: Use this URL to set that up:
remote: http://localhost:7990/bitbucket/plugins/servlet/applinks/oauth/login-dance/authorize
remote: -----
remote: -----
remote: Commit rejected.
remote: Commits on "master" must satisfy Jira policy.
remote: The following Jira tickets do not exist on your Jira server:
remote:
remote:   [ABC-1].
remote:
remote: Please remove references to those tickets from your commit messages.
remote: -----
remote: -----
remote: Push rejected. Commits to "master" must satisfy Jira policy.
remote: The following Jira tickets have invalid statuses for receiving commits:
remote:
remote:   [ABC-1] - Done.
remote:
remote: Either remove references to those tickets from your commit messages,
remote: or adjust the tickets in Jira so they satisfy the status check.
remote: -----
remote: -----
remote: Push rejected. Commits to "master" must satisfy Jira policy.
remote: Some referenced Jira tickets failed the JQL validation check.
remote:
remote: JQL:   "TYPE != task"
remote:
remote: Failing Jira tickets:
remote:
remote:   [ABC-1].
remote:
remote: Either remove references to those tickets from your commit messages,
remote: or adjust the tickets in Jira so they satisfy the JQL validation.
remote: -----

remote: -----
remote: Push rejected.
remote: Commits to "master" must satisfy Jira policy.
remote: Commit 0001b282b756e1d1 was authored by [sylvie@bit-booster.com],
remote: but "TKT-1" is currently assigned to [unassigned].
remote: -----