Skip to content

Latest commit

 

History

History
310 lines (240 loc) · 10.2 KB

getting-started.adoc

File metadata and controls

310 lines (240 loc) · 10.2 KB

Getting started with it

This document walks you through the very basics of it. Many of the interactions below may be automated away eventually, but our goal here is to provide an overview of what is going on under the hood.

Prerequisites

We are going to assume you have the it executable installed using

cargo install --git https://git.eagain.io/it

Chances are that you already have an SSH key handy. If not, or if you want to use a key specifically for this exercise, generate one using

ssh-keygen -t ed25519

It is also a good idea to add this key to your ssh-agent, so you don’t have to type the password every time it is used for signing. Typing ssh-add usually does the trick.

Next, we’ll need to teach git to use our SSH key for signing. If you followed above recommendation and are using an agent for signing, the following commands will set it up as a default:

git config --global gpg.format ssh
git config --global user.signingKey "key::$(cat /path/to/your_key.pub)"

If you prefer to not mess with your existing git configuration, you can also arrange for the key to be recognised by it itself by running the following command instead:

git config --global it.signingKey "key::$(cat /path/to/your_key.pub)"

Lastly, we’ll create an it identity using this key:

it id init

The command’s output will look similar to this:

{
  "committed": {
    "repo": "~/.local/share/it/ids",
    "ref": "refs/heads/it/ids/671e27d4cce92f747106c7da90bcc2be7072909afa304d008eb8ecbfdebfbfe2",
    "commit": "e08c34df95cd28aa212a4d110ecfb8acec2a102c"
  },
  "data": {
    "signed": {
      "_type": "eagain.io/it/identity",
      "spec_version": "0.1.0",
      "prev": null,
      "keys": [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDtt6XEdNVInhiKkX+ccN++Bk8kccdP6SeBPg0Aq8XFo"
      ],
      "threshold": 1,
      "mirrors": [],
      "expires": null,
      "custom": {}
    },
    "signatures": {
      "ddc27a697903b8fe3ae3439818af81eaac20ba65e51a4170e3c81eb25abd1767": "5a460b26099ddd42912b7a52ee0c478619425ddfe4a562fd2ffd427d84cde6ab32effd8971308cfcdb64b08ac920e7a2c2a69d11b0ca7fe293e39306cd4d7c01"
    }
  }
}

The data object is exactly what is stored in the repository repo at branch ref, which we invite you to convince yourself of using normal git commands.

Identities can describe multiple keys, and carry additional custom metadata, but we’ll skip over this for now.

Local drop

it is organised around patches. You know, like in the olden days, but not quite. Patches are recorded onto a log dubbed “drop”.

If you have a git repository to toy around with, you can initialise a drop adjacent to the "normal" branches in it. You can record patches (which you may have received from elsewhere) onto that local drop, and push it to wherever you like.

To initialise a drop in this way, just run:

it drop init --description "my project"

This will drop you into $EDITOR to give you an opportunity to customise the drop’s metadata, which will look similar to this:

{
  "description": "my project",
  "roles": {
    "drop": {
      "ids": [
        "671e27d4cce92f747106c7da90bcc2be7072909afa304d008eb8ecbfdebfbfe2"
      ],
      "threshold": 1
    },
    "snapshot": {
      "ids": [
        "671e27d4cce92f747106c7da90bcc2be7072909afa304d008eb8ecbfdebfbfe2"
      ],
      "threshold": 1
    },
    "mirrors": {
      "ids": [
        "671e27d4cce92f747106c7da90bcc2be7072909afa304d008eb8ecbfdebfbfe2"
      ],
      "threshold": 1
    },
    "branches": {
      "refs/heads/main": {
        "ids": [
          "671e27d4cce92f747106c7da90bcc2be7072909afa304d008eb8ecbfdebfbfe2"
        ],
        "threshold": 1,
        "description": "the default branch"
      }
    }
  },
  "custom": {}
}

You may want to check if it has guessed your mainline branch correctly (in the branches section), but otherwise just save and exit to finish the initialisation step. Run

git log -p refs/it/patches

to see the effect.

We want source code patches to be against the refs/heads/main branch, so we need to teach the drop about what the current state is:

it merge-point record

Again, you may want to run git log as above to see what changed. You’ll notice a line starting with "Re:" in the latest commit message: this is the topic of a patch, and a merge point is just a patch with a well-known topic. Run

it topic ls

to see that this topic now exists, and

it topic show c44c20434bfdaa0384b67d48d6c3bb36d755b87576027671f606c404b09d9774

to display the metadata recorded in it.

Whenever you update refs/heads/main, run merge-point record again to convey the new head to the drop. showing the topic as above will give you a log of every such update.

Finally, let’s create a patch: make some changes on a feature branch, like you normally would, and then run

