Become a Creator today!Start creating today - Share your story with the world!
Start for free
00:00:00
00:00:01
Solving Git's Pain Points with Jujutsu (with Martin von Zweigbergk) image

Solving Git's Pain Points with Jujutsu (with Martin von Zweigbergk)

Developer Voices
Avatar
0 Playsin 16 hours

Git might be the most ubiquitous tool in software development, but that doesn't mean it's perfect. What if we could keep Git compatibility while fixing its most frustrating aspects—painful merges, scary rebases, being stuck in conflict states, and the confusing staging area?

This week we're joined by Martin von Zweigbergk, creator of Jujutsu (JJ), a Git-compatible version control system that takes a fundamentally different approach. Starting from a simple idea—automatically snapshotting your working copy—Martin has built a tool that reimagines how we interact with version control. We explore the clever algebra behind Jujutsu's conflict handling that lets you store conflicts as commits and move freely through your repository even when things are broken. We discuss why there's no staging area, how the operation log gives you powerful undo/redo capabilities, and why rebasing becomes trivially easy when you can edit any commit in your history and have changes automatically propagate forward.

Whether you're a Git power user frustrated by interactive rebases, someone who's lost work to a botched merge, or just curious about how version control could work differently, this conversation offers fresh perspectives on a tool we all take for granted. And if you're working with large monorepos or game development assets, Martin's vision for the future of Jujutsu might be exactly what you've been waiting for.

---

Support Developer Voices on Patreon: https://patreon.com/DeveloperVoices

Support Developer Voices on YouTube: https://www.youtube.com/@DeveloperVoices/join


Jujutsu (JJ): https://github.com/martinvonz/jj

Jujutsu Documentation: https://martinvonz.github.io/jj/

Git: https://git-scm.com/

Mercurial: https://www.mercurial-scm.org/

Rust: https://www.rust-lang.org/

Watchman: https://facebook.github.io/watchman/

Google Piper: https://research.google/pubs/why-google-stores-billions-of-lines-of-code-in-a-single-repository/


Kris on Bluesky: https://bsky.app/profile/krisajenkins.bsky.social

Kris on Mastodon: http://mastodon.social/@krisajenkins

Kris on LinkedIn: https://www.linkedin.com/in/krisjenkins/


Recommended
Transcript

Do you need to know a specific programming language to be a software developer?

00:00:00
Speaker
What technology do you have to know to be a software developer? I think that's a trickier question than it first sounds because, yeah, you've got to know a programming language, right? But there isn't a specific one you have to know.
00:00:13
Speaker
No matter how big a fan you are of Java, you've got to admit that someone could have a very good career without ever learning it. Same for any other language. No matter how much you love it, there isn't a single must-know language.
00:00:27
Speaker
Same's true for databases, too. You probably need to know how to use at least one database. But there isn't a particular one. I thought maybe I could say the command line.
00:00:38
Speaker
and It's very useful. i wouldn't want to live without it. But don't think you have to know the command line. And anyway, I'm not convinced it's a single tool. There's only one specific tool I could think of that comes close to the definition of must know.
00:00:53
Speaker
And that's Git. mean, is there anything more ubiquitous? Is there any tool that you will find in just about every type of project across the world in every language for every stack?
00:01:06
Speaker
Git is everywhere. It's devoured the version control world. It's devoured the keeping my software safe world. But as great as it is, and as much as I love it, there are definitely opportunities to improve its usability.
00:01:22
Speaker
So, is my guest this week trying to take the crown from the world's most established programming tool, or is he just pulling on a few design threads and trying to see if he can make something better?

Introducing JJ: A new version control system

00:01:35
Speaker
With me this week is Martin von Zweiberg. He's the creator of Jiu Jitsu or JJ. It's a version control system. It's Git compatible, but it tackles commits and versioning in quite a different way.
00:01:48
Speaker
couple of my friends recommended it to me and I've been trying out recently. And it's been a bit tricky because to use it, you have to unlearn a few Git habits. But the upside is undeniably, it has better undo, better redo, easier merging, better conflict handling, much easier rebasing.
00:02:08
Speaker
gonna recommend you check it out if you've ever been frustrated by a merge. And I think that's just about all of us. But before you try it out, let's dig into what it is, how it works, and why Martin created it.
00:02:22
Speaker
I'm your host, Chris Jenkins. This is Developer Voices. And today's voice is Martin von Zweigberg.
00:02:39
Speaker
Joining me today, live from Google's offices of all places, Martin, how are you doing? Hi. and Good, thanks. Yeah. Glad to see you here and and here you hear you here. got to remember it's a podcast as well as a video episode.
00:02:54
Speaker
yeah So i you came onto my radar with a very interesting project, which you're going to have to explain to me first why this project needs to exist, because I know a lot of people are going to wonder what's left to solve.
00:03:10
Speaker
You've created a new version control system, which isn't Git. And Git rules the world. So why are you taking on the king? Yeah,
00:03:21
Speaker
yeah that's a good question. um So it at where i work on source control here at Google and have been working on not that for about 10 years, I think.
00:03:34
Speaker
Okay. um And we we do some we have an integration of Mercurial that we... and integrated with our in-house monorepo that's like before Slack here at Google.
00:03:48
Speaker
And um yeah, so I've been working on that project for for many years before I started this one. And we had been talking about in the team, like what what we would like to improve with our solution here, our internal solution.
00:04:04
Speaker
um And one of the ideas that came up was um like automatically snapshotting the working copy um There were like various other ideas, but like this one i am I found very interesting what the consequences would would be for the ui UX of the

How does JJ handle commits and versioning differently than Git?

