Skip to main content

BranchRift

https://github.com/user-attachments/assets/2c032aa3-86f6-44b4-a3fc-86d83c5ecdc7

See integration risk before branches come back together.

See branch divergence, same-path collisions, ownership gaps, and Git LFS readiness before integration — without modifying your repository.

BranchRift is a read-only Git CLI that surfaces branch divergence, same-path collisions, ownership gaps, binary-sensitive changes, and Git LFS readiness before integration. It is for developers and small teams that want a repeatable integration check before merging, promoting, or reviewing a branch.

Two branches touched the same .umap. Know before you integrate.

Source, configuration, assets, and other Git changes share the same report. Paths classified as asset or map, including .uasset and .umap, are treated as binary-sensitive and checked for Git LFS readiness. BranchRift does not inspect the contents of those files, does not predict merge conflicts, and does not modify the repository.

PyPI Python Tests License

BranchRift was formerly released as Repo Preflight. The legacy preflight command remains available in v0.2.0 for compatibility.

Repository: https://github.com/Kaan081/branchrift Issues: https://github.com/Kaan081/branchrift/issues

It answers questions such as:

  • Did the base and feature branch diverge?
  • Can this branch still fast-forward?
  • Did both sides modify the same repository path?
  • Is that collision a binary-sensitive .uasset or .umap?
  • Are Git LFS-managed files actually ready in the current checkout?
  • Did a change cross an ownership boundary?
  • Which changed files deserve manual review?
  • Which verification steps should happen before integration?

BranchRift is intentionally advisory.

It does not merge, checkout, pull, commit, delete, modify, or automatically approve repository changes.


Why this exists

A normal Git diff tells you what changed.

Before integration, teams often need a different view:

What could make this branch expensive or risky to integrate?

BranchRift combines several signals that are normally inspected separately:

  • Git topology;
  • same-path changes on both sides of a branch;
  • binary-sensitive files;
  • Git LFS readiness;
  • repository ownership;
  • governance gaps;
  • technical-risk signals;
  • required verification;
  • focused manual-review paths.

For Unreal Engine teams using Git and Git LFS, one especially useful case is simple:

Two branches touched the same .umap. Know before you integrate.

BranchRift does not replace Git, Git LFS, file locking, code review, CI, or your source-control workflow.

It adds a read-only pre-integration view on top of them.


Quick start

Install with pipx:

pipx install branchrift

Or with pip:

pip install branchrift

Create .preflight.json in the repository root:

{
  "ownership": [
    {
      "match": "prefix",
      "path": "Source/",
      "owner": "Code"
    },
    {
      "match": "prefix",
      "path": "Content/",
      "owner": "Content"
    }
  ]
}

Then run:

branchrift --base main

Or inspect another fetched branch without checking it out:

branchrift --base main --head origin/feature/environment-pass

The legacy preflight command remains available in v0.2.0 for compatibility.


Example: catch integration risk before merge

A report can surface a divergent branch, a same-path Unreal map collision, and LFS readiness in one run. The block below is an illustration of the current terminal report shape. The revisions and paths are examples, not a recorded run.

=== BranchRift ===
Analyzed:
  Base: main
        0123456789abcdef0123456789abcdef01234567
  Head: HEAD
        fedcba9876543210fedcba9876543210fedcba98
  Merge base: abcdefabcdefabcdefabcdefabcdefabcdefabcd
  Comparison: merge-base...head
  Head is current checkout: yes
  Current branch: feature/environment-pass
  Repository state: CLEAN

What changed:
  14 files changed
  Technical risk: MEDIUM
  High risk: 0
  Medium risk: 14
  Low risk: 0
  Git status mix: A=12, M=2
  File types: asset=12, map=1, source=1
  Owners: Code=1, Content=13

  Source/config:
    Source/Game/Inventory.cpp

  Binary:
    Content/Maps/L_Main.umap

Repository readiness:
  Content/Maps/L_Main.umap
    LFS-managed: yes
    State: pointer
    Readiness: attention

