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.
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
.uassetor.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:
- the most-specific path wins;
- 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:
SAMELINEARHEAD_BEHINDDIVERGED
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_addedline_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:
sourceassetmapbuild_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:
- exact filename;
- most-specific path prefix;
- extension;
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
.uassetor.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:
- Were same-path collisions useful or noisy?
- Were binary-sensitive warnings actionable?
- Was ownership resolution correct?
- Did LFS readiness reflect the real repository state?
- Were required checks useful?
- Did the manual-review shortlist save time?
- Did the CLI fail on a valid Git workflow?
- 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)
| File | Size | Uploaded | |
|---|---|---|---|
| branchrift-0.2.0.tar.gz | 60.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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