00:04:28
Speaker
VCS especially.
00:04:30
Speaker
this is the thing where instead of staging everything to make it kind of semi-permanent and then committing it to make it actually permanent? Yes, yes, yes. Okay. Yeah, exactly. So like if you snapshot the working copy so it becomes a commit, um so like there's no um then it means basically that you have no changes on top of your working copy.
00:04:56
Speaker
And so your working copy, or like in the Git sense, the working copy and there there no and there's no dirty working copy in a sense. um So you can always you're always free to move around between commits.
00:05:09
Speaker
um But yeah, so so this this idea of snapshotting is what how the project started. i i found it very ah promising, too.
00:05:23
Speaker
I wanted to experiment with the the UX of that and see where where it led. So but that's how yeah how it started. i mean, I didn't know where it would lead then, but that was hopefully would work out.
00:05:40
Speaker
I love projects like that where you just get something a bit between your teeth and like, let me just see where this goes. Yeah, yeah, it seems... like It went well so far. Okay, so where did it go? um Yeah, so I started with that. I just um i think from the from day one, it ah it was also I had like pluggable backends because I wanted to be able to like if it turned out to to be useful.
00:06:12
Speaker
I wanted to be able to use it with Git repositories for everyone outside of Google and also ah within Google with a different storage backend. So it I had support for Git backends from day one, I think.
00:06:29
Speaker
um And yeah, so i that that's, ah of course, very useful for being able to like experiment and do anything if you can use it on existing repos.
00:06:42
Speaker
Of course, yeah. So you've got massive... like test bed of all the different Git repos in the world. Yeah. if you will yeah and And of course, that there's it's very hard to compete with Git if you're not compatible with Git, at least at the repo level. like So you can't clone someone's Git repo, it's very hard too to get users because the whole team has to switch.
00:07:06
Speaker
Yeah, I've already experienced this. was trying ja Jujitsu. We actually haven't said the name of it yet. Jujitsu, JJ. Yes. I was trying it out. And of course, the first thing I did was try cloning someone's else someone else's repo and then checking I'd be able to push it back without them knowing I was using JJ. Yeah.
00:07:24
Speaker
yeah Yes, yes. So tick that box. Yes. Yeah, exactly. no That was an important requirement. Yeah, so I experimented with the working copy as a commit concept to see how that went. And it seemed promising, so I just continued working on that. And um then kind of as a as a consequence, mostly ah of that, ah I had to figure out what to do with ah merge conflicts.
00:07:57
Speaker
so um Because when ah in Git, when you when you're me when you merge two branches, for example, um and you run into merge conflicts, you're in a state where that Git has to keep keep track of those merge conflicts, and it does that in the the index. It keeps like the different sides of the um inputs in in the index, in the staging area.
00:08:20
Speaker
Yeah. Um, so if I, since I wanted to be able to like store everything as a commit and be able to switch them freely back and forth between commits, I had to figure out something for of some way of storing these conflicts or. Cause it's like when you've got a conflict in Git, kind of jams the whole thing wide open with conflicts and you're just stuck there till you do something.
00:08:47
Speaker
But you're wanting to take that itself as a commit by your very initiating idea. Yes. yes Yeah. Yeah. Okay. Yes, exactly. they did Yeah. i I mean, it would be an option to be in that state where you're stuck, but like I really didn't want to

Is JJ easier for new users compared to Git?

00:09:06
Speaker
ideally be in that state. Like if you're free to move around, i mean, you you lose basically many of the the benefits of being able to freely move around between commits if you if you don't if you're stuck ah when you have a conflict.
00:09:22
Speaker
Yeah. A number of times I've just ah abandoned my attempt to merge something just so I can get something else done. while Yes. yeah Yes, exactly. Yeah. Yeah, so that was the next thing that um that I had to to solve, kind of.
00:09:38
Speaker
yeah, initially, yeah and i in initially Well, so we store what how we store these conflicts is um when whenever you run into a conflict, ah we store the inputs of the conflict. So if you're rebasing, well, if you're, let's say you're merging commits B and C with A as the the merge base.
00:10:03
Speaker
You know what? I'm going to, yeah we'll get to that, Thor. I'm going to interrupt you and wind back a bit because I found the experience of using JJ to be Like, you you learn so much to learn how Git works.
00:10:18
Speaker
Like, no, you can't commit something. You've got to understand what staging area is first. And by the time you've got through that learning hurdle, it's hard to imagine doing it another way. And in some way, JJ seems weird because it's simpler.
00:10:33
Speaker
Like, there is no staging area. Can you just try and give me a mental model for how I approach this thing as a user? Well, um I mean, to me, I i came from, I used Git and I i even contributed to Git like 15 years ago or something.
00:10:53
Speaker
But then when I joined this team here at Google, we integrated Mercurial with our in-house monorepo, as I said. And Mercurial also doesn't have a staging area. So at least I was used to to that model or I had gotten used to that.
00:11:11
Speaker
um So your your mind hasn't been bent into that shape the way mine has. yeah Yeah, I guess it got straightened out a a yeah on the way. um But, yeah, Mercurial has like a similar model in in in that sense, that there's no staging area, and instead it has nice commands for...
00:11:34
Speaker
like um What Git users usually do, I think, add dash P or or something like that to build up something that's ready to commit in the staging area and then commit it um In Mercurial, you have to...
00:11:50
Speaker
yeah instead like you ah there's an interactive commit command that's basically the same, but then like if you want to adjust that be you before you commit, like in Git you can add more and more to the staging area and build it up until you're ready to actually come commit.
00:12:08
Speaker
In Mercurial you simply commit it and then you adjust, you can um ahend amend, and there's an interactive amend which is like serves the same purpose basically as the ah add dash P after you already have some something staged.
00:12:22
Speaker
So anyway, there there are without the staging area, you you can you can do the same things. um um The staging area isn't really needed as long as you just accept that you create the commit before it's actually ready.
00:12:39
Speaker
Yeah. Yeah, this is the weird thing to me. It's like everything's already always committed. but But then you might sometime, but when you actually like, okay, that's final, then you push on to the next commit and it's all backwards.
00:12:54
Speaker
You create the commit first and then you add stuff to it. Yes, yes. it Yes, it takes a while to get used to. i think I think the commit is just a way of storing the state. It doesn't mean that you're ready to send it for a review or anything.
00:13:09
Speaker
So if you kind of accept that it's just a way of storing your changes, and it's maybe not so strange. Yeah, yeah. and think i'm ah I've been playing around with it a lot. I'm beginning to get used to and I'm beginning to actually really quite like it in that there's, it feels, it feels a lot less formal than Git, but I think I'm right in saying it's equally powerful.
00:13:34
Speaker
Yeah, I would say so at at least. um I think we have a lot of, um functionality for moving commits around, moving parts of commits around that are much easier to use and powerful more powerful than GITs.
00:13:53
Speaker
Tell me a bit about, the before we get into merging, which is I know is juicy, tell me a bit ah about the equivalent of rebasing and shuffling commits around. So there is a rebase command, JJ rebase, which is similar to to git um And it works kind of the same way.
00:14:14
Speaker
ah But it also has, like, we don't have an interactive rebase command, so there's no, um if you're familiar with what that does, it lets you rewrite um rewrite history ah rewrite the commits us as you go.
00:14:30
Speaker
So you can you can stop in the middle and edit the commits, for example. um JJ's rebase command does not do like both

How does JJ enhance the rebase command?