Integration:
  Topology: DIVERGED
  Fast-forward eligible: no
  Ahead: 7
  Behind: 4
  Same-path collisions: 2
  Binary-sensitive collisions: 1
    - Content/Maps/L_Main.umap [map, BINARY-SENSITIVE]
    - Source/Game/Inventory.cpp [source]

Governance:
  PASS

Required verification:
  - build verification
  - map integration verification
  Manual review: 2 files
    - Content/Maps/L_Main.umap
    - Source/Game/Inventory.cpp

A collision means the same repository path changed on both sides since the merge-base.

It does not mean BranchRift is claiming that Git will definitely produce a textual merge conflict.

For binary files such as .uasset and .umap, BranchRift marks the overlap as BINARY-SENSITIVE instead of pretending it can inspect their internal semantics.


What BranchRift reports

BranchRift currently reports:

  • requested base and head revisions;
  • resolved commit SHAs;
  • merge-base;
  • ahead/behind counts;
  • topology relationship;
  • fast-forward eligibility;
  • same-path branch collisions;
  • binary-sensitive asset/map collisions;
  • conservative exact text change facts;
  • Git LFS state;
  • working-tree readiness;
  • configurable repository ownership;
  • ownership gaps;
  • ownership-boundary crossings;
  • technical-risk signals;
  • required verification checks;
  • focused manual-review paths;
  • dirty working-tree state;
  • revision provenance;
  • human-readable terminal output;
  • deterministic JSON output.

Design principles

BranchRift is deliberately:

  • read-only — it never mutates the repository;
  • conservative — it does not invent semantics it cannot prove;
  • explicit — topology, provenance, readiness, and uncertainty are visible;
  • automation-friendly — terminal and JSON output are both supported;
  • Git-native — it works with an existing Git workflow instead of replacing source control;
  • focused — it prioritizes integration signals instead of trying to become a universal repository analyzer.

Requirements

  • Python 3.10+
  • Git available on PATH

Runtime dependencies:

  • Python standard library only

Git LFS is optional.

When Git LFS is unavailable, source-only analysis can still complete, while LFS-specific information may become unknown.


Installation

Recommended isolated CLI installation:

pipx install branchrift

Standard Python installation:

pip install branchrift

Verify:

branchrift --help

The legacy preflight command remains available in v0.2.0 for compatibility.


Install for development

Clone the repository:

git clone https://github.com/Kaan081/branchrift.git
cd branchrift

Install in editable mode:

python -m pip install -e .

Install test dependencies:

python -m pip install -e '.[dev]'

Run the suite:

python -m pytest -q

Configuration

BranchRift reads repository policy from .preflight.json by default.

A minimal configuration requires ownership rules:

{
  "ownership": [
    {
      "match": "prefix",
      "path": "src/",
      "owner": "Backend"
    },
    {
      "match": "path_exact",
      "path": "Dockerfile",
      "owner": "Platform"
    }
  ]
}

ownership is required.

Governance thresholds and default file-type rules are provided automatically unless overridden.

You can also use a config file elsewhere:

branchrift --base main --config /path/to/preflight.json

Ownership matching

A repository can contain many ownership rules.

Each changed path resolves to one effective owner.

Prefix ownership

A prefix rule owns a repository subtree:

{
  "match": "prefix",
  "path": "src/payment/",
  "owner": "Payments"
}

Exact-path ownership

A path_exact rule owns one repository-relative path:

{
  "match": "path_exact",
  "path": "Dockerfile",
  "owner": "Platform"
}

When multiple ownership rules match:

  1. the most-specific path wins;
  2. an exact-path rule wins over an equivalent prefix rule.

Prefix matching is path-segment aware.

For example:

src

matches:

src/app.py

but does not match:

src2/app.py

Equivalent prefix spellings such as:

src
src/
src\

are canonicalized consistently.

An unmatched path becomes Unknown.

Analysis continues, but the path is reported as an ownership governance gap.

BranchRift currently resolves one effective owner per path. Multiple simultaneous co-owners are not modeled.


Running BranchRift

Compare the current checked-out revision against main:

branchrift --base main

Compare the current checked-out revision against dev:

branchrift --base dev

Analyze another fetched branch without checking it out:

branchrift --base main --head origin/feature/my-change

