1git-series internals
2====================
3
4Requirements
5------------
6
7The format git-series uses to store each patch series ensures that standard git
8tools can always handle a git-series repository. In particular:
9
10- All commits and objects in the history and metadata of every series must
11 remain reachable via git's normal object reachability algorithms, so that git
12 will never discard the history or metadata of a series.
13- Transferring a git-series repository via git's standard protocols must
14 transfer all series including history and metadata, without any extensions to
15 the git protocols.
16
17Refs
18----
19
20git-series stores the series ref for a patch series named `NAME` in
21`refs/heads/git-series/NAME`. This will appear to git as a branch named
22`git-series/NAME`. From that ref, git can reach all the information git-series
23tracks about a patch series, so sending or receiving that ref brings along all
24the information git-series needs.
25
26git-series maintains a symbolic ref `refs/SHEAD` pointing to the current
27series. If a repository does not have a current series, SHEAD will not exist.
28
29git-series commits
30------------------
31
32git-series stores each version of a patch series as one commit object. The
33`git-series/NAME` ref refers to commit corresponding to the current version of
34the patch series NAME. The tree object within each git-series commit acts like
35a key-value store, with tree entry names as keys; the tree entry `series`
36references the last commit of the patch series itself.
37
38In this documentation, a "git-series commit" refers to a commit corresponding
39to a version of an entire patch series, as distinguished from a commit
40corresponding to one patch within a patch series.
41
42A git-series commit can have two types of parent commits: those connecting the
43history of the patch series, and those referencing gitlink commits that also
44appear in the git-series commit's tree. A git-series commit can have any
45number of either type of parent, but all of the parents connecting the history
46of the patch series will always appear before any of the parents referencing
47gitlink commits.
48
49The parents connecting the history of the patch series, if any, point to
50previous git-series commits representing previous versions of the patch series;
51a git-series commit with more than one such parent represents a git-series
52merge commit. The remaining parents of each git-series commit correspond to
53commits referenced as gitlinks (tree entries with mode 160000) within the
54commit's tree; this ensures that git can reach all of those commits. (Note
55that git's traversal algorithm does not follow gitlink commits within tree
56objects, so without these additional parent links, git would consider these
57gitlink commits unreachable and discard them.)
58
59The parents of each git-series commit that reference gitlinks in that
60git-series commit's tree do not appear in any particular order; do not assume
61that the `series` object or any other gitlink appears at any particular
62position within the parents list. These parents exist only to make commits
63reachable and transferable by git. Always look up commits via named tree
64entries within the git-series commit's tree object.
65
66In the root git-series commit, all the parent commits correspond to gitlinks
67within the git-series commit's tree. This will not occur for any non-root
68commit of a git-series. Algorithms trying to walk git-series commits should
69filter out parents that appear in the git-series commit's tree. (This does not
70require a recursive tree walk; the gitlinks within the git-series commit's tree
71will appear in the top-level tree object.)
72
73git-series tree entries
74-----------------------
75
76The tree within a git-series commit can contain the following entries:
77
78- `series`: Every git-series tree must contain this entry, as a gitlink with
79 mode 160000. This identifies the last commit in the patch series.
80- `base`: If this exists, it must refer to a gitlink with mode 160000. This
81 identifies the base commit for the patch series. The patch series consists
82 of the commits reachable from `series` and not reachable from `base`:
83 `base`..`series`. Many git-series commands require `base`, but a patch
84 series does not have to have a `base`.
85- `cover`: If this exists, it must refer to a blob with mode 100644. This
86 provides a cover letter for the patch series. This blob should contain UTF-8
87 text.
88
89git-series staged changes and "working directory"
90-------------------------------------------------
91
92Like git, git-series allows staging part of all of the changes to the patch
93series for a commit, or committing all the changes directly via `git series
94commit -a`. However, git-series does not maintain a "working directory"
95directly. Instead, git-series tracks the staged and unstaged changes to a
96patch series named NAME via commits referenced by
97`refs/git-series-internals/staged/NAME` and
98`refs/git-series-internals/working/NAME`. The tree of each of those commits
99may contain any of the standard git-series tree entries. (If the series has
100nothing staged, the "staged" ref will not exist.) These commits will also have
101all of the corresponding gitlink entries as parents, to keep them reachable by
102git.
103
104The `working` commit for a patch series tracks the current state of the patch
105series. For example, setting a base with `git series base` or a cover letter
106with `git series cover` will store the new base or cover letter as `base` or
107`cover` in the tree of the commit referenced from the working ref. git-series
108commands will keep the `series` entry of the working tree referring to the
109current HEAD.
110
111The `staged` commit for a patch series, if present, tracks the staged changes
112to the patch series. `git series add` adds changes from `working` to `staged`,
113and `git series unadd` removes changes from `staged`.
114
115If a series does not have a series ref `refs/git-series/NAME`, but has a staged
116or working ref, the series still exists, with no series commits. This can
117happen by running `git series start NAME`, making some changes without
118committing, and then running `git series detach`. git-series treats that as an
119existing series, and allows checking it out. This preserves work in progress
120on an un-started series.