00:14:40
Speaker
of those things. It just...
00:14:42
Speaker
moves the moves commits around. It doesn't let you edit them while you're moving them, as Git Interactive Rebase does. um But other than that, they're pretty similar.
00:14:55
Speaker
Jgs rebase command is more powerful in that it lets you rebase a whole a tree of commits, not just ah one chain of commits.
00:15:07
Speaker
um And it always updates bookmarks to match. And then, then of course, there's the merge, mer um conflict handling that that we have that we'll talk about later.
00:15:20
Speaker
and may I guess you don't need the edit in the rebase because you can just jump to any commit at any time and edit it. yes exactly yeah so Yes, exactly. So instead of this interactive rebase having like the edit and squash and so on, as part of the interactive rebase, we have separate commands for those those things. So we have and and an edit command that um makes the working copy point to the commit you you tell it to point to.
00:15:52
Speaker
so And that can be an an ancestor commit. It doesn't have to be the leaf commit. ah So your working copy can actually be an ancestor of some other commits.
00:16:02
Speaker
And, um oh, I haven't said when we do the automatic snapshotting, but like whenever you run any command, any jj command, will the first thing that we do is automatically snapshot the working copy.
00:16:15
Speaker
um So every time I take JJ, you are creating ah sort of mini commit? Yes. Yeah, I mean, it is it's it's a regular commit. It has all the changes that you see in in the diff.
00:16:27
Speaker
um But, well, if nothing changed compared to last time, then we don't create that commit. But yeah. um Yeah, so if you're editing a past commit, then when whenever you run a command, we ah snapshot that and we see that something changed, we create the new commits and we rebase all the descendants on top. So you're your if you if you had a chain of commits there, you will still have a linear chain of commits on top.
00:16:57
Speaker
Yeah, this is something I've tried to do in Git and it's painful and seems to be easy in JJ. you're like You can go back and edit a commit in the history jump straight into that, change it, and everything ripples through, usually without merge conflicts?
00:17:14
Speaker
Well, that's the same as Git. Yeah, it just seems like there's so much less machinery in the way you're doing it. Yes, yes, yeah, yeah I think so. Yes, I think it's a lot simpler to do. But yeah, we would run into conflict conflicts in pretty much the same cases.
00:17:34
Speaker
I ah guess I have to ask you before we move on from that. If you're snapshotting, if you're creating commits every single time, and I know you must have tried tested this on some very large repos if you've used it at work, is it like a performance is a serious performance hit to create a commit every time?
00:17:53
Speaker
No. Why not? not um so i know um I mean, creating commits is pretty cheap. ah it It doesn't take long. um Rebasing is also...
00:18:05
Speaker
not terribly slow. I mean, it's not if if you tried it... you ah like um I did some performance performance tests like years ago um and in the Git repo, and we were able to rebase about 1,000 commits per second. So it's it's like... um If you use Git before Mercurial or something, um that seems very fast.
00:18:29
Speaker
But like the reason Git and Mercurial are slow, or at least the reason Git is slow, um is mostly because they do the rebase in the working copy. As as you rebase each commit, to you update the working and copy to that state and run any pre-commit hooks and whatever. um theres There's a gi git replay command that does this basically the same thing as as we do. Rebase the, rewrite the commits in memory, and and that's a lot faster.
00:19:00
Speaker
Oh. so Okay. like yeah Creating commits is not that slow, really. But I would have thought there's a performance hit to re-scanning the file tree and rehashing all the files to check they haven't changed.
00:19:14
Speaker
Yes, that that definitely, ah that can be slow. um and But Git has that problem with Git status too. it's ah You have to scan the the working copy too to see what has changed. so Yeah, I suppose it must do.
00:19:29
Speaker
Yeah. We have an integration with Watchman, which is a file system watcher that makes that faster if you are in a very large repo, or like a repo with a large working copy.
00:19:41
Speaker
Okay. Hey, I'm jumping around here, but you you have to be okay with that because your very tool lets me jump around the branches very easily. Okay. um okay so
00:19:55
Speaker
if it's not performance hit, you are scanning every time you're storing everything as a commit. You, I think we need to talk about how you're storing things because is it just, is it literally the same as Git?
00:20:10
Speaker
Cause you're kind of giving me the impression that JJ is a user facing tool over a Git storage engine. Um, yes and no, um,
00:20:22
Speaker
So, yeah, I mean, as I said, we we have pluggable backends, so we can work inside the Google repo, for example. um And so Google, we have a different storage backend where we write commits to ah database.
00:20:36
Speaker
um So that's very different than obviously not Git-backed. um But also, like even if you're in ah using the Git backend, um we ah We used to store some some of the data outside of the Git commits.
00:20:55
Speaker
um um and because We it yet, but ah we haven't talked about it yet but like in One of the first things you see when it runs JJLog is what we call the change ID, which is like a stable identifier that follows a commit as as it gets rewritten. So if you change the description of commits, it it keeps its change ID, even though it gets a new commit ID.
00:21:22
Speaker
Right. Yes, because if you're creating a new commit every time something changes, I'm going to end up with a vast number of random shars. I need something to refer to my logical thing I'm working on today.
00:21:36
Speaker
ah Yes. Yeah. I mean, yeah you we could use the the commit ID just like Git does, but it's just ah it the change ID, the stable one is just much more convenient. It means like like if you...
00:21:53
Speaker
run jdlog, you see some change ID. For example, you can um run jddescribe to update the description of of that commit, and then um you can rebase it again without having to look at its new commit ID. You can refer to the old ah the same change ID as it had before because you know it keeps it.
00:22:11
Speaker
Right, yeah. That in itself is useful. so Yeah, yeah. that Okay. Yes. i those The change IDs are very useful for for just ah using on the CLI.
00:22:23
Speaker
um But yeah, back to where we store stuff. so So the change ID, for example, is something that we have that gi doesn't store in its commits directly. ah So we used to store some stuff outside of the of the Git repo. So we create just regular Git commits with a few pieces of metadata in our own custom storage on top of Git.
00:22:46
Speaker
um but yeah like Gradually, we have moved all of these into git commit object. So these days, we stored this change ID um in as a git header in ah in the git commit object. So like if you if you say if you push that to remote and someone else pulls using JJ, they will they will see that um same change ID.
00:23:13
Speaker
Okay, so to make sure I understand this, I know that when Git stores like a file, it's it stores something like the string file, and then um a size, and then some header separator, and then the actual contents of the file.
00:23:29
Speaker
ah Yes, but that's a different thing. um that Well, yeah, that's the... um That's how it stores blobs, so file files, as you said. um But ah commit objects are stored um with some headers, and like one one header is the committer, and one is the the author.
00:23:50
Speaker
one parent Parent. Parent, yes. And the the tree it points to. um But you can add custom headers there. um And that's what we do. we add this ah change ID as a custom header.
00:24:05
Speaker
OK, so a git header for a commit, well, it's basically key value pairs in the header. yeah And you can just add stuff in. Yeah. OK, and then this file objects and trees are the same.
00:24:19
Speaker
um know So the in the Git model, there is there are files or blobs, um yeah which is just file content, and then trees, which is like a directory.
00:24:34
Speaker
um And those are recursive, so you would have um one for each single directory, and then they point to the the child directories. And then at the...
00:24:46
Speaker
top you have some one single tree for the root directory, and the git commit object points to to that tree. And JJ uses basically the same the same model. That's how we're able to be so compatible with Git, because the models match very well.
00:25:03
Speaker
That also sounds more than simple enough to store in an arbitrary database, too. Yeah. modulo garbage collection? Because if you're snapshotting all the time, you must generate more unused commits.
00:25:17
Speaker
ah yes Yes, definitely. um it It's usually not really a problem, but yeah you can um we do have garbage collection these days. like there's a ah There's a command to like abandon We haven't talked about the operation log, but we'll get to that, I guess.
00:25:35
Speaker
Definitely. You can tell it to abandon old stuff and then we just subprocess Git's GC to garbage collect the actual Git objects.
00:25:48
Speaker
Okay. Okay. So, yeah, okay. I can see how it's quite similar. So the next thing I definitely want to talk about, we're going to get we're working our way towards merge, but I'm assuming they're the scariest part of this, so we'll save it.
00:26:01
Speaker
The op-log, this is interesting. This is ah for the first really compelling reason to snapshot everything.