Use an explicit configuration file:

branchrift --base main --config /path/to/preflight.json

Produce machine-readable JSON:

branchrift --base main --json

Revision topology

BranchRift resolves both revisions to commit SHAs and reports their relationship.

Possible topology relationships include:

  • SAME
  • LINEAR
  • HEAD_BEHIND
  • DIVERGED

The report also includes:

  • ahead count;
  • behind count;
  • merge-base;
  • fast-forward eligibility.

Example:

Integration:
  Topology: DIVERGED
  Fast-forward eligible: no
  Ahead: 7
  Behind: 4

This is advisory information.

BranchRift does not automatically merge or block the branch.


Same-path collisions

A collision means that the same repository path changed independently on both sides since the merge-base.

Conceptually:

merge-base -> base side changed path X
merge-base -> head side changed path X

then:

path X = collision

Example:

Integration:
  Same-path collisions: 2
  Binary-sensitive collisions: 1
    - Content/Maps/L_Main.umap [map, BINARY-SENSITIVE]
    - src/app.py [source]

A collision is not a prediction that Git must produce a merge conflict.

It is an integration-review signal.

Binary-sensitive collisions

Files classified as asset or map are treated as binary-sensitive.

For Unreal projects this includes:

  • .uasset
  • .umap

BranchRift does not claim to inspect semantic changes inside these files.

Rename behavior

Collision detection is intentionally path-based and uses path-string overlap.

It does not currently model rename identity when calculating same-path collisions.


Exact change facts

BranchRift can extract conservative facts from text diffs.

These facts are literal observations from the merge-base unified diff.

They are not semantic code analysis.

A value_changed fact is recorded only when one removed line and one added line assign the same key to different scalar values.

Other meaningful text changes can appear as:

  • line_added
  • line_removed

For example:

max_players: 4 -> 8

BranchRift intentionally avoids pretending to understand what that change means to the application.

Binary files

Binary diffs and files classified as asset or map do not produce internal change facts.

BranchRift does not claim to inspect internal Unreal asset/map contents.

Git LFS pointer metadata

A valid Git LFS pointer contains transport metadata such as:

version
oid
size

When the changed content is itself a valid LFS pointer, those transport lines are not reported as meaningful exact change facts.

Ordinary source text that happens to contain words such as size or oid is not suppressed.


Binary and Git LFS readiness

Asset and map changes receive readiness information.

A changed path managed by Git LFS can also receive a readiness record even when its semantic file type remains other.

For example, .wav is not classified as an asset by default, but it can still receive LFS readiness information if Git attributes identify it as LFS-managed.

Example:

Repository readiness:
  Content/Maps/L_Main.umap
    LFS-managed: yes
    State: hydrated
    Readiness: ready

Possible states can include:

  • hydrated;
  • pointer;
  • missing;
  • unknown;
  • not LFS-managed.

Current checkout

When the analyzed revision is the current checkout, BranchRift can use working-tree state and Git LFS information to determine readiness.

A hydrated LFS file can be reported as ready.

A pointer left in the working tree can require attention.

Historical or non-current revisions

When --head is not the currently checked-out commit, BranchRift does not incorrectly apply current working-tree hydration state to that historical revision.

Instead, readiness can become:

unknown

with the reason:

analyzed_head_not_current_checkout

This is intentional.

The tool prefers explicit uncertainty over a misleading conclusion.


Detached HEAD support

BranchRift supports SHA-based analysis from detached HEAD checkouts.

A detached checkout is reported as:

DETACHED

Topology, collisions, change facts, provenance, and revision analysis remain commit/SHA based.

This is useful for environments where a branch name is not available, including some CI workflows.


Revision provenance

Every report records which revisions were actually analyzed.

This includes:

  • requested base;
  • resolved base SHA;
  • requested head;
  • resolved head SHA;
  • merge-base SHA;
  • comparison range;
  • whether the analyzed head is the current checkout.

Example:

Analyzed:
  Base: main
        0123456789abcdef0123456789abcdef01234567
  Head: origin/feature/test
        fedcba9876543210fedcba9876543210fedcba98
  Merge base: abcdefabcdefabcdefabcdefabcdefabcdefabcd
  Comparison: merge-base...head
  Head is current checkout: no

