2 个版本
0.1.1 | 2019年2月25日 |
---|---|
0.1.0 | 2019年2月21日 |
#1679 in 开发工具
265KB
4.5K SLoC
ojo
是一个基于与 pijul
相同理念的极简版本控制系统 (VCS),如以下系列博客文章所述 此处。这不是一个真正的 VCS,你不应该用它做任何重要的事情。(首先,它只能跟踪单个文件。)我编写了 ojo
来帮助我理解博客文章中讨论的思想,并且我将其公开发布,希望也许它能帮助其他人。
安装
ojo
是一个命令行程序。它仅在 Linux 上进行了测试,尽管它可能也适用于类似的操作系统。 ojo
使用 rust 编写;要安装它,你需要安装 rust 工具链。一旦你完成了,克隆这个仓库,并用 cargo
构建。
$ git clone https://github.com/jneem/ojo.git
$ cd ojo
$ cargo build --release
然后你可以在 target/release/
目录中找到 ojo
二进制文件。
用法
创建仓库
要开始你的 ojo
之旅,在当前目录中初始化一个仓库
$ ojo init
Created empty ojo repository.
这将在当前目录中创建一个 .ojo
目录,其中包含文件 db
。此 db
文件包含 ojo
的所有内部数据。它是纯文本(YAML 格式),所以如果你好奇的话可以查看。
创建和应用补丁
每个 ojo
仓库只能跟踪一个文件,文件名默认为 ojo_file.txt
。要创建补丁,请使用命令 ojo patch create
。例如,假设你刚刚创建了一个仓库,然后编辑了文件 ojo_file.txt
。要创建反映你新更改的补丁:执行
$ ojo patch create --author "My Name" --description "Something something"
Created patch rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
输出中的长字符串是你刚刚创建的补丁的唯一标识符。它是通过对补丁内容(包括时间戳,因此即使你有完全相同的 内容,也不太可能看到相同的哈希值)进行哈希得到的。
《ojo》的一个特点是它默认不会立即应用创建的补丁,这与(例如)git commit
不同,后者创建补丁并将其应用到当前分支。如果您想同时创建和应用补丁,请在ojo patch create
中提供参数--then-apply
$ ojo patch create --author "My Name" --description "Something something" --then-apply
Created and applied patch rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
或者,您可以首先创建补丁,然后使用ojo patch apply
命令来应用它
$ ojo patch create --author "My Name" --description "Something something"
Created patch rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
$ ojo patch apply rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
Applied:
vDLmQ2m8JnblI0wPq2bTSYusqNtHOLNo1iRt4nWdyLY=
如果您想取消应用补丁,请使用ojo patch apply --revert
$ ojo patch apply -R rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
Unapplied:
vDLmQ2m8JnblI0wPq2bTSYusqNtHOLNo1iRt4nWdyLY=
输出文件
《ojo》的另一个特点是它不会自动更新文件的副本以匹配内部存储库中的更改。要输出包含存储库当前内容的文件,请使用ojo render
命令。默认情况下,存储库的内容将被输出到ojo_file.txt
文件,但您可以更改它。
$ ojo render # outputs the repository contents to ojo_file.txt
$ ojo render --path other_file.txt # specify another output path
组合使用
$ ojo init
Created empty ojo repository.
$ echo "First line" > ojo_file.txt
$ ojo patch create --author Me --description "I wuz here" --then-apply
Created and applied patch rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
# Now the file stored in the repository consists of the single line
# "First line". The file ojo_file.txt also consists of the single line
# "First line", but that's because we put it there ourselves; ojo hasn't
# touched it.
$ echo "Second line" >> ojo_file.txt
$ ojo patch create --author Me --description "Me again" --then-apply
Created and applied patch xGRnP1j1o9FdJPPJoD6OM4Pxj3qgyN2hKG_0qg54t38=
# Now the file stored in the repository has two lines, and so does the
# file ojo_file.txt.
$ ojo patch apply --reverse
Unapplied:
xGRnP1j1o9FdJPPJoD6OM4Pxj3qgyN2hKG_0qg54t38=
# The file stored in the repository has just one line. To reflect that change
# in the filesystem, we need to render:
$ ojo render
Successfully wrote file 'ojo_file.txt'
$ cat ojo_file.txt
First line
冲突和解决
ojo
处理冲突的基本理论在一系列博客文章中有所描述,请参见此处。主要思想是,与文件不同,ojo
存储“graggles”,这是行的有向图。文件是graggle的特殊情况,其中行的有向图强制执行唯一排序。(更确切地说,如果一个graggle具有唯一的拓扑排序,则它是一个文件。)大多数时候,您希望存储库表示文件;如果它表示的不是文件而是graggle,我们称之为冲突。
以下是如何获得冲突的方法
$ ojo init
Created empty ojo repository.
$ echo "First line" > ojo_file.txt
$ ojo patch create --author Me --description "Starting out" --then-apply
Created and applied patch rLbZ6RjMol8_wV0tW2dnMapcaNVJB25A9uWFXixDU6c=
$ echo "Second line" >> ojo_file.txt
$ ojo patch create --author Me --description "Working hard"
Created patch xGRnP1j1o9FdJPPJoD6OM4Pxj3qgyN2hKG_0qg54t38=
# Notice that we haven't applied the second patch, so the file in the repository
# only has the first patch applied. Now let's edit the file on disk so that
# it consists of "First line" followed by "Alternate second line":
$ echo "First line" > ojo_file.txt
$ echo "Alternate second line" >> ojo_file.txt
$ ojo patch create --author Me --description "Working differently" --then-apply
Created and applied patch y-lgpjY30n5STzqtrMOEkvBM_WUWy0Yji91y9KTzptc=
# And finally, we apply the patch that added "Second line"
$ ojo patch apply xGRnP1j1o9FdJPPJoD6OM4Pxj3qgyN2hKG_0qg54t38=
Applied:
xGRnP1j1o9FdJPPJoD6OM4Pxj3qgyN2hKG_0qg54t38=
现在,那个长命令列表的效果是创建一个包含“第一行”后面跟“第二行”或“备选第二行”,但没有规定这两行可能的顺序的graggle。特别是,结果不是一个文件,因为包含的行没有线性顺序。如果您尝试渲染该文件,它将不会工作
$ ojo render
Error: Couldn't render a file, because the data isn't ordered
您可以使用两个重要的命令来解决冲突。第一个是检查它,通过渲染一个图
$ ojo graph
这将创建一个“dot”文件,可以使用graphviz进行渲染
$ dot -o out.pdf -Tpdf out.dot
现在您可以查看out.pdf
以查看您的不是文件的graggle的可视化。
一旦您了解了发生了什么,您可以使用ojo
的内置交互式graggle解析器来解决冲突
$ ojo resolve --author Me
这个交互式实用程序将引导您通过将无序的graggle转换为完全排序的文件的过程。在上述示例中,这相当于决定“第二行”应该放在“备选第二行”之前还是之后。(在遥远的将来某个时候,我希望为ojo resolve
的用户界面创建一些全面的文档。但现在,希望它是可以合理探索的。无论如何,您可以在右上角查看所有当前活动的键绑定。)
当ojo resolve
完成后,它将生成一个补丁,然后您可以将该补丁应用到文件中,以消除冲突
$ ojo resolve --author Me
# do the interactive thing...
Created patch SfxSwnA2POPHzL4eNNHku7t4Lyl5xW7Ge9pRXr5hV60=
$ ojo patch apply SfxSwnA2POPHzL4eNNHku7t4Lyl5xW7Ge9pRXr5hV60=
Applied:
SfxSwnA2POPHzL4eNNHku7t4Lyl5xW7Ge9pRXr5hV60=
$ ojo render
Successfully wrote file 'ojo_file.txt'
依赖项
~7–17MB
~199K SLoC