-
Notifications
You must be signed in to change notification settings - Fork 0
Core Concepts
A task is not a file in your working tree. It's a sequence of operations (CreateTask,
SetStatus, AddComment, and so on) stored as a chain of git commits under
refs/tasks/<task-id>. Each mutation appends one more commit to that chain; the commit's tree
holds a single blob, ops.json, containing the operation(s) that mutation recorded. Reading a task
means walking every commit reachable from the ref's tip and folding the operations into a Task
struct, in causal order.
This has a few consequences worth internalizing early:
-
No working-tree footprint.
git statusnever shows a dirty task file.git add/git commiton your actual code is unaffected by task activity. -
Full history for free. Every field change, every comment, every label add/remove is a real,
timestamped, attributed commit.
git task log <id>walks and prints that chain. -
The ref's tip advances; the task's id does not.
<id>is the creation commit's own object hash. As you append operations, the ref (refs/tasks/<id>) moves to point at the newest commit, but the id you address the task by never changes.
A task's real identity is its creation commit's hash. Typing a full hash is a hassle, so every repo
has a short, human-readable address key (e.g. SRV), and tasks display as SRV-9057e58a: the key
plus a hash prefix.
The KEY- part is purely cosmetic. It gets stripped before every lookup and whatever's left is
resolved as a hash prefix, so it is never validated against the repo's actually-configured key: a
task addressed with the wrong prefix, or a bare 9057e58a with no prefix at all, both resolve the
same way. Don't hand-construct an id from a title or a guess; always take it from a prior command's
output.
The first task created in a repo with no key pinned yet locks one in automatically (derived from
the repo's directory name), so it stays stable even if the directory is later renamed or cloned
elsewhere. Pin it explicitly with git task config key SRV; see Configuration.
Because two clones of the same repo can each append operations to the same task while offline,
refs/tasks/<id> is a commit graph, not a straight line. When git task pull finds a task edited
on both sides since the last sync, it produces a real two-parent git merge commit joining both
histories, the same way git merge would for a branch. No data is lost: both branches' full
operation sequences remain reachable, and loading a task always replays every reachable commit in
topological order (a Kahn's-algorithm-style sort), falling back to timestamp only to break ties
between commits with no ancestor relationship to each other.
This matters practically in one way: conflicts are not resolved field by field. There's no per-field "last write wins" merge strategy. The merge commit just joins two branches; whichever operations land later in the deterministic topological order win for a given field. See Sync and Multi-Repo for the push/pull mechanics this supports.
A repo's address key, its required-field overrides, and its automation rules are not stored in a
working-tree file either. They live under a second, reserved ref, refs/tasks/config, as their own
chain of config operations, folded the same way a task's operations are. That means repo config
syncs automatically over the same push/pull/clone refspecs as tasks, with no separate export
step and no extra directory to check in. It's edited exclusively through git task config ...;
there's no file to hand-edit. See Configuration.
git-task draws a sharp line between two different things people mean by "delete":
-
Soft delete (
git task delete <id>) appends aDeleteTaskoperation like any other mutation. It's recorded in history, syncs to every peer on their nextpull, and is hidden fromlsby default (ls --deletedshows it). There is norestore; once recorded, it stays. -
Hard delete (
git task drop <id> --force) removes the local ref outright: no history entry, no sync. A peer who already has the task locally will bring it back the next time they push, or you pull from them. Add--remote [name]to also delete it on one named remote, but that reaches only that remote, not every clone that already fetched the task.
If in doubt, delete is almost always the right one, since it's the version that actually
propagates. See Task Management.
git-task never asks who you are. Every write is attributed to whatever git config resolves for the
repo: its own .git/config first, falling back to the global ~/.gitconfig. There is no
--author flag to override it. Run git task whoami to see, before you write anything, what
identity (name/email) a command would be attributed to, at each layer (repo, global, effective).
git-task
Start here
Using tasks
Building on git-task
Contributing