This makes the report auditable and avoids ambiguity about which repository state produced a result.


Dirty working tree

BranchRift reports whether the current worktree is clean or dirty.

Example:

Repository state: DIRTY
Warning: uncommitted changes are not included in the branch diff.

The branch analysis remains revision-based.

A dirty worktree is reported as context rather than silently mixed into the comparison.


Redirecting JSON output

JSON output is available with:

branchrift --base main --json

If shell redirection creates the output file inside the repository:

branchrift --base main --json > report.json

the shell creates report.json before BranchRift begins.

The repository may therefore correctly appear as DIRTY.

Redirect outside the inspected repository if you need the worktree state to remain unchanged.


Git command timeouts

Git operations have timeout budgets based on expected cost.

Operation class Budget Examples
fast 15s revision lookup, current branch, merge-base
normal 30s name-status, worktree status, check-attr
expensive 90s unified diff, collision scan, git lfs ls-files

A timeout becomes a GitError.

BranchRift does not silently return a partial report after a Git timeout.


UTF-8 and terminal output

Git stdout and stderr are decoded as UTF-8 on Windows and Linux.

This avoids relying on the Windows ANSI code page for Git output.

Valid Unicode text such as:

—
→
çağrı
İstanbul

is preserved internally.

If the active terminal encoding cannot represent a character, BranchRift escapes that character deterministically at the output boundary instead of crashing.

For example:

→

can become:

\u2192

on a limited terminal encoding.

JSON output keeps normal json.dumps escaping behavior.


Bounded terminal output

Large repositories can produce long manual-review lists.

Terminal output therefore shows at most 20 manual-review paths.

For example:

Manual review: 57 files
  - path/one
  - path/two
  ...
  ... 37 more paths omitted

The full list is still available in JSON output.

This keeps interactive output readable without discarding machine-readable information.


File classification

Default semantic file types include:

  • source
  • asset
  • map
  • build_config
  • fallback other

Default examples include:

Source

Extensions such as:

.py
.c
.cpp
.h
.hpp
.cs
.js
.ts
.java
.go
.rs

Assets

.uasset
.fbx
.blend

Maps

.umap

Build/config

Examples include:

Dockerfile
Makefile
CMakeLists.txt
Jenkinsfile
Procfile
.github/workflows/
.gradle

Classification precedence is:

  1. exact filename;
  2. most-specific path prefix;
  3. extension;
  4. other.

Custom file_types rules replace the defaults.


Governance

BranchRift separates technical risk from governance state.

Default governance configuration:

{
  "critical_escalation": true,
  "critical_unknown_count": 5,
  "critical_unknown_ratio": 0.25
}

Ownership gaps initially produce:

ATTENTION

When configured count/ratio thresholds are crossed, governance can escalate.

A confirmed ownership-boundary crossing is treated as critical governance information.

Governance status does not automatically block the repository.

BranchRift remains advisory.


Required verification

Changed file types can produce targeted verification requirements.

Examples include:

build verification
asset verification
map integration verification

The goal is not to claim that a change is correct.

The goal is to make the required human or automated verification explicit.


Exit codes

Code Meaning
0 Analysis completed successfully
2 Configuration error
3 Git/repository/revision error
4 Known BranchRift domain error

A completed analysis still returns 0 when it discovers:

  • high technical risk;
  • critical governance;
  • collisions;
  • a dirty worktree;
  • required manual review.

BranchRift is advisory in the current release.


Security model

BranchRift is intentionally read-only.

The CLI:

  • never uses shell=True;
  • passes Git arguments as an argument list;
  • validates user-supplied Git revision arguments;
  • checks Git return codes;
  • handles Git stderr explicitly;
  • applies Git command timeouts;
  • disables external diff helpers during diff inspection;
  • disables textconv helpers during diff inspection;
  • disables fsmonitor hooks during worktree status inspection;
  • escapes terminal control characters from repository/config-derived display text;
  • does not execute commands from .preflight.json;
  • does not require API keys;
  • does not require credentials;
  • does not require network access for normal analysis;
  • never merges;
  • never checks out a revision;
  • never commits;
  • never deletes repository data;
  • never modifies analyzed repository files.