What is JJ's operation log and micro undo capability?

00:26:09
Speaker
Tell me about the op-log. um Yeah, so the op-log is... um It actually started as um a solution for concurrency ah problems.
00:26:25
Speaker
Okay. um So I... We have um at Google where we use this Mercurial thing on top of... um We we were you store Mercurial repos on top of a distributed file system, and this often runs into...
00:26:42
Speaker
um well once in a while at least, it runs into ah concurrent writes from different machines, and which corrupts your repo. Yeah.
00:26:53
Speaker
Fun. yeah fun So the oplog started as a as an attempt a successful attempt i think to to to to solve that problem.
00:27:06
Speaker
um And it's what it is, is just um if you think of all the the branches in your Git repository, for example, or all the refs, including head, we just basically snapshot that.
00:27:21
Speaker
um So the oplog contains ah Like it's it's similar to commit graph. it's ah It's a DAG, just like a commit graph.
00:27:32
Speaker
um And it keeps track of where all the branches currently point at every point in time. So after every every command we update this, they create a new operation and with a snapshot of all where all your branches or like bookmarks, as we call them, point.
00:27:52
Speaker
I have And this is the thing that enables me to kind of micro undo. yes Yes. So so yes, it started to to solve the the concurrency problems, but yes, it's very useful for being able to go back in time. You can restore your repo to ah past point of like if you...
00:28:15
Speaker
um if you rebase something and turn and you decide you didn't actually want that, you can go back. um um And you can go back multiple steps, not just one step. And we can um load the repo at any point in time, and you can run JJ log at the specific operation to to see what your log output or any command um output should look like at any point in time.
00:28:41
Speaker
Oh, okay. So I can... I can go back and get the log as it was before I rebased trivially. Okay. yeah One thing I found, I've been playing around with this a lot. you you're You're luring me in slowly.
00:28:57
Speaker
um One thing I found really useful is i often, when I'm developing with Git, I will put things i definitely like into the staging area so that I can easily throw away the other changes if I need to, but keep the important ones.
00:29:14
Speaker
but I don't yet want to commit them. And maybe I should, maybe it's bad habit, but that's something I do. And I have definitely run into the case with jujitsu where um I sort of wished I'd done that on a so on a more fine grained level. And I can just undo individual snapshots I took without even thinking about taking snapshots.
00:29:35
Speaker
I can step back to where I was a few minor changes ago. So like the way I'm staging things, but even more fine-grained? um I think what you're asking is for, like, we don't have a very good way of...
00:29:53
Speaker
of doing that today, I think it we should make it simpler. But there is a ah JJ evolution log or evo log to look at the past snapshots of a single change. So as I said, the change is this thing that stays constant as you um modify it. but And every time we snapshot, we amend and into the same change. And the evolution log she shows a log of how your working copy or or any other commit has been rewritten.
00:30:25
Speaker
So there will be a future where i get an animation of all the but from deltas that came in to make that change. Yeah. Yeah. Yeah. yeah I mean, there's a jjevo.log-p to show the the deltas.
00:30:36
Speaker
Okay. Someone's going to be training in LLM with that before long. All the extra data about how working commits are gradually evolved. Yeah. can totally see that.
00:30:48
Speaker
Okay. Um, I think, I think we've got to go for it. we've got to dive into conflicts. So here I am with a system that's a lot like Git.
00:31:00
Speaker
How are you handling conflict? How do you do it better? Do you think than the way Git handles conflict? Um, yeah, ah as I said, we do, we record conflicts in, in commits because we want everything to be, to be a commit. Um,
00:31:18
Speaker
And um it's not the conflict markers that we store.

Resolving conflicts in JJ vs Git