it patch record

This will drop you into $EDITOR, asking you to describe what the patch is about. After you save and exit, a new record will be committed onto the drop, and a new topic will have been created:

$ it topic ls
{
  "topic": "2d2d3c97df62b18d3d1476342fe9d6df0989592f6d55d151350422795da714d8",
  "subject": "Just testin"
}
{
  "topic": "c44c20434bfdaa0384b67d48d6c3bb36d755b87576027671f606c404b09d9774",
  "subject": "Merges"
}

You can post more patches to an existing topic, and reply to a specific entry within the topic. Because a patch in it is really a combination of commentary and source code changes, and source code changes are actually optional, we have a handy shortcut to just, well, comment:

it topic comment record 2d2d3c97df62b18d3d1476342fe9d6df0989592f6d55d151350422795da714d8

Type your comment into $EDITOR, save and exit. The result may look like this:

$ it topic show 2d2d3c97df62b18d3d1476342fe9d6df0989592f6d55d151350422795da714d8
{
  "header": {
    "id": "11337eb409fbd16a034d0323dfa8d879b5a0f36c",
    "author": {
      "name": "Kim Altintop",
      "email": "[email protected]"
    },
    "time": "2023-01-09T09:39:15+01:00",
    "patch": {
      "id": "8da0f98009aae98e7ca9df926125aa386a4f6a644c2036e9ec86a0810a7b8a62",
      "tips": []
    },
    "in-reply-to": "0c9b7c0b437a3a072f3a1eead17703d22a0bf8f1"
  },
  "message": {
    "_type": "eagain.io/it/notes/basic",
    "message": "Ship it"
  }
}
{
  "header": {
    "id": "0c9b7c0b437a3a072f3a1eead17703d22a0bf8f1",
    "author": {
      "name": "Kim Altintop",
      "email": "[email protected]"
    },
    "time": "2023-01-09T09:23:51+01:00",
    "patch": {
      "id": "502b3c4dcf709c9b16df2b58aece9a8966405347a2bf6ccbb305711120984951",
      "tips": [
        "refs/it/bundles/502b3c4dcf709c9b16df2b58aece9a8966405347a2bf6ccbb305711120984951/heads/main"
      ]
    }
  },
  "message": {
    "_type": "eagain.io/it/notes/basic",
    "message": "Just testin"
  }
}

Notice the patch.tips array? If the patch contains references which are conventionally recognised as source code changes (i.e. refs/heads/…​, refs/tags/…​), their physical location inside the drop’s repository will be shown here. it is currently lacking a nice UI for this, but you can just do

git diff refs/it/bundles/502b3c4dcf709c9b16df2b58aece9a8966405347a2bf6ccbb305711120984951/heads/main

to see the diff against your currently checked-out branch. If you’re satisfied, go ahead and merge this ref into your local main branch. Don’t forget to thank yourself for the contribution by commenting on the topic!

To wrap it up, you may be wondering how it stored everything in your repository, and perhaps clean it up. Run

git for-each-ref refs/it

to poke around the references it uses to maintain its state. Note, however, that this structure is not part of any public API, and may change without further notice!

The actual patch bundles can be found in .git/it/bundles. Note that a patch bundle is self-contained — you can send them over email, store them in IPFS, or whatever is convenient to move them from one place to another.

Remote drop

We said that you could receive patches over whatever channel, and apply them to your local drop. A more tangible way is to serve the drop over HTTP, allowing anyone to submit patches to it. While it’s possible to do this from your working repository, it is preferable to create a dedicated repo for the drop:

it drop init --git-dir /the/drop.git --description "my public drop"
it merge-point record --git-dir /the/drop.git --source-dir .
cd /the/drop.git
RUST_LOG=debug it serve

In a second terminal, cd into your working repo and add the drop as a regular git remote:

git remote add dropit /the/drop.git
git remote update dropit

You can now submit to it by replacing record with submit for the respective commands, and specifying --drop dropit/patches to use the remote drop as the reference.

Currently, an extra command it drop bundles sync is needed to receive the patch bundles after updating the remote. This is not particularly smart yet, especially given that we do support inspecting individual topics (as opposed to the entire drop history) by it topic unbundle. We’ll get there.

Loose ends

If you’ve used email to send around patches, or even the excellent b4 tool, this may all seem vaguely familiar to you: instead of mbox archives we have binary git bundles, what gives?

That’s fair, we haven’t really detailed how it permits much richer interactions and datatypes, for lack of a UI. For brevity, we also haven’t shown that patch bundles can be stored on IPFS, the "commit bit" can be extended to co-maintainers, or how more complex topologies can be created by drop aggregation (and without resorting to HTTP POST).

We invite you to play around with the available commands, read the spec, and perhaps consider to contribute where you see it is currently lacking :)