

The original workflow, which is still in use today, is git-blame
followed by git-show
: look up candidate commits, then examine their history individually. This can be accelerated with a GUI; e.g. GitHub and GitLab support blame-style views.
The original workflow, which is still in use today, is git-blame
followed by git-show
: look up candidate commits, then examine their history individually. This can be accelerated with a GUI; e.g. GitHub and GitLab support blame-style views.
I agree that the UX of existing git commands is not great. They evolved in a particular insular environment – Linux kernel development with heavy mailing-list usage and large multi-headed merges, with occasional pull requests and manual integration testing.
Check out my top-level comment for a link to git’s data model. A data-first approach with blob
, tree
, commit
, and tag
can be enlightening. The on-disk format tries to balance integrity, easy manipulation, disk space, and incremental updates; it’s also weakly monoidal, enabling distributed development. Look up the history of Bitkeeper and git; this is “a version control system [designed] from the ground up with documented architecture from the start”! And there are many non-C implementations as a result, like pure-Python dulwich.
A PDF is available here, and analysis from Colyer 2016 is good.
This paper is fascinating in terms of ethnography. Consider: the paper mentions “branch” or “branches” dozens of times, but only says “tree” four times, and every instance is in the phrase “working tree”. The paper never mentions “blob” or “blobs”, “DAG” or “graph” or “poset”. The authors either chose to omit git’s data model, or they don’t know about it. The implication is that the UX and UI don’t reflect the data model, I suppose, but it is a very curious omission.
Now, contrast this with Git’s documentation. When sysadmins teach git, we focus on the data first. git is a kind of database which stores four different flavors of object, and the git UI is merely a collection of commands for programmatically manipulating the database. All of the various UX is purpose-built, on a per-command basis, for development workflows. New commands can be implemented as plain UINX-style executable scripts in any language.
In summary, this paper looks at git as a version-control product, while its developers and users look at git as a version-control framework.
There was a followup paper from a few years later, also with Colyer 2016 analysis; this paper has too many glaring defects to discuss here.
On a personal note, I saw this and am happy to note that science has marched along:
We plan to extend our notation to make it more expressive in the future, but are cognizant of the fact that diagrammatic syntaxes for first order logic have a long and troubled history.
Not long after this paper, ontology logs were figured out, which can be made as expressive as needed for the case of relations; see Patterson 2017.
Nix comes closest. The biggest issue with Nix is that it does not admit a clean simple LL/LR grammar, but I think it admits a PEG, which is fine for practical work. The ecosystem could use more independent implementations and tooling, but I haven’t found any deficiencies with the language that would make me prefer e.g. Guile Scheme’s larger standard library and richer types.
HCL is another option. It’s not awful, but it’s verbose when trying to do anything higher-order, and it wasn’t intended to directly represent lambda-style subroutines. Guile Scheme, as used in Guix, is clearly capable, but requires embedding a fairly large standard library or having to NIH common routines; similar problems plague Lua or Python.
I think that your question has an interesting framing. My first answer was to mention jq and the relational pipes toolkit, but those are still run from a top-level shell. For example, I suppose that there’s two things that you can do with JSON: you can manipulate it and I would use jq for that, or you can load it as a datastructure into a (build) action and I would use Nix for that. jq is close to ideal for its particular formalization, but relational pipes are still evolving and I think that there are further simplifications that could be made.