00:31:23
Speaker
People often think that when they hear that we store conflicts, it they assume we just store the conflict markers. Yeah, I assumed you were storing like can broken up files that won't compile anymore. yeah um Yeah, no. So what we store is the inputs for for the merge.
00:31:41
Speaker
um So um like if you have if you have some base commit a and you have commit B and C as children of that, then you now want to merge those two.
00:31:56
Speaker
um What we um store in in the child commit then is those three inputs. We store the the tree that's from a as the base and this a tree from B and C as the two sides that that we have to merge.
00:32:14
Speaker
um And then like if but if if we can resolve that automatically, then then we do that and we just store the resulting tree in in in this a child, the merge commit.
00:32:26
Speaker
right um But like if we can't, then we we keep those three input trees ah in in ah in the commit, and also as this kind of git commit header, as I mentioned before. before yeah We use that for conflicts too.
00:32:43
Speaker
So if there's a conflict, we store multiple trees instead of just git single tree. Right. References to those different trees. Yeah. So you're not taking up much space.
00:32:56
Speaker
And presumably this works because it's always cheap to recalculate what the conflicts are. Yes, it seems like it it might be a bit expensive, but it's it's not too bad. like we Yes, we exactly. so so um We do that on the fly whenever... ah So if you're if you look at the the file, if you check out this commit, for example, we... we redo that conflict resolution. and um And of course, if since this was presumably ah a conflict, we had some conflicts, that's why we had multiple trees, then we materialize those conflicts as conflict markers in the working copy. So um when you check it out.
00:33:43
Speaker
The inputs are immutable. It's a pure function to commute to calculate the conflicts from those immutable inputs. Yeah, okay.
00:33:54
Speaker
yeah I can see that. So whenever you yeah check out the commit or your diff or or like restore the state from that commit or whatever, then we would calculate those conflicts on the fly.
00:34:06
Speaker
So if I... go back in time five commits, and we're all gonna want a diagram for this, but I'm gonna try and describe it accurately. If I go back in time five commits and try and merge in something new that's conflicted, that's gonna be updated to store the inputs that would conflict.
00:34:27
Speaker
What happens to the first descendant of that, which is now supposed to be based on a conflicted merge? Ah, yes. Good question. So um here we do something um that I haven't seen anywhere else before.
00:34:47
Speaker
ah We do some simple algebra on conflicts, states. um So in... this The conflict I mentioned before, we had base A and trees B and C that were merging.
00:35:01
Speaker
um the The conflict state there we ah we it will be like B plus C minus A, or like equivalently C min plus B minus A. So if you think of the ah the changes that were introduced in commit C um that was based on A. So that diff is C minus A. um So if you apply that on top of yeah B, then you get this ah this expression.
00:35:36
Speaker
Yeah. um Okay. Slow down a second. You can treat diffs as algebra of one commit minus another commit. Yes. Yes, you can. Yeah.
00:35:47
Speaker
Yeah. Thank God you're doing it, but. Yeah. Yeah. Okay, carry on. Yes. It's... and it's Not obvious, but it's ah it's pretty simple once you once you figure out that you can you can do this. um And then the expressions also, like these expressions, I mean, they're very simple expressions, just plus and minus.
00:36:08
Speaker
um So what happens with the descendants that you... um ah I'm not going to try to describe those those expressions in detail because it's hard without the picture.
00:36:21
Speaker
um But yeah, we we propagate the... the change So like if the commit on top was commit D, for example, um and its parent was C, let's say, then we apply that and we add that to the ah to the expression we had from the this new commit that you you mentioned.
00:36:45
Speaker
And like in some cases, that simplifies and and becomes not a conflict or becomes a simpler conflict, for example. So I'm picturing some kind of simple addition-subtraction expression where, just like regular addition-subtraction, sometimes things cancel out and simplify, and you end up with, hopefully, one term at the end.
00:37:09
Speaker
And that's great. And if it's not, there's a conflict, and we still need to address it. yes And presumably, sometimes that means when I resolve an earlier conflict, the subsequent equation just magically flattens out, and I don't have more work to do.
00:37:24
Speaker
Yes, exactly. That sounds really quite elloquent elegant. Yeah, yeah. It turned out to work pretty well. um Yeah, so one one simple example, ah ah one one way to test this is like if you rebase a commit somewhere and it results in conflicts, if you rebase the same commit back to to where it was before, the conflicts will ah will go away.
00:37:50
Speaker
ah and it I mean, you can do the math on a whiteboard after or something, but yeah, it's it's pretty simple and it's it it works in practice. Yeah.
00:38:01
Speaker
Are you doing that on a per commit basis or a per file basis? Good good question. um Both. and we So this this ah merge merge conflict algebra,
00:38:15
Speaker
um We do it in lots of places. We do it, yes, initially at the tree level. And if there are ah conflicts there, we try to descend into subtrees and so on. And then we descend into the files.
00:38:32
Speaker
um And um like then we do use the same same algebra for the individual hunks in a file.
00:38:42
Speaker
So hunks are the different parts of a diff. um And we also do it at ah higher levels, like refs when you update, when... um when the remote changes ah a ref, like a bookmark, moves a bookmark or a branch ah forward and you move it forward,
00:39:02
Speaker
um um then we like ah then use the same conflict algebra for for those. And like in some places cases, they they simplify and and become not a conflict. And like otherwise, we actually you can have conflicted bookmarks in JJ.
00:39:21
Speaker
So if if you change the bookmark and the remote change the bookmark, then you will have, in some cases, you have a conflict ah and you have to resolve that. Yeah. you're too I'm still thinking in Git terms, but this is when your two branches have diverged in a way that can't be you know yeah and you're automatically resolved.
00:39:40
Speaker
Yes. yes yeah and Yes. In those cases, we will mark the the the branch or bookmark itself as conflicted. Yeah. and Okay. that on the surface, having yeah now getting conflicts in bookmarks as well, that worries me. But yeah it does lead to a system where you can jump around, do get work done, and come back to resolving conflicts when it suits you rather than when it suits the version control system.
00:40:10
Speaker
Yeah. Which is nice. um Yeah, it's not that different from... Git, I mean, you can still have divergence, it just doesn't get um displayed in the same way, kind of. Like if your if the remote branch was moved forward and your local branch moved forward, then you will still have to resolve that somehow and in Git, like the origin slash master and look and just the local master or something.
00:40:41
Speaker
Yeah. Okay. I think I have to go and ask this now. What is a good language for writing a mixture of file system scanning and um difference algebra?
00:40:55
Speaker
What's this written in? And is it a good choice? Rust. Rust. Okay. Yeah. um Yeah, it was just... um I had...
00:41:07
Speaker
I mean, not much thought was put into it. I had heard good things and I wanted to learn Rust when I started the project. so Fair enough. I picked Rust. I was wondering if you going to say Go because of your origins.
00:41:20
Speaker
No, I've never, i don't know, never been attracted to Go for some reason. okay Oh, and I should say that um ah some some thought was put into it. like it's In particular, our experience from Mercurial ah led me not to want to use an interpreted language, at least like Mercurial is written in Python.
00:41:44
Speaker
didn't know that. And we had so many performance problems, mostly because of that, I think. Oh, yeah. i It seems like something you want to write in C or one of its descendants.
00:41:57
Speaker
Yeah. Yeah. Yeah. like I didn't want to write and in Java or Kotlin or something either. Yeah. Okay. That's fair. but's um ah Both Rust, Go and see ought to be on the shortlist for a project like this.
00:42:11
Speaker
Yeah. ah Well, for me, not C. It's just too hard to, ah too easy to make bugs and too hard to write, to be productive for me, at least.
00:42:21
Speaker
Okay. and In that case, let's let's go back into feature space for this, because there are, like, as soon as you say, I've got something that works with Git, people are going to say, does it do X, Y, Z that I'm used to from Git? And I'm afraid i'm going to ask you those questions.
00:42:37
Speaker
So... um We've talked about merges and conflict resolution. How about bisect? Can I do the equivalent of git bisect? No, that's something I really want to add, but um haven't found time yet. um I mean, the good thing is if you're in a git repo, you can use git bisect.
00:42:55
Speaker
um it But does it still work? Yes. So I can use, can I do both tools coexist on the same repo happily? Yes, yes. we we have um ah We call it co-located mode when there's the.jj directory and.git directory are both in the same workspace.
00:43:17
Speaker
um And then you can run jj commands and git commands. and um So how that works is whenever whenever you run ah JG command, we check what the latest state in Git is, and we import any recent changes.
00:43:33
Speaker
And then like at the end, after yeah have run were finished running JG command, and um we update the Git bookmarks and head and so on. So it's a match.
00:43:45
Speaker
So I could use JJ a bit and then go running back to Git when when I need something familiar for a particular operation. Yes. Okay. In that case, i'm just I'm raising my hand for the feature request of bisect.
00:43:57
Speaker
Yes. No, we definitely want that. Okay. Is that going to introduce a new performance issue because you will then have you can't do it everything in memory anymore? You need to check it out physically to the file system in order to run a bisect and um bisec execution command.
00:44:16
Speaker
um Yes, that will have to to run in the working copy. Yeah.
00:44:25
Speaker
yeah I guess it's a price worth paying. Sorry? I guess that's a price worth paying if you actually want to bisect something. Yeah, it will have to run in some working copy at least. I mean, we could possibly make it run in a different working copy, but it will still you will need to do a build. mean, typically at least you would need to do a build and run some tests and something. so Okay. It needs a working copy.
00:44:47
Speaker
I can think of one thing that you might... might do in a bisect-ish way that would still work in memory. So let me ask you if you've got the equivalent of git grep.
00:44:58
Speaker
I want to grep through everything that's been checked in.

