pub trait GitRepo {
Show 28 methods
// Required methods
fn head_oid(&self) -> Result<String>;
fn find_reference_point(&self, commit_ish: &str) -> Result<String>;
fn list_commits(
&self,
from_oid: &str,
to_oid: &str,
) -> Result<Vec<CommitInfo>>;
fn commit_diff(&self, oid: &str) -> Result<CommitDiff>;
fn commit_diff_for_fragmap(&self, oid: &str) -> Result<CommitDiff>;
fn staged_diff(&self) -> Option<CommitDiff>;
fn unstaged_diff(&self) -> Option<CommitDiff>;
fn split_commit_per_file(
&self,
commit_oid: &str,
head_oid: &str,
) -> Result<()>;
fn split_commit_per_hunk(
&self,
commit_oid: &str,
head_oid: &str,
) -> Result<()>;
fn split_commit_per_hunk_group(
&self,
commit_oid: &str,
head_oid: &str,
reference_oid: &str,
) -> Result<()>;
fn count_split_per_file(&self, commit_oid: &str) -> Result<usize>;
fn count_split_per_hunk(&self, commit_oid: &str) -> Result<usize>;
fn count_split_per_hunk_group(
&self,
commit_oid: &str,
head_oid: &str,
reference_oid: &str,
) -> Result<usize>;
fn reword_commit(
&self,
commit_oid: &str,
new_message: &str,
head_oid: &str,
) -> Result<()>;
fn get_config_string(&self, key: &str) -> Option<String>;
fn drop_commit(
&self,
commit_oid: &str,
head_oid: &str,
) -> Result<RebaseOutcome>;
fn move_commit(
&self,
commit_oid: &str,
insert_after_oid: &str,
head_oid: &str,
) -> Result<RebaseOutcome>;
fn rebase_continue(&self, state: &ConflictState) -> Result<RebaseOutcome>;
fn rebase_abort(&self, state: &ConflictState) -> Result<()>;
fn workdir(&self) -> Option<PathBuf>;
fn read_index_stage(
&self,
path: &str,
stage: i32,
) -> Result<Option<Vec<u8>>>;
fn read_conflicting_files(&self) -> Vec<String>;
fn squash_commits(
&self,
source_oid: &str,
target_oid: &str,
message: &str,
head_oid: &str,
) -> Result<RebaseOutcome>;
fn squash_try_combine(
&self,
source_oid: &str,
target_oid: &str,
combined_message: &str,
is_fixup: bool,
head_oid: &str,
) -> Result<Option<ConflictState>>;
fn squash_finalize(
&self,
ctx: &SquashContext,
message: &str,
original_branch_oid: &str,
) -> Result<RebaseOutcome>;
fn stage_file(&self, path: &str) -> Result<()>;
fn auto_stage_resolved_conflicts(&self, files: &[String]) -> Result<()>;
fn default_branch(&self) -> Option<String>;
}Expand description
Abstraction over git repository operations.
Isolates the git2 crate to the repo::git2_impl module. Callers work
through this trait so that the real Git2Repo implementation can be
swapped with a mock or fake in tests.
Required Methods§
Sourcefn head_oid(&self) -> Result<String>
fn head_oid(&self) -> Result<String>
Returns the OID that HEAD currently points at.
Fails if HEAD is detached or does not resolve to a direct commit reference.
Sourcefn find_reference_point(&self, commit_ish: &str) -> Result<String>
fn find_reference_point(&self, commit_ish: &str) -> Result<String>
Find the merge-base (reference point) between HEAD and a given commit-ish.
The commit-ish can be:
- A branch name (e.g., “main”, “feature”)
- A tag name (e.g., “v1.0”)
- A commit hash (short or long)
Returns the OID of the common ancestor as a string.
Sourcefn list_commits(&self, from_oid: &str, to_oid: &str) -> Result<Vec<CommitInfo>>
fn list_commits(&self, from_oid: &str, to_oid: &str) -> Result<Vec<CommitInfo>>
List commits from one commit back to another (inclusive).
Walks the commit graph from from_oid back to to_oid, collecting
commit metadata. Returns commits in oldest-to-newest order.
Both from_oid and to_oid can be any commit-ish (branch, tag, hash).
The range includes both endpoints.
Sourcefn commit_diff(&self, oid: &str) -> Result<CommitDiff>
fn commit_diff(&self, oid: &str) -> Result<CommitDiff>
Extract the full diff for a single commit compared to its first parent.
For the root commit (no parents), diffs against an empty tree so all
files show as additions. Returns a CommitDiff containing the commit
metadata and every file/hunk/line changed.
Sourcefn commit_diff_for_fragmap(&self, oid: &str) -> Result<CommitDiff>
fn commit_diff_for_fragmap(&self, oid: &str) -> Result<CommitDiff>
Extract commit diff with zero context lines, suitable for fragmap analysis.
The fragmap algorithm needs each logical change as its own hunk. With the default 3-line context, git merges adjacent hunks together which produces fewer but larger hunks — breaking the SPG’s fine-grained span tracking.
Sourcefn staged_diff(&self) -> Option<CommitDiff>
fn staged_diff(&self) -> Option<CommitDiff>
Return a synthetic CommitDiff for changes staged in the index (index vs HEAD).
Returns None when the index is clean (no staged changes).
Sourcefn unstaged_diff(&self) -> Option<CommitDiff>
fn unstaged_diff(&self) -> Option<CommitDiff>
Return a synthetic CommitDiff for unstaged working-tree changes (workdir vs index).
Returns None when the working tree is clean relative to the index.
Sourcefn split_commit_per_file(&self, commit_oid: &str, head_oid: &str) -> Result<()>
fn split_commit_per_file(&self, commit_oid: &str, head_oid: &str) -> Result<()>
Split a commit into one commit per changed file.
Creates N new commits (one per file touched by commit_oid), each applying
only that file’s changes. Rebases all commits between commit_oid (exclusive)
and head_oid (inclusive) onto the resulting commits, then fast-forwards the
branch ref to the new tip.
Fails if:
- the commit has fewer than 2 changed files (nothing to split)
- staged or unstaged changes share file paths with the commit being split
- a rebase conflict occurs while rebuilding descendants
Sourcefn split_commit_per_hunk(&self, commit_oid: &str, head_oid: &str) -> Result<()>
fn split_commit_per_hunk(&self, commit_oid: &str, head_oid: &str) -> Result<()>
Split a commit into one commit per hunk.
Creates N new commits (one per hunk across all files), in file-then-hunk-index order. Each intermediate tree is built by cumulatively applying the first k hunks of the full diff (with 0 context lines) onto the original parent tree.
Fails if:
- the commit has fewer than 2 hunks (nothing to split)
- staged or unstaged changes share file paths with the commit being split
- a rebase conflict occurs while rebuilding descendants
Sourcefn split_commit_per_hunk_group(
&self,
commit_oid: &str,
head_oid: &str,
reference_oid: &str,
) -> Result<()>
fn split_commit_per_hunk_group( &self, commit_oid: &str, head_oid: &str, reference_oid: &str, ) -> Result<()>
Split a commit into one commit per hunk group.
Hunks are grouped using the same SPG-based fragmap algorithm shown in the hunk group matrix: two hunks from the commit end up in the same group when they share the same set of interacting commits on the branch (i.e. their fragmap columns deduplicate to the same column). This yields fewer, more cohesive commits than per-hunk splitting, and the groups match exactly what the user sees in the TUI fragmap after deduplication.
Fails if:
- the commit cannot be mapped to at least 2 fragmap groups (nothing to split)
- staged or unstaged changes share file paths with the commit being split
- a rebase conflict occurs while rebuilding descendants
Sourcefn count_split_per_file(&self, commit_oid: &str) -> Result<usize>
fn count_split_per_file(&self, commit_oid: &str) -> Result<usize>
Count how many commits split_commit_per_file would produce for this commit.
Sourcefn count_split_per_hunk(&self, commit_oid: &str) -> Result<usize>
fn count_split_per_hunk(&self, commit_oid: &str) -> Result<usize>
Count how many commits split_commit_per_hunk would produce for this commit.
Sourcefn count_split_per_hunk_group(
&self,
commit_oid: &str,
head_oid: &str,
reference_oid: &str,
) -> Result<usize>
fn count_split_per_hunk_group( &self, commit_oid: &str, head_oid: &str, reference_oid: &str, ) -> Result<usize>
Count how many fragmap groups split_commit_per_hunk_group would produce
for this commit, given the full branch context up to head_oid from
reference_oid.
Sourcefn reword_commit(
&self,
commit_oid: &str,
new_message: &str,
head_oid: &str,
) -> Result<()>
fn reword_commit( &self, commit_oid: &str, new_message: &str, head_oid: &str, ) -> Result<()>
Reword the message of an existing commit.
Creates a new commit with the same tree and parents as commit_oid but
with new_message as the commit message, then cherry-picks all commits
strictly between commit_oid and head_oid (inclusive) onto the new
commit, and fast-forwards the branch ref to the resulting tip.
Because only the message changes the diff at every step is identical, so no conflicts can arise from staged or unstaged working-tree changes.
Sourcefn get_config_string(&self, key: &str) -> Option<String>
fn get_config_string(&self, key: &str) -> Option<String>
Read a string value from the repository’s git configuration.
Returns None when the key does not exist or is not valid UTF-8.
Sourcefn drop_commit(&self, commit_oid: &str, head_oid: &str) -> Result<RebaseOutcome>
fn drop_commit(&self, commit_oid: &str, head_oid: &str) -> Result<RebaseOutcome>
Drop a commit from the branch by cherry-picking its descendants onto its parent.
Returns RebaseOutcome::Complete when all descendants are
successfully rebased, or RebaseOutcome::Conflict when a cherry-pick
step produces merge conflicts. In the conflict case the working tree
and index contain the partially merged state for the user to resolve.
Sourcefn move_commit(
&self,
commit_oid: &str,
insert_after_oid: &str,
head_oid: &str,
) -> Result<RebaseOutcome>
fn move_commit( &self, commit_oid: &str, insert_after_oid: &str, head_oid: &str, ) -> Result<RebaseOutcome>
Move a commit to a different position on the branch.
Removes commit_oid from its current position and inserts it
immediately after insert_after_oid. All affected descendants are
cherry-picked in the new order.
insert_after_oid may be the merge-base (reference point) to move
the commit to the very beginning of the branch.
Returns RebaseOutcome::Complete on success or
RebaseOutcome::Conflict when a cherry-pick step conflicts.
Sourcefn rebase_continue(&self, state: &ConflictState) -> Result<RebaseOutcome>
fn rebase_continue(&self, state: &ConflictState) -> Result<RebaseOutcome>
Resume a conflicted rebase after the user has resolved conflicts.
Reads the current index (which the user resolved), creates a commit
for the conflicting cherry-pick, then continues cherry-picking the
remaining descendants. Returns a new RebaseOutcome — the next
cherry-pick may also conflict.
Sourcefn rebase_abort(&self, state: &ConflictState) -> Result<()>
fn rebase_abort(&self, state: &ConflictState) -> Result<()>
Abort a conflicted rebase and restore the branch to its original state.
Resets the branch ref to state.original_branch_oid, cleans up the
working tree and index.
Sourcefn workdir(&self) -> Option<PathBuf>
fn workdir(&self) -> Option<PathBuf>
Return the path of the repository’s working directory, if any.
Bare repositories have no working directory and return None.
Sourcefn read_index_stage(&self, path: &str, stage: i32) -> Result<Option<Vec<u8>>>
fn read_index_stage(&self, path: &str, stage: i32) -> Result<Option<Vec<u8>>>
Read the raw blob content of a specific index stage for a conflicted path.
Stage 1 = base (common ancestor), 2 = ours, 3 = theirs.
Returns None when that stage entry does not exist for the path.
Sourcefn read_conflicting_files(&self) -> Vec<String>
fn read_conflicting_files(&self) -> Vec<String>
Return the list of paths that currently have conflict markers in the index (entries with stage > 0), sorted alphabetically and deduplicated.
Sourcefn squash_commits(
&self,
source_oid: &str,
target_oid: &str,
message: &str,
head_oid: &str,
) -> Result<RebaseOutcome>
fn squash_commits( &self, source_oid: &str, target_oid: &str, message: &str, head_oid: &str, ) -> Result<RebaseOutcome>
Squash two commits into one.
Creates a single commit that combines target_oid (older) and
source_oid (newer) by cherry-picking source’s diff onto target’s
tree. The result replaces target’s position in the history and source
is removed. All descendants between target and head_oid (excluding
source) are rebased onto the squash commit.
Returns RebaseOutcome::Complete on success or
RebaseOutcome::Conflict when a cherry-pick conflicts.
When the initial squash tree creation (source vs target) conflicts,
the returned ConflictState carries a squash_context so the TUI
can let the user resolve, then call squash_finalize.
Sourcefn squash_try_combine(
&self,
source_oid: &str,
target_oid: &str,
combined_message: &str,
is_fixup: bool,
head_oid: &str,
) -> Result<Option<ConflictState>>
fn squash_try_combine( &self, source_oid: &str, target_oid: &str, combined_message: &str, is_fixup: bool, head_oid: &str, ) -> Result<Option<ConflictState>>
Test whether combining source onto target produces a conflict.
Returns Ok(None) when the trees merge cleanly (caller should proceed
to open the editor and then call squash_commits).
Returns Ok(Some(ConflictState)) when the cherry-pick conflicts. The
conflict is written to the working tree and index. The ConflictState
carries a SquashContext so the TUI can let the user resolve, then
(for squash) open the editor and call squash_finalize, or (for fixup)
call squash_finalize directly without opening the editor.
Sourcefn squash_finalize(
&self,
ctx: &SquashContext,
message: &str,
original_branch_oid: &str,
) -> Result<RebaseOutcome>
fn squash_finalize( &self, ctx: &SquashContext, message: &str, original_branch_oid: &str, ) -> Result<RebaseOutcome>
Finalize a squash after the user resolved a squash-time tree conflict.
Reads the resolved index, creates the squash commit with message,
then cherry-picks the descendants listed in ctx. Returns
RebaseOutcome::Complete or Conflict for a descendant conflict.
Sourcefn stage_file(&self, path: &str) -> Result<()>
fn stage_file(&self, path: &str) -> Result<()>
Stage a working-tree file, clearing any conflict entries for that path.
Equivalent to git add <path>. Reads the file from the working directory,
adds it to the index at stage 0 (which removes stages 1/2/3), and writes
the updated index to disk. Must be called after a merge tool resolves a
conflict so that subsequent index.has_conflicts() checks return false.
Sourcefn auto_stage_resolved_conflicts(&self, files: &[String]) -> Result<()>
fn auto_stage_resolved_conflicts(&self, files: &[String]) -> Result<()>
Auto-stage conflicting files whose working-tree content no longer contains conflict markers.
When a user resolves conflicts in an external editor (instead of the
built-in mergetool), the index still carries stage 1/2/3 entries.
This method reads each file from disk and stages it if the standard
<<<<<<< marker is absent, so that index.has_conflicts() reflects
the actual resolution state.
Sourcefn default_branch(&self) -> Option<String>
fn default_branch(&self) -> Option<String>
Return the name of the repository’s default upstream branch.
Looks up the symbolic target of refs/remotes/origin/HEAD (the pointer
that git remote set-head origin --auto sets) and strips the
refs/remotes/ prefix so the returned value can be passed directly to
find_reference_point. For example when origin/HEAD points to
refs/remotes/origin/main this returns Some("origin/main").
Returns None when the remote tracking ref is absent or has no symbolic
target (e.g. the repo has no remote configured, or origin/HEAD was
never set).