Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 61 additions & 1 deletion guides/team-workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ You can share generated graph files in the repository, build them in each clone,
1. Register the assistant skill in project scope if your team wants shared instructions.
2. Build and inspect the graph.
3. Decide which generated artifacts belong in version control.
4. Install `graphify hook install` once in each clone.
4. Install `graphify hook install` once in each clone, or the [pre-commit hook](#commit-the-graph-with-the-code-that-changed-it) if you commit the graph.
5. Run `graphify update .` after pulls and merges.

The upstream project recommends committing `graphify-out/` to share a starting map. Review generated files first; they contain source-derived information. Keep local cost reports out of version control:
Expand All @@ -22,6 +22,66 @@ graphify-out/cost.json

You can also exclude `graphify-out/cache/` to reduce repository size, at the cost of less cache reuse. The portable manifest uses relative paths and is re-anchored on load.

## Commit the graph with the code that changed it

`graphify hook install` rebuilds the graph in the background after each commit. If you commit `graphify-out/graph.json`, every commit that changes code then leaves the rebuilt graph behind as an uncommitted change. A `pre-commit` hook avoids that: it rebuilds the graph before the commit and stages it, so each commit carries the graph of its own code.

Track only the graph, so the hook stages exactly what it rebuilt. Each clone rebuilds the other files in `graphify-out/` locally. Replace any existing `graphify-out/` ignore line with these two lines:

```gitignore
graphify-out/*
!graphify-out/graph.json
```

If you already track other files in `graphify-out/`, untrack them once with `git rm -r --cached graphify-out` and then run `git add graphify-out/graph.json`. Otherwise each rebuild leaves them modified.

Mark the graph as generated output in `.gitattributes`:

```gitattributes
graphify-out/graph.json merge=graphify linguist-generated=true -diff
```

- `linguist-generated=true` collapses the file in GitHub pull requests.
- `-diff` makes `git diff`, `git log -p`, and `git show` print `Binary files differ` instead of the graph. A patch saved from `git diff` then can't be applied; `git format-patch` still includes the graph.
- `merge=graphify` merges the graph with graphify's union merge driver instead of as text.

Since graphify 0.9.86, `graph.json` is one line of compact JSON, so GitHub counts a rebuilt graph as one changed line (+1 −1) in a pull request.

`graphify hook install` registers the merge driver. With the pre-commit hook instead, register it once in each clone. If a repository already has it from `graphify hook install`, copy its `merge.graphify.driver` value. Otherwise point the driver at the Python that graphify is installed in, the way `hook install` does, so merges also work when `graphify` is not on `PATH`, as in GUI git clients:

```bash
git config merge.graphify.name "graphify graph.json union merge"
git config merge.graphify.driver '"/path/to/python" -m graphify merge-driver %O %A %B'
```

On Linux and macOS, `sed -n '1s/^#!//p' "$(command -v graphify)"` prints that Python. Keep the double quotes around its path; a Windows path can contain a space.

Without the driver, a merge, rebase, or cherry-pick that changed the graph on both sides stops with a conflict in `graph.json`. Rebuild it with `rm graphify-out/graph.json && graphify update . && git add graphify-out/graph.json`, then continue.

If you use a hook manager such as Husky, pre-commit, or lefthook, add the lines below to its pre-commit step. Otherwise put them where `graphify hook install` puts its post-commit hook: the `pre-commit` file in git's hooks directory, which `git rev-parse --git-path hooks` prints. That is `.git/hooks` unless `core.hooksPath` names another directory. If the file already exists, add the lines before any final `exit` or `exec` line, so they run and your other checks keep running:

```sh
# graphify: rebuild graphify-out/graph.json and commit it with the code that changed it.
if [ "${GRAPHIFY_SKIP_HOOK:-0}" != 1 ] && [ -f graphify-out/graph.json ] &&
! git diff --cached --quiet -- . ':!graphify-out/graph.json'; then
{ PYTHONHASHSEED=0 graphify update . && git add graphify-out/graph.json; } || exit 1
fi
```

A new file needs `#!/bin/sh` as its first line and must be executable (`chmod +x`). The hook only refreshes an existing graph, so build and commit the first one yourself. `PYTHONHASHSEED=0` keeps the rebuild deterministic, as in the hooks `graphify hook install` writes: clustering walks sets whose order depends on that seed, so without it community ids can change on commits that did not change the code's structure.

`.git/hooks` is not committed, so each clone adds the hook itself. To share it through the repository, commit it in a directory such as `.githooks/` and run `git config core.hooksPath .githooks` in each clone. Git then runs only the hooks in that directory and ignores `.git/hooks`, so move any hooks you still use from `.git/hooks` into it. If your CI commits to the repository, install graphify there too, or set `GRAPHIFY_SKIP_HOOK=1` for those commits.

Use this hook in place of `graphify hook install`. It replaces all four hooks that `hook install` adds: post-commit, post-checkout, post-merge, and post-rewrite. The committed graph already matches each commit, but the untracked files in `graphify-out/`, such as `GRAPH_REPORT.md` and `graph.html`, are not refreshed after a branch switch. Run `graphify update .` after a branch switch, as after pulls and merges.

Keep these points in mind:

- A commit fails when the rebuild fails or `graphify` is not on `PATH`. Set `GRAPHIFY_SKIP_HOOK=1` or pass `--no-verify` to commit without the rebuild; the committed graph is then stale.
- The rebuild reads your working tree, not the staged files, so unstaged and untracked code ends up in the committed graph. To commit part of your changes, stage them, run `git stash --keep-index --include-untracked`, run a plain `git commit`, and then `git stash pop`. Avoid `git commit <path>`: the hook stages the graph into git's temporary index, so your index keeps the old graph.
- Git runs no pre-commit hook for a merge it completes without conflicts, or for the commits that `rebase`, `cherry-pick`, and `revert` create. Those commits carry the graph git merged from their parents, not a rebuild, and the merged graph can keep symbols that one side deleted. Run `graphify update .` afterward and commit the graph, or merge with `git merge --no-commit` and then run `git commit` so the hook runs.
- Everyone should run the same graphify release. The graph records the version that built it, and releases can build different graphs from the same code.
- Each commit waits for a full rebuild, which takes from seconds to minutes depending on the code. One 2,800-file repository takes about a minute.

## One graph per worktree

Avoid multiple branches writing into one output location. Set `GRAPHIFY_OUT` to a worktree-specific directory when you use a shared or custom output setup.
Expand Down