Parallel development with JJ's multiple repo support

00:45:01
Speaker
um No, we don't. um yeah i I guess we will get that someday, but yeah, no.
00:45:10
Speaker
Okay, that's fair that's fair. I could probably just check it out myself and and grep. Yes, yeah. Okay. um Yeah, we do have the...
00:45:21
Speaker
ah pickaxe, git log dash t or dash s. I forget which one is which. That's the one that searches through all the old commits looking for the string you want.
00:45:32
Speaker
Yes, yes. Okay. That's very useful. Sometimes that's the that's the hard one, isn't it? Because git grip is just searching your working copy and ignoring the git ignore files. Yes.
00:45:43
Speaker
But searching history is the one you actually need a tool for. and yeah And um this is a feature, because we live in the age of LLMs and agent-based coding, this is a feature I find myself using more and more and more Git work trees, where you can have multiple versions of the same repo checked out on your file system.
00:46:05
Speaker
And when you commit to one, and you've committed to all of them. Do you have that? yeah Yeah, that's been supported for a few years. yeah um it It works in a very similar way.
00:46:16
Speaker
What made you add that one sooner than, say, Bisect? um Is there a reason? i I'm not sure. Yeah,
00:46:33
Speaker
yeah I'm not sure. we do what We want that at Google, but I'm not sure um how how important it actually was. but um
00:46:45
Speaker
it Yeah, I don't know. it's It wasn't that hard to add, and it fit's it fits nicely in the model. But yeah, Bissect is not really a ah that much work either. It's just that no one has prioritized it, I guess, because they fall back to Git Bissect instead. I i mostly want it at that's Google, so it would be...
00:47:11
Speaker
um would be really nice when whenever someone finds time to implement it. Okay. That makes me wonder how many people are working on Jiu-Jitsu. ah ah You mean up upstream? Like the open source project?
00:47:24
Speaker
Yeah, yeah. um um It's, I mean, people are, some some people are more active than others. Always.
00:47:35
Speaker
We're maybe... 10 people who are pretty active. Okay. I mean, there is especially one person who has who writes like 50% of the code these days.
00:47:50
Speaker
And it's not you? No, it's not. i I spend too much time on um internal things. And yeah, it's hard to find time to to write much code these days.
00:48:01
Speaker
Okay. So what does that mean for your your hopes for the project? I mean, are you are you envisaging a day when one day there's a JJ hub, which Microsoft are wishing they bought years ago?
00:48:15
Speaker
Yes. Yes. I yeah i think a lot of um a lot of us in the community are hoping for that date too. um And Yeah, this actually is something I've been a little surprised about, how um open the community is to the kind of workflows we have at Google and and supporting our integrations here.
00:48:40
Speaker
um Because they're not immediately relevant to most of the community yet. But we're we're hoping that we'll get there eventually, like having...
00:48:51
Speaker
this kind of um ah cloud-based, cloud-hosted repositories outside of Google too. And ah the virtual working copy that way that we have at Google have something like that outside of Google too. So yeah, I think the many in the community are are also looking forward to to that day.
00:49:13
Speaker
who he What do you think you need? i mean Is this a project that just interests you and is the way you want to work? Or are you trying to like broadcast, to develop a mindshare, like come over to the light side?
00:49:32
Speaker
um I'm not sure. um But yeah, I yeah i think that we we do. We have, ah it seems like the community, like we have kind of a ah pretty shared vision for the the project, at least.
00:49:51
Speaker
um if I'm not sure I'm answering your question correctly. but I'm just wondering how much your community is like, how much is this a technical project and how much is it a, we need to go go for the hearts and minds of developers and say there's a better way than Git?
00:50:11
Speaker
um Yeah, I think we we i think it's definitely quite a bit of that. i think we ah most of the community is very um passionate and like think we have something that's better than Git in for, I mean, not for everyone. I think it's honestly, a lot of Git users um don't do much more than just Git commits, Git push, Git pull, and that's almost it. If if you don't your project doesn't have um um ah doesn't like care much about keeping a clean history and having small small and and atomic commits,
00:50:54
Speaker
Or if maybe youre just you have you're just working on your own personal projects, you so you don't care much about that either, then there's not much benefit. I maybe Undo is nice, but other than that, it's um you don't need all the tools for it cleaning up history history and so on Yeah.
00:51:14
Speaker
I'll tell you one place that's come to my mind that I think it would be popular is... There are a lot of new programmers, and I might be using that term slightly loosely, like people doing agentic coding, ah who really need to learn about source control.
00:51:34
Speaker
We've all read the horror stories about the the agent made a change and now my repo doesn't work and How do I undo it? I've got no source control. A simpler model to teach people than Git, where you can just say, type this and you'll save a snapshot and then you can just ignore it and you'll be able to undo it later.
00:51:52
Speaker
Yes. Yeah, I do think it it might be. i I honestly have little experience with ah working with agents myself, but um I do think it it feels like a model that's um perhaps simpler for to to to use with agents and have the agent produce work on us in a separate workspace or something and and ah give you a commit back when it's done.
00:52:21
Speaker
Yeah. So. Yeah. I wonder if, uh, cause I wonder if the reason I found it a little bit hard to get my head around is because of the things I've learned that bend my mind out of shape with Git.
00:52:35
Speaker
I think it might be an easier tool to teach a new user than a seasoned user.
00:52:43
Speaker
Yeah. My, my, there might be some, some truth in that. Yeah. Um, I, Since like almost everyone already has experience with Git, it's i'm not I don't meet these people much, so it's hard for me to say. but yeah um And also, ah we also haven't focused much on documentation for these users because everyone uses Git so far.
00:53:10
Speaker
Yes. so yeah I've seen more tutorials for how you come from Git than how you get started completely. fresh. Yes. it's hard It's hard to know what you what you've learned so long ago that it seeps into your bones, I think.
00:53:25
Speaker
Yeah. Okay. ah we're We're getting too philosophical. um Let's pull it back to tech. there' There's one other thing I wanted to ask you about, like the nuts and bolts, which is what the over-the-wire protocol.
00:53:38
Speaker
Do you just use Git's push and pull mechanism, or do you have something different? No. ah Well, yes and no. When ah using the Git backend, the remote is a Git remote, um like GitHub or GitLab or something like that.
00:53:56
Speaker
So yes, it's just the regular Git protocol. And actually, we even just self-process to Git push or Git fetch. So yes. um in Then internally at Google, we have our own protocol that uses gRPC to talk to our server.
00:54:20
Speaker
um And yeah, that's completely custom. And it's not actually it's not defined by JJ, the project itself. It's completely custom to Google. um yeah So it's is that kind of network stuff the concern of the storage engine rather than JJ itself?
00:54:38
Speaker
it Yes. um So there's... I haven't mentioned this. We talked about GITs, how we actually store stuff in GIT before, but I um ah you said that we store commits as regular commit, ah Git commits.
00:54:54
Speaker
But I forgot to say that we also have like a higher level integration with JJGit commands, and those um um like bypass the...
00:55:05
Speaker
the backend storage abstraction so that they're like, talk directly to the Git backend, as I said, run, Git push, for example. And so like similarly, internally, we have these commands called JD Piper because our backend is called Piper.
00:55:26
Speaker
And these they are they talk directly to our server. Okay. Then I'm just going to ask you of pure curiosity, if someone wanted to add another storage engine for their custom needs, what kind of work goes into that? How hard is that? How much work?
00:55:47
Speaker
um It's not very hard. um and the We actually have a several different storage backend abstractions, but for just storing commits, um all you need is basically read and write file, read and write tree, read and write commits, and that's about it.
00:56:12
Speaker
The abstraction is at a pretty low level like that, so you don't need to do anything about diffing or merging. That's all in the JJ library itself.
00:56:25
Speaker
Okay. And I would write that in Rust? Yes. Yeah. mean, you can obviously FFI to whatever you want or RPC to somewhere, but yeah.
00:56:36
Speaker
Okay. That makes it sound like quite a nice separate, I guess Git has that notional separation between the plumbing and the porcelain, as they call it. Yes, yeah but it's different. Like they don't have a way of replacing the storage.
00:56:54
Speaker
there's There's talk about about that in the Git project, but I don't think they're anywhere close to um actually having it done. Okay. So you need I guess you need to sort that architecture out early or it's a real pain to untie later. I think so.
00:57:10
Speaker
So i' going to ask you about the future. Obviously, going to finish this call and you're going to go straight to doing BISECT just for me. But after that, what were you hoping to put it? Is JJ finished?
00:57:25
Speaker
What's next? How much work does it need? um So one of the large current projects is copy tracking. We don't have support for copies.
00:57:38
Speaker
um like We have very limited support. We have support that's only with the Git back, and like when you i mean which is what everyone outside of Google uses. So um when you diff two commits, we we call into it ah ah diffing code for detecting copies.
00:58:00
Speaker
But um we have a more long-term plan to actually record ah record copies and renames um and in ah So unlike Git, which detects copies on um um the fly, so if you if you do Git CP, it doesn't doesn't actually do anything, as you may know. It just creates a copy of the file.
00:58:27
Speaker
Because in Git, it's just... you hash the file if it's got the same hash, then it is the same file with a different name, right? Is that what you're talking about? Yes, even if it has changed, then like there's Git.
00:58:41
Speaker
I don't actually remember the flags, but Git diff can detect copies that are just similar. But okay um the the point is that Git detects those. It doesn't record them. So if you do Git CP, it doesn't record in a metadata saying that the file was copied.
00:59:00
Speaker
It's just working on a heuristic of the diff. This hasn't changed much, so it must be the same file originally. yeah Yeah. Okay. um so but but But we want to record that information instead. So we have we have a design doc that took me ages to complete, but like we have a design now that I believe in. um And ah so we're going to to work on that and get support for copies done later.
00:59:27
Speaker
done so Why is that good? I'm not instantly seeing why you need to track that. um oh One reason is that it's expensive to calculate on the fly.
00:59:42
Speaker
um like like the ah Detecting copies, especially copies, Detecting renames is not that expensive because you only need to find the files that were added and files that were removed in same same committer between the between the two trees you're comparing.
01:00:02
Speaker
um And then like only those could be our candidates for renames, but like if you're if you have a copy, then you have to look at all the files in the repo um to to find where it could possibly have come from if it's just similar to some other file.
01:00:18
Speaker
Yeah. yeah git Git has some different flags for for this. I think it's git diff. i think it's get stiffff that has dash dash find copies harder or something like that too to to look extra hard for copies and um because it's expensive. So they have these trade-offs depending on what you actually need.
01:00:38
Speaker
um But and like especially for big repositories like Google, there's obviously in no way we can... um scan the entire repo for for for all the files.
01:00:50
Speaker
um So I think that's the that's the main reason. But yeah, it's also it's also um useful to be able to explicitly say that a file has been copied from a particular place. like um I think especially in large repos, it's not...
01:01:10
Speaker
obvious, like if you just detect it it, it may detect the wrong file that just happened to be similar, even though it's not where you actually copied it from, and it may be a bit illogical. So I think there are yeah cases like that too.
01:01:22
Speaker
Especially if you've got, I mean... Google must have, if it's got a mono repo, it must have vast amounts of Java files that look roughly the same, even though they're not copies, Yes, yes. So just detecting it in all those cases would be yeah but yeah confusing, I think.
01:01:39
Speaker
no I am reluctant to ask you any Google-specific questions for fear the lawyers circle around us. So let me try and ask this and in a