See SECURITY.md for vulnerability reporting guidance.


JSON output

Use:

branchrift --base main --json

JSON output contains the full structured report, including data that may be truncated in terminal presentation.

It is intended for:

  • scripts;
  • CI experimentation;
  • reporting;
  • downstream tooling;
  • automated inspection.

BranchRift does not currently turn risk/governance findings into blocking exit codes.


Validation

v0.1.9, released as Repo Preflight, was tested across:

  • Python 3.10;
  • Python 3.11;
  • Python 3.12;
  • Python 3.13;
  • Ubuntu CI;
  • Windows CI;
  • clean built-wheel installation;
  • CLI execution outside the source tree;
  • detached HEAD scenarios;
  • Git LFS scenarios;
  • Unicode/Windows terminal cases;
  • rename/copy edge cases;
  • large change sets.

The v0.1.9 test suite contains 167 tests.

The release was also exercised with:

  • 10,000 changed files;
  • up to 1,000 Git LFS attribute paths.

These checks are validation evidence, not a performance SLA.


Current scope and limitations

BranchRift is intentionally narrow.

It currently does not provide:

  • AST-level semantic analysis;
  • language-server analysis;
  • dependency-graph reasoning;
  • automatic merge-conflict resolution;
  • guaranteed Git conflict prediction;
  • semantic inspection inside .uasset or .umap;
  • rename-aware collision identity;
  • multiple simultaneous co-owners for one path;
  • automatic repository modification;
  • automatic merge approval.

The project prefers conservative facts over unsupported conclusions.


Project status

Current release: 0.2.0

BranchRift is an early-stage developer tool.

The current focus is:

  • real-repository validation;
  • false-positive reduction;
  • false-negative discovery;
  • integration-workflow feedback;
  • Git/LFS edge cases;
  • onboarding and packaging;
  • small-team workflows.

Feedback backed by a real repository or workflow problem is especially useful.


Feedback

If you test BranchRift on a real repository, useful feedback includes:

  1. Were same-path collisions useful or noisy?
  2. Were binary-sensitive warnings actionable?
  3. Was ownership resolution correct?
  4. Did LFS readiness reflect the real repository state?
  5. Were required checks useful?
  6. Did the manual-review shortlist save time?
  7. Did the CLI fail on a valid Git workflow?
  8. What would prevent you from running it again?

Please do not publish:

  • secrets;
  • credentials;
  • private repository contents;
  • sensitive company information.

Security-sensitive reports should follow SECURITY.md.

General feedback can be opened through GitHub Issues.


Contributing

Issues, tests, documentation improvements, focused rule changes, and small pull requests are welcome.

Please read CONTRIBUTING.md before submitting a larger change.

Ideas backed by a real repository or workflow problem are preferred over speculative feature expansion.


License

BranchRift is released under the MIT License.

See LICENSE.

Metadata

Release files for branchrift 0.2.0

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

Source distribution (sdist)

Source distribution for branchrift 0.2.0
File Size Uploaded
branchrift-0.2.0.tar.gz 60.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for branchrift 0.2.0
File Interpreter ABI Platform
branchrift-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 91.8 kB

Release files / branchrift-0.2.0.tar.gz

Download URL branchrift-0.2.0.tar.gz
Size 60.9 kB
Tags Source
SHA-256 checksum
How to use checksums
0bd650e41d337d68507d8340def638a9a748a038f21040fa8f67d3d450de431e
BLAKE2b-256 checksum
How to use checksums
471ff175a4e2da47f409f3907e42602721f649bc3aca176c7190e34b08700e17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release files / branchrift-0.2.0-py3-none-any.whl

Download URL branchrift-0.2.0-py3-none-any.whl
Size 30.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a67b0ee612603233c7c2309e5e18deee28cbf9de0d0adb341cb5c32dc41b2611
BLAKE2b-256 checksum
How to use checksums
698a06845e443b17beced3a88cdce1a139cc9694148892da036c3181abb79040
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

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