## vcs.VcsAdapter


The VCS surface tether relies on. Paths are relative to `root`.


Usage

``` python
vcs.VcsAdapter()
```


## Methods

| Name | Description |
|----|----|
| [abandon()](#abandon) | Drop `revs` from history, rebasing their descendants - except that |
| [alive_commits()](#alive_commits) | [commit_alive](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit_alive) for many commits in a bounded number of calls - |
| [bookmark_delete()](#bookmark_delete) | Delete the bookmark / branch `name`. |
| [bookmark_set()](#bookmark_set) | Create `name` at `rev` or move it there (backwards allowed). |
| [bookmarks()](#bookmarks) | Local bookmarks (jj) / branches (git): name -\> commit id. |
| [commit()](#commit) | Commit the given paths with [message](CommitResult.md#tether.CommitResult.message); return the new commit id. |
| [commit_alive()](#commit_alive) | Whether [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) - or, in jj, the change it belonged to - is still |
| [commit_info()](#commit_info) | Author, timestamps, message, and parents for many commits in one call. |
| [conflicted_bookmarks()](#conflicted_bookmarks) | Local bookmarks with several targets (jj, after a divergent move or |
| [conflicted_commits()](#conflicted_commits) | Visible commits whose tree holds a conflict (jj). Empty under git. |
| [current_bookmarks()](#current_bookmarks) | The bookmarks the working copy is on. |
| [current_rev()](#current_rev) | Return the commit id of the current working-copy / HEAD commit. |
| [dependants()](#dependants) | Visible commits built on [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) other than the working copy: |
| [dirty()](#dirty) | Whether any of `relpaths` differs from the last commit (jj: `@` |
| [drop_bookmark()](#drop_bookmark) | Make [bookmark](PullReport.md#tether.PullReport.bookmark) and its `commits` (from [exclusive_commits()](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.exclusive_commits)) |
| [exclusive_commits()](#exclusive_commits) | Commit ids reachable from [bookmark](PullReport.md#tether.PullReport.bookmark) and from nothing else that |
| [files_at()](#files_at) | Return `{root-relative path: text}` for files under `reldir`. |
| [files_at_many()](#files_at_many) | `{rev: files_at(rev, reldir)}` for several commits through one |
| [forget_workspace()](#forget_workspace) | Stop tracking the checkout at `root`: `jj workspace forget` by |
| [goto()](#goto) | Return the working copy to a [position()](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.position) taken earlier. |
| [history_digest()](#history_digest) | A digest of every visible commit id: changes whenever any workspace |
| [history_revs()](#history_revs) | Return commit ids reachable in the repository. |
| [is_ancestor()](#is_ancestor) | Whether `ancestor` is `rev` or one of its ancestors. |
| [iter_history_files()](#iter_history_files) | Yield `(commit id, files_at(commit, reldir))` across all history. |
| [list_files_at()](#list_files_at) | List tracked file paths under `reldir` at `rev` (root-relative). |
| [new()](#new) | Move the working copy so the next [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) lands on top of `rev`. |
| [new_bookmark()](#new_bookmark) | Start a bookmark `name` at `rev` (default: the current base) and |
| [position()](#position) | Where the working copy is, as data [goto](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.goto) can return to. |
| [read_file_at()](#read_file_at) | Return file content at `rev` or `None` if the path is absent. |
| [refs()](#refs) | Named pointers (bookmarks / branches, tags) plus the `head` entry. |
| [remote_counterparts()](#remote_counterparts) | Remote refs for [bookmark](PullReport.md#tether.PullReport.bookmark) (`origin/feature`, `feature@origin`): |
| [resolve()](#resolve) | Return a stable commit id for `rev`. |
| [rewrite_history()](#rewrite_history) | Rewrite the files under `reldir` in every commit. |
| [shared_dir()](#shared_dir) | The directory every checkout of this repository shares (git's common |
| [tracked()](#tracked) | Which of `relpaths` (files) the VCS tracks: in jj's working-copy |
| [uncommit()](#uncommit) | Turn [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) back into working-copy changes if it is still the |
| [unresolved_conflicts()](#unresolved_conflicts) | Conflicted commits that are a visible head or a working copy and |
| [workspace_roots()](#workspace_roots) | Root directories of every live checkout of this repository. |

------------------------------------------------------------------------


#### abandon()


Drop `revs` from history, rebasing their descendants - except that


Usage

``` python
abandon(revs, keep_dir)
```


every descendant keeps the files under `keep_dir` exactly as they were (snapshot, not patch, semantics: a manifest records a whole state, so a later commit's manifest must survive the removal of an earlier one untouched instead of conflicting with it). Returns the commit ids that were abandoned and `{old commit id: new commit id}` for the descendants that were rebased.

jj: `jj abandon` then rewrite the descendants' `keep_dir` files back (which also resolves the conflicts jj recorded there). git: the commits must be on the current branch and the tree clean; `rebase --onto` with conflicts under `keep_dir` resolved to the original content, then a fix-up pass so every descendant's `keep_dir` matches what it held before.


------------------------------------------------------------------------


#### alive_commits()


[commit_alive](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit_alive) for many commits in a bounded number of calls -


Usage

``` python
alive_commits(commits)
```


[status](backends.VerifyReport.md#tether.backends.VerifyReport.status) asks about every commit the op log records, and must not spawn a process per entry.


------------------------------------------------------------------------


#### bookmark_delete()


Delete the bookmark / branch `name`.


Usage

``` python
bookmark_delete(name)
```


------------------------------------------------------------------------


#### bookmark_set()


Create `name` at `rev` or move it there (backwards allowed).


Usage

``` python
bookmark_set(name, rev)
```


------------------------------------------------------------------------


#### bookmarks()


Local bookmarks (jj) / branches (git): name -\> commit id.


Usage

``` python
bookmarks()
```


------------------------------------------------------------------------


#### commit()


Commit the given paths with [message](CommitResult.md#tether.CommitResult.message); return the new commit id.


Usage

``` python
commit(relpaths, message, *, advance=None)
```


`advance` names a bookmark / branch to move onto the new commit as part of the same operation (jj: one op-log entry, so `jj undo` takes the commit and the bookmark move back together; git: the checked-out branch moves by itself, any other is updated afterwards).


------------------------------------------------------------------------


#### commit_alive()


Whether [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) - or, in jj, the change it belonged to - is still


Usage

``` python
commit_alive(commit)
```


part of visible history. jj resolves the commit to its change id (hidden commits still resolve) and asks whether that change is visible, so a rewrite does not count as loss; git checks reachability from any ref.


------------------------------------------------------------------------


#### commit_info()


Author, timestamps, message, and parents for many commits in one call.


Usage

``` python
commit_info(revs)
```


------------------------------------------------------------------------


#### conflicted_bookmarks()


Local bookmarks with several targets (jj, after a divergent move or


Usage

``` python
conflicted_bookmarks()
```


fetch). They are left out of [bookmarks()](RecoveredRefs.md#tether.RecoveredRefs.bookmarks), which has one commit per name, so the commits they reach would otherwise count as unreferenced; commands that judge references refuse while there are any. Always empty under git, whose refs have one target.


------------------------------------------------------------------------


#### conflicted_commits()


Visible commits whose tree holds a conflict (jj). Empty under git.


Usage

``` python
conflicted_commits()
```


------------------------------------------------------------------------


#### current_bookmarks()


The bookmarks the working copy is on.


Usage

``` python
current_bookmarks()
```


jj: the bookmarks at `@`, else - when `@` is empty - at `@-` (the usual state right after `jj new main` or `tether commit`); several when they share a commit, as right after [new_bookmark](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.new_bookmark). git: the branch `HEAD` points at, or nothing when detached.


------------------------------------------------------------------------


#### current_rev()


Return the commit id of the current working-copy / HEAD commit.


Usage

``` python
current_rev()
```


------------------------------------------------------------------------


#### dependants()


Visible commits built on [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) other than the working copy:


Usage

``` python
dependants(commit)
```


what [uncommit()](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.uncommit) would rewrite. jj rebases every child of a commit it squashes away, so a bookmark's line on top of it would be rewritten onto the parent; git's `reset --soft` moves one branch and leaves the commit in place, so the answer is always empty.


------------------------------------------------------------------------


#### dirty()


Whether any of `relpaths` differs from the last commit (jj: `@`


Usage

``` python
dirty(relpaths)
```


vs its parent; git: index or worktree vs `HEAD`).


------------------------------------------------------------------------


#### drop_bookmark()


Make [bookmark](PullReport.md#tether.PullReport.bookmark) and its `commits` (from [exclusive_commits()](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.exclusive_commits))


Usage

``` python
drop_bookmark(bookmark, commits)
```


disappear from visible history. jj abandons the commits (which takes the bookmark with them); git deletes the branch, after which nothing reaches the commits. The working copy must not be on the bookmark.


------------------------------------------------------------------------


#### exclusive_commits()


Commit ids reachable from [bookmark](PullReport.md#tether.PullReport.bookmark) and from nothing else that


Usage

``` python
exclusive_commits(bookmark)
```


keeps a commit visible - no other local bookmark, tag, remote bookmark, or another workspace's working copy: the line of work that leaves visible history with the bookmark. Oldest first.


------------------------------------------------------------------------


#### files_at()


Return `{root-relative path: text}` for files under `reldir`.


Usage

``` python
files_at(rev, reldir)
```


------------------------------------------------------------------------


#### files_at_many()


`{rev: files_at(rev, reldir)}` for several commits through one


Usage

``` python
files_at_many(revs, reldir)
```


object reader.


------------------------------------------------------------------------


#### forget_workspace()


Stop tracking the checkout at `root`: `jj workspace forget` by


Usage

``` python
forget_workspace(root)
```


name, or `git worktree remove` (a clean, non-main worktree). Returns a one-line description of what was done, or `None` when the VCS has nothing to forget there (git's main worktree; an unknown path).


------------------------------------------------------------------------


#### goto()


Return the working copy to a [position()](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.position) taken earlier.


Usage

``` python
goto(position)
```


jj: edit the change if it still exists, or start a fresh empty change on its parent when the recorded working copy was empty (jj abandons those when the working copy moves away). git: switch to the branch, or detach at the commit.


------------------------------------------------------------------------


#### history_digest()


A digest of every visible commit id: changes whenever any workspace


Usage

``` python
history_digest()
```


or bookmark of this repository gains or loses a commit. Plans whose safety rests on what history references (`gc`) bind to it.


------------------------------------------------------------------------


#### history_revs()


Return commit ids reachable in the repository.


Usage

``` python
history_revs()
```


------------------------------------------------------------------------


#### is_ancestor()


Whether `ancestor` is `rev` or one of its ancestors.


Usage

``` python
is_ancestor(ancestor, rev)
```


------------------------------------------------------------------------


#### iter_history_files()


Yield `(commit id, files_at(commit, reldir))` across all history.


Usage

``` python
iter_history_files(reldir)
```


A conflicted jj commit is yielded once per input of the conflict - every side and base of its tree - and last with the tree jj shows for it, so a walk that collects references sees every manifest the conflict may resolve to, and one that keeps a single answer per commit keeps the same one as before.

Implementations stream through one object-reader process rather than spawning per commit; callers should consume lazily.


------------------------------------------------------------------------


#### list_files_at()


List tracked file paths under `reldir` at `rev` (root-relative).


Usage

``` python
list_files_at(rev, reldir)
```


------------------------------------------------------------------------


#### new()


Move the working copy so the next [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) lands on top of `rev`.


Usage

``` python
new(rev)
```


jj: `jj new REV` (a fresh empty change; `None` means on top of the current one). git has no empty-commit primitive: a branch name is switched to; any other revision is checked out onto a new branch `tether/<rev12>` so the commits that follow stay reachable (a detached HEAD would let `gc` treat them as gone); `None` is a no-op - the next commit lands on the current branch.


------------------------------------------------------------------------


#### new_bookmark()


Start a bookmark `name` at `rev` (default: the current base) and


Usage

``` python
new_bookmark(name, rev)
```


move the working copy onto it.

jj: `jj new REV` then the bookmark at `@-`. git: `switch -c NAME [REV]`.


------------------------------------------------------------------------


#### position()


Where the working copy is, as data [goto](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.goto) can return to.


Usage

``` python
position()
```


Always has [kind](Action.md#tether.Action.kind) and [id](backends.HistoryEntry.md#tether.backends.HistoryEntry.id) (jj: the working-copy change id; git: the HEAD commit) and [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit); jj adds `parent` and `empty`, git adds [branch](handles.NeonHandle.md#tether.handles.NeonHandle.branch) (`None` when detached).


------------------------------------------------------------------------


#### read_file_at()


Return file content at `rev` or `None` if the path is absent.


Usage

``` python
read_file_at(rev, relpath)
```


------------------------------------------------------------------------


#### remote_counterparts()


Remote refs for [bookmark](PullReport.md#tether.PullReport.bookmark) (`origin/feature`, `feature@origin`):


Usage

``` python
remote_counterparts(bookmark)
```


what still reaches its commits after a local drop, and what a later push deletes (jj) or leaves (git).


------------------------------------------------------------------------


#### resolve()


Return a stable commit id for `rev`.


Usage

``` python
resolve(rev)
```


------------------------------------------------------------------------


#### rewrite_history()


Rewrite the files under `reldir` in every commit.


Usage

``` python
rewrite_history(reldir, transform, *, ignore_immutable=False)
```


`transform(commit, files)` receives `{root-relative path: text}` and returns the texts that should be there instead (same keys; a commit whose result equals its input is left alone, but still gets a new id if a parent changed). Descendants are rebased, bookmarks / branches and tags follow, change ids (jj) are preserved. Returns `{old commit id: new commit id}` for every commit that changed. The working-copy commit is not rewritten (edit the working tree instead); the working copy ends where it started.

This is history rewriting: every other clone must re-sync. `ignore_immutable` (jj) rewrites commits jj considers immutable.


------------------------------------------------------------------------


#### shared_dir()


The directory every checkout of this repository shares (git's common


Usage

``` python
shared_dir()
```


dir; jj's repo dir), where a lock that must be seen by all of them can live. For a single checkout it is the checkout's own store.


------------------------------------------------------------------------


#### tracked()


Which of `relpaths` (files) the VCS tracks: in jj's working-copy


Usage

``` python
tracked(relpaths, *, checkout=None)
```


commit as last snapshotted, in git's index. One call and no snapshot, so `Repo.find` can afford it on every run: a per-checkout file the VCS tracks came with a clone (or was committed by hand) and is refused. `checkout` asks another checkout of this repository (a root from [workspace_roots](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.workspace_roots)), with `relpaths` relative to it.


------------------------------------------------------------------------


#### uncommit()


Turn [commit](vcs.VcsAdapter.md#tether.vcs.VcsAdapter.commit) back into working-copy changes if it is still the


Usage

``` python
uncommit(commit)
```


working copy's parent (jj) / `HEAD` (git); `False` if it is not.

jj: `jj squash --from COMMIT --into @`; git: `git reset --soft`. The tree is unchanged either way - the commit's edits stay in the working copy as uncommitted changes.


------------------------------------------------------------------------


#### unresolved_conflicts()


Conflicted commits that are a visible head or a working copy and


Usage

``` python
unresolved_conflicts(reldir)
```


whose conflict touches `reldir` (jj). A descendant inherits a conflict until it resolves it, so a conflict no later commit resolved always shows at a head, and one resolved in a child (or further down) does not - wherever the bookmarks are. Empty under git.


------------------------------------------------------------------------


#### workspace_roots()


Root directories of every live checkout of this repository.


Usage

``` python
workspace_roots()
```


jj workspaces (`jj workspace list` + `jj workspace root --name`) or git worktrees (`git worktree list`). Used by `gc --prune-bookmarks` to keep the working branches of workspaces that still exist.


------------------------------------------------------------------------


#### References


#### refs()


Named pointers (bookmarks / branches, tags) plus the `head` entry.


Usage

``` python
refs()
```