How does JJ handle performance with large repositories?

01:01:48
Speaker
generic way. You have used JJ on a truly vast repo.
01:01:53
Speaker
How does it perform and which bits were hard and did you have to optimize anything when you realized? um Yeah, ah it it performs pretty well. um it's we like they're basically to We run it in two different environments.
01:02:11
Speaker
One is the CLI, where we're on the local user's local machine. And we have daemon process that ah takes care of caching and stuff. like making um When you create the commit, for example, we just write it to the daemon, then the daemon flushes it in the background. So that reduces latency locally.
01:02:35
Speaker
um And the other environment is the server, where for which is used for um our cloud-based IDE. um And that that like that doesn't have as much caching, so things are slower in that environment.
01:02:50
Speaker
um it's It's still um comparable, slightly faster to our existing Mercurial-based solution.
01:03:02
Speaker
um But yeah, locally, it's it's pretty fast. um like even Especially thanks to the caching on the Daemon. um And we also do, um many algorithms are like do things concurrently. So like when you need to read files, for you we read them concurrently from from the backend, for example.
01:03:27
Speaker
Ooh. Okay. was going to end there, but you've just opened a can of worms. You're doing concurrent file reading in Rust. Are you using something like Tokyo, some kind of async thread or forking? How does that work? um Yeah, we use a eight async Rust, yes. Okay.
01:03:48
Speaker
um but Because the slowness is almost almost all I.O. It's not that much processing usually. believe so So just async on with even with a single thread is sufficient to make it make it fast.
01:04:05
Speaker
um yeah We still have a bunch of things that are too serial. like but yeah It's possible, at least. we shouldn we ah Generally, we can do a lot of things in concurrently, but like um like when you walk at ah a tree or two trees to come to to diff them, for example, we can um you you're limited to the depth ah of the of the tree because you can only want walk one level of a tree at a time to find what's different at the next level. But like at the single depth, you can ah do all those reads of trees concurrently and the files within trees too.
01:04:48
Speaker
Yeah. Yeah, and i see it's like that JavaScript thing as well, isn't it? Like if you just pushed reading the file to an event loop so that you didn't have to block what you're coding while you wait for the file to come back. you can get You can get work done, at least conceptually, you can get work done while the OS work worries about pulling the file in.
01:05:10
Speaker
So this is why single even single-threaded asynchronous code works better. yeah Yes, yes. Okay. Okay, that that was that was simpler than I expected.
01:05:22
Speaker
Yeah. Okay. um I have to ask you, is there anything else we've missed out, anything we should dive into? Any more Easter eggs like that before we go? ah you You asked about the future. Yeah.
01:05:36
Speaker
the I mentioned the short-term copy tracking. um I think long-term I mentioned a little bit before about the how we're hoping that will be a JGHub or something like that with like native ah and the cloud-based ah storage of repos and VFS.
01:05:59
Speaker
um And we also want to ah add better support for large files. So Git has these LFS extension. um Git NX, I think, is maybe a different version of it or something.
01:06:13
Speaker
yeah um But yeah. o We want to be able to support large files better natively and and not need... So the user doesn't like see a difference between large files and regular files.
01:06:30
Speaker
um So that's... um I think that will that can largely be solved by these cloud-based forges, including the one at Google. we large Large files is...
01:06:44
Speaker
ah mostly a problem in Git because it like the at least before partial clone, Git these days has partial clone support, which like doesn't download all file content. But um but yeah even with partial clone, like it it it reads files unnecessarily like when when rebasing and and other things. Yeah.
01:07:11
Speaker
So I think, anyway, where I was going with this is ah I think we should be able to support like ah game studios and similar companies where that are currently kind of stuck on Perforce um because they have large file content. um So I would really like to be able to help ah game studios get better VCS.
01:07:36
Speaker
Yes, that would be a huge market. And I could see how rebasing is going to work better with JJ because you don't need to check everything out to a working copy and yes do sometimes to do very little actual work before you check out a different... Yes, yes.
01:07:53
Speaker
How is that going to work, though? Do you have a plan for it? Well... well I'm putting you on the spot. No, we do we do have a do have a plan. one I think much of it will be helped by just having a native cloud-based forge.
01:08:15
Speaker
So um if you just never download these files and you read them from from your ah your backend on demand, and that as as you said, that demand is much smaller than in Git because we don't update the working copy all the time,
01:08:29
Speaker
yeah um That helps a bunch. um and ah But we're also looking into ah CDC, Content-Defined Chunking, so of which should help ah reduce the amount of ah content to transfer if you when you update binary files. like It splits um ah splits binary files up into smaller pieces and and transfers only like the the parts that have changed.
01:08:57
Speaker
Yes. Now, I don't know content-defined chunking algorithm well enough that I'm going to open that can of worms, but I do know enough that it's like yet sensibly splitting files, not just about ah file size boundaries.
01:09:11
Speaker
Yes. um Yeah. and I just think it still depends and a lot on on the actual file. like If it's an archive, it's essentially random ah and there are no boundaries that match. So, you know, that case, it doesn't help, but hopefully there are files that are um more structured.
01:09:31
Speaker
Yes. If I, if we've got a huge file and I have one bite at the start, does that make it look like an entirely new file? Because all the offsets have changed. That's the algorithm, right?
01:09:42
Speaker
Yes. Being smart about that. Yeah. Yes. Yes, exactly. Okay. I think that lead that leaves us with an algorithm to go and look up on Wikipedia. Yeah. Yeah. And I need to leave you to go and I feel guilty about saying this. I need you to leave you to go and write ah JJ Bisect for me.
01:10:01
Speaker
Well, I either go off and um ah beat you to writing JJ Hub or at least get a really nice Vim plug in for JJ going because that's what I'll need. Yeah. Nice. Yeah.
01:10:12
Speaker
Awesome. its Martin, thank you very much for taking me through it. Yeah. Thank you. Thanks. Thank you, Martin. You'll find a link to jujitsu in the show notes. And I'd really recommend giving a trial. It's interesting to use.
01:10:27
Speaker
I'll say i think the hard part of learning it is with Git, you're used to making your changes and then adding them to a commit. With JJ, it's kind of backwards. You start the commit, add changes to it, and you're only really finished with that commit when you start the next one.
01:10:43
Speaker
And it's a small change of workflow, but it's a big change of ingrained habits and muscle memory. And the payoff doesn't really come until you try and do your first merge or your first rebase.
01:10:56
Speaker
So if you give JJ a try, and I think you should... Make sure you get past that initial weirdness and get to the good stuff before you really make a decision, because that's what you want to evaluate. Before you head off to the terminal and install it and give it a try, i have a quick request for the GUI.
01:11:12
Speaker
Please take a moment to like or rate this episode, maybe share it with a friend, and make sure you're subscribed, because we'll be back soon with another guest. Until then, I've been your host, Chris Jenkins. This has been Developer Voices with Martin von Zweigberg.
01:11:26
Speaker
Thanks for listening.