Matthias: This is Rust in Production, a podcast about companies who use Rust to shape
Matthias: the future of infrastructure.
Matthias: My name is Matthias Endler from
Matthias: corrode, and I welcome you to this very special episode of the podcast.
Matthias: I had the pleasure to travel to Berlin and meet with Scott Chacon and Kiril
Matthias: Videlov from GitButler.
Matthias: We talk about GitHub, Git Internals, and how the team at GitButler is refining
Matthias: Git branching with Rust.
Matthias: Scott, Kiril, thanks so much for having me and if you have a few minutes to
Matthias: introduce yourself that would be amazing.
Scott: Yeah, thanks for inviting us. So my name is Scott Chacon, I was one of the co-founders
Scott: of GitHub way back in the day, I'm very old,
Scott: and today Kiril and I and Anne have started a new company called Git Butler
Scott: and so we're spending all of our time on that which is partially written in
Scott: Rust which is I think why we're on the show. Yeah, that's me.
Kiril: All right. Thanks for having me on the show as well. My name is Kiril.
Kiril: I'm a software engineer, co-founder of GitButtler.
Kiril: I've been working with version control stuff for a number of years now.
Kiril: So I'm kind of really, really excited about what we're building at GitButtler.
Matthias: So a couple of weeks ago, I was at the We Are Developers conference,
Matthias: and this is where I met you guys.
Matthias: But in fact, I know one of you at least for a very, very long time,
Matthias: because, Scott, you wrote a book called ProGit.
Matthias: And yeah, you taught me Git back in the day. It's kind of crazy.
Matthias: And it was amazing. So I know that you are amazing when it comes to communication,
Matthias: when it comes to developer products. I guess you care a lot about developers.
Matthias: In general and what i
Matthias: find interesting about git butler is that i think it's an iteration on what
Matthias: you did before so it's maybe you can express it in your own words how would
Matthias: you describe git butler to someone who maybe is aware of github and git already.
Scott: Yeah i mean i think i think kind of the impetus
Scott: for this was was a product that Kiril had done
Scott: before which was called sturdy and it
Scott: was a different take on version control that that was kind
Scott: of asking questions like you know why is version control not
Scott: more like google docs you know where you're not committing
Scott: stuff but it is doing version control right like there's other ways
Scott: of doing version control than than how software developers do it and i
Scott: found that really compelling of just rethinking sort of the client i think i
Scott: think github did a relatively good job of making sort of how people are using
Scott: mailing lists type type things approachable but there was no we never really
Scott: owned the client right like when we never really tried to make the client experience better.
Scott: We just kind of relied on Git and all of the existing Git clients,
Scott: most of which wrapped the Git CLI and those commands.
Scott: And nobody really stepped back and said, if we did this from scratch,
Scott: how would we do this, right?
Scott: If the GitHub guys sort of created the client in the first place,
Scott: what might it look like today?
Scott: And I find that fascinating. So I think that's kind of where it started.
Scott: And, and it's, it's a, an interestingly difficult thing to do, right.
Scott: To, to kind of, to take, to go to first principles on something that you've
Scott: been using for a really long time.
Scott: Like it's been around for, I mean, like you said that I wrote ProGit the first
Scott: version of that in 2009, right. So that was 15 years ago.
Scott: And so there's, there's a whole generation of people that have never used anything other than git.
Scott: And so to take a step back and say, let's just throw everything away and figure
Scott: out what can we imagine would be an ideal workflow, like not sort of leaning
Scott: on anything that came before, what might that look like?
Scott: And that's exciting to me every day like it's always fun to work on it's always
Scott: fun to reimagine kind of review processes or,
Scott: how to share work or how to talk about work and how to get work integrated into
Scott: some sort of production mainstream you know line and so that's where it started
Scott: it's actually kind of funny because I feel like you mentioned ProGit like I think.
Scott: One of the reasons that I've been successful in these things that I'm doing
Scott: is that I'm not very smart so I think You know, if Linus or something creates
Scott: a CLI, you know, version control system,
Scott: it's really hard to use because he's very smart and he just assumes that everybody
Scott: else is going to take the time to learn it.
Scott: And I had I really struggled with it.
Scott: And so when I finally figured out kind of how to learn it and use it,
Scott: I started writing about it because I was like this took me way too long to do.
Scott: And so I want to do and it's kind of the same with the CLI, right?
Scott: It took me a really long time kind of to learn how to be good at Git.
Scott: And so I want to make something that makes it makes you be able to do the same
Scott: things where you're not worrying about that and spending your time and your
Scott: effort on on how do I rebase, you know,
Scott: stuff properly, but but to give
Scott: you the same tools, but make it much more approachable and much more easy.
Matthias: A while ago, you wrote a blog post that kind of became a phenomenon.
Matthias: It was on Hacker News. I saw it all around the web. It was titled Why GitHub Won.
Matthias: And in that article, you also compare Git with things that came before Git, like SVN.
Matthias: And sometimes it helps to learn from the past. Are there things out there that
Matthias: you got inspired by when starting Git Butler?
Matthias: Any new ideas that have not been integrated into any version control system right now?
Scott: Yeah, there's lots of stuff. I mean, there's lots of stuff in,
Scott: like I said, in Kiril's product Sturdy, where it would kind of be live streaming
Scott: the changes that you're doing.
Scott: I think one of the main things that we looked at was, I feel like the git commit is overloaded.
Scott: And so you use it to save your work. So people do work in progress commits, right?
Scott: When that's not really committing, it's not really documenting a change.
Scott: It's just saving your work, which I think is kind of stupid.
Scott: Like with Kiril's, you didn't have to do that because it was constantly saving
Scott: and it was constantly pushing in the background.
Scott: And Git Brothers has this timeline thing that kind of does a version of that
Scott: that I think is really nice.
Scott: It also, Git commit is used to share your change. You can't push anything over
Scott: the wire unless you commit it.
Scott: So people will also do commits just to be able to push it somewhere,
Scott: right? So one is saving, one is sharing.
Scott: And then the third is actually documenting, which is what people think it's
Scott: used for, right? But it's actually used for all of these other things and it's
Scott: kind of overloaded to do these things because it's the only way you can do them.
Scott: And I think being able to separate that in a client is one of the main important
Scott: things that we want to try to hit first, right, is we're backing up your stuff
Scott: whether you commit or not.
Scott: We're able to save and push that and share that with people,
Scott: whether you commit or not, right? Like even work in progress stuff,
Scott: you can get some review on, right?
Scott: And then you can use your commits to actually have a nice documentation of what you're doing.
Scott: And so, yeah, there's a lot of, I think, tools that came before, even like,
Scott: you know, I feel like we were trying to solve one very specific problem with
Scott: distributed version control systems, but we lost other strengths of centralized
Scott: version control systems. Like they're not all horrible, right?
Scott: Like being able to say, hey, I'm working on this file. Like we all got frustrated.
Scott: Those of us that are old enough to have used centralized version control systems.
Scott: Like you get frustrated that a file is locked and you can't edit it or you can't,
Scott: you know, if somebody locks it in per force or something, right?
Scott: Like it's very frustrating, but you know that they're working on that file.
Scott: And so, you know, or if it doesn't necessarily mean like we need to get to the
Scott: point where I can't edit it, but it would be nice to say, hey,
Scott: did you know that Kiril is working on that too, right?
Scott: Like you guys are probably going to have merge conflicts at some point.
Scott: You might want to look at that before it becomes too bad, right?
Scott: The way that people tend to do it with sort of GitHub-based workflows now is,
Scott: you know, you work on something, somebody else works on something.
Scott: Whoever merges first has 0% of the work and whoever merges second has 100% of
Scott: the merge conflict work, right?
Scott: And so like, I think there's a middle, there's some middle grounds in some of
Scott: these things where we can look at older systems and say, what were they actually
Scott: good at that Git and GitHub is not good at and, you know, what.
Scott: You know, what's interesting from Bitkeeper, what's interesting from from mailing
Scott: list patch workflows, right?
Scott: Like, there are there are interesting things that they did that they do better
Scott: than the workflows that we have today with sort of GitHub pull requests.
Scott: And I think trying to learn from that and pull that into how can we productize
Scott: that in a way that GitHub might have, right, like that makes it accessible and easy to use.
Scott: I think that's a something only a slightly stupid person can do because I you
Scott: know, you have to you have to get frustrated by it, right?
Kiril: I mean, one thing to add to your answer, like one thing that I think I did wrong
Kiril: in my previous project in version control was trying to reinvent everything, right?
Kiril: Like trying to reinvent version control entirely from scratch or like inventing
Kiril: the snapshotting entirely from zero.
Kiril: And that, well, that is very difficult. It turns out that Git is really,
Kiril: really good at that part. But it's also really difficult to have people adopt
Kiril: something that is not compatible with Git because Git is not just a tool.
Kiril: It's a format. It's a protocol. It's a protocol for distributing the software
Kiril: from your machine or from CI to a production environment.
Kiril: So I think that's a big one. So I think what's really interesting that we're
Kiril: doing at the moment is we are thinking about the workflow and we're thinking
Kiril: about the user interaction.
Kiril: But at the same time always producing compatible data structures like git data
Kiril: structures so at the end of the day what what the two outputs is is just git
Kiril: git trees that become branches and you can you can have that consumed by other
Kiril: tools that are in the ecosystem.
Matthias: I interacted with Git mostly from the command line. So I typed in my commands
Matthias: and then it would do something magically.
Matthias: But behind that, there's this .git folder, which a lot of people might know of.
Matthias: And there's an entire structure of objects and hashes and so on.
Matthias: Is that ill-specified or is it in effect really well-specified so that you can
Matthias: reimplement parts of it in Rust?
Scott: It depends on what you're trying to abuse, right? So like we're,
Scott: there's, there's a couple of, of libraries in Rust that are very good.
Scott: LibGit2 is, or Git2RS is built on LibGit2.
Scott: So it's, it's actually C, but it has the Rust bindings.
Scott: And we worked on that at GitHub, you know, years ago. And now Git Oxide,
Scott: and we, we work with Sebastian on, on trying to see which is sort of faster
Scott: implementations of these.
Scott: But, but the, the actual data structure in Git is relatively straightforward,
Scott: I think most from, you know, what we're trying to do.
Scott: The, but you know, we, we try to do some other stuff. We're learning some stuff
Scott: from jujutsu from some other systems.
Scott: And, you know, we want to inject things into the header and it took us a while
Scott: to figure out there's no like RFC on sort of, you know, git like formats or
Scott: protocols or anything. Right.
Scott: Even, even like some of the server protocols are still documented by me,
Scott: like just like learning it, but like, no, no, it's not written down in lots of places. Right.
Scott: And so it's, it's, you have to kind of guess what's
Scott: going to break because there's lots of different implementation there was no the
Scott: one of the problems with git is that there was no like standard linkable
Scott: library for for a very long time which is why libgit2 which is why it's called
Scott: libgit2 right because originally it was libgita libgit.a but it was non-reentrant
Scott: so just anytime you hit an error condition it would just exit and so you can't
Scott: link anything to it because it'll just kill you know a gui or whatever and so
Scott: they had this like unix philosophy of just shell out and run these commands and fork exec.
Scott: And, and, and so, yeah, now it's, it's difficult to know what did JGit do the
Scott: Java implementation, right?
Scott: Or what did libgit2 do, or what does core git do?
Scott: If it sees a null byte here, is it going to explode? If you add a header in
Scott: the wrong place, like which of these implementations is going to have a problem?
Scott: Will GitOxide, you know, it re-implemented a lot of this as well. Will it have a problem?
Scott: And so since they didn't have a linkable library, there was just five,
Scott: 15, you know, re-implementations of this that different people use.
Scott: And so we have to be a little careful of like, or try it out in lots of things.
Scott: If we're going to do something that's very non-standard, something that core
Scott: Git wouldn't do and be like, is this, I mean, I know it's not core Git,
Scott: but like, is it acceptable?
Scott: Like, well, everything else, ignore it so that we can, we can use it.
Scott: Right. I mean, so that's always, that's always kind of fun.
Matthias: Did those implementations diverge over time?
Scott: They've tried. I mean, diverge in that, in that, you know, nothing does everything
Scott: that libgit A does, right? Like that the core Git library does.
Scott: So even libgit 2 only does, you know, maybe 80% of stuff.
Scott: Like there's even you know stuff that was merged maybe
Scott: a year ago ref table stuff that that isn't that
Scott: it doesn't work at all right and libgit2 or and
Scott: gitoxide or in probably jgit even even though
Scott: sean came up with the spec 10 years ago but yeah it's it's so it depends on
Scott: what you're trying to do i think most of the core stuff is you know the old
Scott: pack files and loose objects and all that stuff is is very standardized sub
Scott: modules like once you start getting into things that the 10% of people use or 5% of people,
Scott: then, then it gets a little bit, a little bit more iffy.
Scott: A lot of the stuff in Git in the last, you know, eight years or so has been
Scott: done by GitHub and Microsoft and GitLab and stuff like that,
Scott: that are mostly server side anyways.
Scott: Like it's trying to scale large server sort of implementation.
Scott: So most of us don't run into it when we're doing it on client stuff.
Scott: And that's a lot of the stuff that isn't implemented everywhere because it's
Scott: just not worth it for most, most implementations.
Scott: But, but yeah, it's, it's definitely, it's not standard, right?
Scott: Like there's lots of different degrees of percentage of implementation from
Scott: these different libraries.
Matthias: It makes it pretty hard, or at least in my mind as an engineer,
Matthias: I wouldn't even know where to start.
Matthias: So I wonder, Kiril, when you started working on the predecessor of GitButler,
Matthias: Sturdy, how did you get started with that?
Matthias: And did you just literally pop up .git folder and then start implementing?
Kiril: The error in my initial approach was trying to implement a brand new incompatible
Kiril: implementation of a version control system. So that was not even attempting to be compatible.
Kiril: So I think I'm ill-equipped to answer this in a good way.
Kiril: We tried something that was – so we had a file system watcher that would observe
Kiril: what happened on disk and then pick those changes up and attempt to create a
Kiril: snapshot and attempt to record that snapshot and then do that continuously and
Kiril: then handle the various corner cases that you can encounter accordingly.
Kiril: And that particular bit is really, really hard.
Kiril: So it was not long until we kind of, at the time, gave up on this approach and
Kiril: kind of shifted towards using Git as an engine, as a database for what we're trying to do.
Matthias: And did you shell out to the command line to use Git?
Kiril: So for applications that are trying to do something with Git,
Kiril: there are a number of ways of trying to do it.
Kiril: One is shelling out fork exec to the Git binary, perform the command and pick
Kiril: up the output. And that kind of can be limiting, and it can also be slow if
Kiril: you do it in a kind of tight loop.
Kiril: So for a lot of things, we would use libgit, libgit2 rather,
Kiril: in order to actually bind a proper library that would interface with Git structures.
Kiril: And for GitButler, this is actually our approach that we take in GitButler is we use O3.
Kiril: We have so we
Kiril: have libgit through a rust crate so
Kiril: we're interfacing with libgit libgit2 rather and we
Kiril: do a lot of tree manipulation or
Kiril: you know modifying git data structures that way and then for certain operations
Kiril: like fetching and pushing it is difficult to do that with libgit because of
Kiril: you know differences in operating systems libgit2 has a its own transport for.
Kiril: SSH, you know, fetch and push. And that is difficult. So specifically for those
Kiril: operations, we fork exec.
Kiril: And now since recently, we have been playing around with GitOxide.
Kiril: And GitOxide is attempting to be, you know, a Git library, a Git compatible library.
Kiril: And that allows you to do the same things that you could do with LibGit2,
Kiril: but ideally in a faster way, ideally in a more flexible way.
Kiril: And it is faster. It is faster for a lot of use cases.
Scott: Yeah, it's interesting. In the early days of GitHub, this was one of the first
Scott: things that I worked on when I started at GitHub was we were fork-execing everything.
Scott: But like fork-exec has a pretty big overhead if you're doing it thousands of
Scott: times, right? And you're trying to do it in one web request or something like that.
Scott: And so I would go in and look at what was the slowest and try to reimplement
Scott: those things in Ruby, like just in pure Ruby, because that's what we were using
Scott: on the back end. And we're kind of doing the same thing, right?
Scott: It's like, if we can take a fork exec overhead, it's almost always faster and
Scott: definitely compliant, right?
Scott: If we can do it in libgit2, then there's a nice interface for that in Rust,
Scott: right? And it runs in C and it's fairly cross-platform.
Scott: And then if we can do it as fast as possible, like if we can do it in git oxide,
Scott: then it's nice because it's purely in Rust, right?
Scott: And so like now it's not even doing the C bindings or anything.
Scott: And so, yeah, I mean, it's fun.
Scott: It makes for a really interesting code base.
Kiril: I have not shared this with you, Scott, yet.
Scott: Oh, no.
Kiril: So recently we migrated the way we fetched the branches, the branches data,
Kiril: or listing just branches in a repository.
Kiril: We're now using GitOxite for that. And it appears that at the minute we have
Kiril: the fastest client at fetching all branches.
Kiril: So the test repository had 20,000 branches, which I think is a ludicrous amount of branches.
Kiril: I don't know who needs that many. But in that scenario, our app is currently
Kiril: faster than the CLI in answering the question, what are my 20,000 branches?
Matthias: How do you measure that? Do you have some sort of benchmarking tool for this? Or how do you do that?
Kiril: A very primitive timestamp-based approach.
Matthias: And you get some granularity by having a lot of branches and working with big repository, I guess.
Kiril: So the particular repository is the GitLab repo. And that one has a lot of branches. I don't know why.
Kiril: And just listing them, all of them in the CLI is...
Kiril: A little bit slow and we do it faster.
Matthias: Maybe it sounds almost tautological but at some point you needed to decide what
Matthias: language to use to write git butler in and of course you could have picked c
Matthias: but you could have picked any other language but you chose Rust to do so so.
Kiril: For our use case i think it's not necessarily the language characteristics that
Kiril: were a driving driving force, but rather the ecosystem or the libraries and
Kiril: the tools that are available.
Kiril: In particular, in terms of what we're trying to achieve with the application,
Kiril: so we're building something that manipulates Git data structures on your computer.
Kiril: So we need to be able to interface with Git and with the file system in a good way.
Kiril: We need to be able to create custom user interfaces. We need to have that set
Kiril: up in a secure way, in a performant way.
Kiril: We need to be able to cross-compile for different platforms.
Kiril: And it just so happens that on that point of being able to create custom interfaces,
Kiril: there is this toolkit called Tauri.
Kiril: So Tauri is a framework or a toolkit that allows you to create desktop apps and
Kiril: use web technologies for the user interface.
Kiril: In a way, it's similar to Electron, but what's different from Electron is they
Kiril: use the native operating system
Kiril: WebView, so they don't need to package the Chromium with the binary.
Kiril: And also, they have a very strict and specific way of communicating between
Kiril: the user interface code and the core of the application with the positive impact
Kiril: for security. right now so yeah.
Scott: No i was gonna say i i just from a i
Scott: i was trying to remember us talking about this like when
Scott: we first approached it because we did his so sturdy
Scott: was was an electron app right right right so he had some electron experience
Scott: i obviously you know i came from from github so we did Atom and extracted electron
Scott: out of it and so i i've i even wrote some documentation for electron or for
Scott: Atom actually back in back in the day and so i was familiar with that but like
Scott: when we were looking at how do we build the desktop app,
Scott: that is interesting, right? I think those are really the only two options that
Scott: came up that are, that could, you know, we could easily put it out on all the
Scott: platforms that we wanted to.
Scott: It worked more or less the same. We could do the user interface in HTML and JavaScript.
Scott: And then really the question was the difference of the backend.
Scott: Is it going to be a node or is it going to be in Rust?
Kiril: And there was a node backend for a couple of days.
Scott: Yeah, I mean, I mean, the, you know, when it comes down to it,
Scott: I hate JavaScript, but I don't think that's actually what the deciding factor was.
Scott: I think the deciding factor was, was A, we assumed that it would probably be
Scott: faster and B, we want to do a CLI, I think, version of it at some point.
Scott: And so it was kind of a nice concept to me, at least, that we could have the
Scott: one user interface be in HTML and JavaScript, the backend, sort of the core
Scott: crates and stuff be entirely in Rust, purely in Rust with nice APIs.
Scott: And then we could write a CLI interface or TUI interface or something that would
Scott: have all of the important stuff already done, right? And it would kind of work the same everywhere.
Scott: And CLIs and Rust are much nicer to distribute than CLIs in Node, right?
Scott: And so all of those things, I think, were kind of what tipped us over.
Scott: I mean, it is nicer that it has smaller binaries because of using the operating
Scott: system's sort of default web view, but it also causes some issues because we
Scott: don't control it, right?
Scott: And so there are problems with you know, some Linux distro using some ridiculous,
Scott: you know, web view that we have to debug and be like, why isn't it working on this thing?
Scott: Right. So I think, I feel like that's, that's pluses and minuses,
Scott: but the, the, the, the idea of Rust being sort of the core library that we can
Scott: throw whatever user interface on to do the things that we're, we're, you know,
Scott: hopefully is battle tested and good at and not have to rewrite it in Swift and
Scott: rewrite it, you know, do it, do it in a bunch of different languages or something per platform.
Scott: Like all of those, I think made it fairly clear that Tauri would be a good idea.
Matthias: It's surprising because I don't hear that a lot, that people come to Rust also
Matthias: because of the nice UI libraries.
Matthias: And it feels like that was at least some factor. I don't know if Rust would
Matthias: have been a non-starter, if Tauri didn't exist. I don't think so.
Matthias: Maybe you would have split it up and maybe kept the back end written in Rust
Matthias: and the front end written in something else.
Kiril: It was certainly the gateway drug, right? We never.
Scott: I don't think we ever would have chosen Rust.
Kiril: Nobody on the team had Rust experience. So we started working on this with zero Rust background.
Scott: Yeah. It was a struggle for me.
Scott: I've done systems programming in such a long time. Like I'm a Ruby guy,
Scott: right? And like I'm coming in, I'm like, why can't I just fucking...
Kiril: I've seen the light. I think it's fantastic.
Scott: I used ChatGPT a lot in the first days.
Scott: And then I sat down and read the Rust book, thank God.
Scott: Helped a lot that was the first time i'd even thought about the stack in the
Scott: heap and like like since i was from college it was it's been such a long time we.
Matthias: Had Steve Klabnik on the podcast just a couple episodes ago so shout out to him.
Scott: Yeah he was he's in the jj discord and and we we sort of said hi to each other
Scott: there not not too long ago as well he's he actually wrote like speaking of other
Scott: version control systems if you've done something on jujutsu yet,
Scott: But Steve wrote like the tutorial book for that.
Scott: So if you do want to learn Jujutsu, you have to kind of find his tutorial
Scott: book that's online somewhere and read through that because it's a great sort of intro to that system.
Matthias: Yeah, he also mentioned that on the podcast. So yeah, definitely if you want,
Matthias: you should definitely check it out.
Scott: I've only sent one patch via Jujutsu, like one actual thing.
Scott: And it was to correct some stuff in that tutorial book. So I'm also a co-author.
Scott: I'm kidding. There's like, it's like a change of two lines or something.
Scott: But I used that to learn how to use that system, actually. It was pretty cool. Thanks, Steve.
Matthias: Kiril, you had some previous Rust experience before? No, no.
Kiril: None of us. Nobody in the team had any Rust experience.
Matthias: Oh, wow. Okay. And how long did it take the both of you to pick up the language?
Matthias: It's not a competition. I'm just curious. Is it days, weeks, months, years?
Kiril: There are really different levels of competence. Like you can get started with
Kiril: messing things up very quickly, right?
Kiril: But to be truly productive and to truly know what you're doing,
Kiril: maybe like a month or something.
Matthias: What's your background?
Kiril: I mean, I'm a software engineer. So I've done a number of languages.
Kiril: I have enjoyed Go, I've done a bunch of Java, I've done some C.
Kiril: I had a phase of really being into Clojure. Like I really, really liked the
Kiril: Lisp style of programming.
Matthias: But essentially you have a different background than Scott.
Scott: I mean, you're much, he's much more hardcore programmer than I am.
Kiril: I mean, computers are cool.
Scott: I've, I've just done, I'm very, I'm a very practical programmer.
Scott: Like I, I like whatever gets the job done easiest.
Scott: And so that's usually been Ruby for me because I usually do websites.
Scott: And so I, I, before that it was PHP, but I've been doing Ruby for,
Scott: for 20 years now, at least.
Scott: And I'm very comfortable with it. And anytime I try to do something,
Scott: it usually comes down to that.
Scott: Unless if I'm trying to do mobile apps, I'll do like react native or something
Scott: because, you know, exposed like a nice, I'll just do, I'll do whatever's easiest
Scott: to see if an idea works, I think.
Scott: And so for, for Rust, I kind of still learned the minimal amount to get something
Scott: to work. Like I'll still, I'll throw a patch in every once in a while.
Scott: And then, you know, somebody will come in and be like, Jesus,
Scott: Scott, and you know, make it, they'll fix it, but like, I'll get it to work
Scott: and make sure that it's even a good idea.
Scott: Right. And so that's, that's, you know, I'm old enough now that I don't have
Scott: to, I don't have to learn new things. but.
Matthias: If you can maybe remember one of the things that you learned from rust which
Matthias: turned out to be surprisingly good what would it be.
Scott: I mean i like yeah again
Scott: i from the ruby world it's it's it couldn't be a more
Scott: different language right and so i i do like the the compiler stuff like like
Scott: it's it is nice to be like if it compile like you know most of it is dealing
Scott: with compiler issues rather than runtime issues so so if it compiles and it
Scott: actually runs something then it probably runs the way that I meant it to.
Scott: Whereas in Ruby, you don't know until it runs into an issue and there's no good
Scott: debugger and things like that in the same world.
Scott: But like, it's very different doing systems programming and doing sort of Ruby,
Scott: you know, almost scripting type programming, right?
Kiril: The error messages are so good. So good from the compiler. I think I'm still impressed.
Kiril: You know, like just having the compiler tell you, all right,
Kiril: you move this over here on this line, this part, this is super useful.
Kiril: I think you don't get this in C++ to my knowledge.
Matthias: So that's also ergonomics.
Kiril: Exactly. The getting started experience for me was fairly pleasant.
Kiril: There is some mountains to climb, but it's obvious that there is some thought
Kiril: put into getting people up to speed with Rust.
Scott: I've also found that there's not a lot of boilerplate. like
Scott: like i feel like if when i write you know like i
Scott: don't know c c code i have to do a bunch of header files that kind of
Scott: you know redeclares the same stuff like you're not you're not doing a lot of
Scott: or java java has a lot of that right like just random bullshit that you're that
Scott: you're typing out because you have to not because it actually tells the compiler
Scott: something that's valuable right or or new like i i feel like rust is relatively
Scott: fast to write in i i don't always,
Scott: have the entire memory model.
Scott: Like I suck at lifetimes and things like that. And so I tend not to deal with
Scott: them as little as possible until somebody's like, this is not how you do this.
Scott: But I feel like it's still a fairly succinct language for a systems language, right?
Scott: I was kind of constantly impressed by that.
Kiril: It was one thing that I found very difficult while getting started,
Kiril: which is the approach challenge for error handling or the way you want to structure
Kiril: your application error-wise.
Kiril: Now, I understand that there is the anyhow camp, and then there is the camp
Kiril: of using typed errors and just finding the balance or understanding which way one would use for,
Kiril: let's say, building a library versus building an application like ours, the trade-offs.
Kiril: Yeah, it is more challenging for... I think there's no right answer,
Kiril: right? And therefore, the ecosystem has not standardized on one thing. Yeah.
Matthias: Any tips on how to navigate that ecosystem?
Kiril: Well, I think understand what you're trying to achieve with errors. I think if you...
Kiril: I'm now repeating, I think, advice that I've read.
Kiril: But if you are creating a library, you have one set of...
Kiril: You're trying to set the expectations that other people have.
Kiril: In our case, we are building an application and creating.
Kiril: It so happens that for us creating types for all the different subsystems and
Kiril: functionalities in our application does not necessarily add the value to warrant
Kiril: the additional type creation and type conversion.
Kiril: So that was creating a boilerplate for us. And we've recognized that,
Kiril: okay, we care about what,
Kiril: So our application works on like an API. So you have commands that git processed
Kiril: and we do care what happened.
Kiril: We do care if there is an error at the end such that we can present it in a
Kiril: meaningful way to the user.
Kiril: But we seldomly have the application flow switch on the error types.
Kiril: And for that reason, because we have this user interface that is interacting
Kiril: with a core of Git Butler,
Kiril: we're using Anyhow, we're using Anyhow, and we're adding context to errors where appropriate,
Kiril: and we're adding error codes as context in such a way that that gets passed
Kiril: on to the front end, and then the front end knows what to do with the error codes.
Scott: It was pretty funny having a team coming in that all had sort of different,
Scott: like we all read books and we all copied from different code,
Scott: and so we had three different ways of doing error reporting,
Scott: like throughout the, throughout the application. Right.
Scott: And then kind of had to go and clean all, had to choose one,
Scott: right. Like figure out like what, what would be a good way?
Scott: Is it anyhow, like, is it typed or like how, like, what do we choose?
Scott: And now can we go through and make everything the same? Right.
Scott: And it was like waves of, I mean, Kiril did a lot of this, right.
Scott: Like going through and changing all of the error sort of handling stuff to try
Scott: to be somewhat consistent.
Scott: Right. But like, this is another thing of having a bunch of people start not
Scott: knowing, like not really having a lot of previous background in this and just
Scott: doing whatever seemed right.
Scott: And not knowing, like nobody really had any particular taste at the beginning,
Scott: but it's definitely gotten better as the longer that we've worked with it.
Kiril: Yeah, I think that error handling and also structuring an application that is growing and evolving.
Kiril: It's a non-obvious thing. How do you structure it? Do you have one crate or
Kiril: do you have multiple crates?
Scott: Yeah, we went from like one crate to 50 crates, and now we're like at 20 crates or something.
Kiril: Actually, it's 31.
Matthias: How do you strike the balance there? So when to crate, crate, and when not to?
Kiril: So we we started off from a place of having
Kiril: very few and we had code
Kiril: depending on other code that should not have so
Kiril: i think when it
Kiril: comes to software in general i think a lot about this idea
Kiril: of optimizing for deletion what does
Kiril: it mean to optimize for deletion it means to be able to say
Kiril: okay i don't like this feature i want to just delete it and if that
Kiril: feature is intertwined in 20 different places it's hard
Kiril: to delete but what i just said is just
Kiril: a fancy way of saying make modular software right it's
Kiril: it's not a new concept and so we
Kiril: recognized that this this was an issue for us we were adding things and old
Kiril: things were difficult to clean up so at some point we we just bit the bullet
Kiril: and and started splitting things off now i had i come from a background of using
Kiril: build systems like Bazel.
Kiril: And there you are really encouraged to make build targets or compilation targets
Kiril: that are small, kind of modular.
Kiril: And this also forces the dependency graph to be unidirectional and very explicit.
Kiril: And I think this explicitness.
Kiril: It forces you to think about the boundaries, forces you to consider,
Kiril: okay, do I want this to depend on these other things?
Kiril: Or you recognize that, oh, there's going to be a cycle here.
Kiril: It's impossible for me to make it a separate crate. Why is that?
Kiril: Maybe that should belong to this other functionality.
Kiril: So we mostly take package by feature approach or crate by feature.
Kiril: Or we strive to put different aspects of the client in separate crates.
Matthias: That means if I delete a crate, then I make a couple modifications and it mostly just works again.
Kiril: This is the cool thing about Rust. We've made such dramatic changes to the structure
Kiril: of not just where the code lives, but the interfaces and such.
Kiril: And it all just works because you have a statically typed language with a compiler that helps.
Kiril: So if you can get it to compile, it will work. That's the beauty of the setup that we've got.
Scott: Yeah, I doubled down on that as well. Like you were asking what I liked about
Scott: Rust and refactoring stuff is so nice in Rust compared to Ruby or any other
Scott: language that I've done because you change the one thing to be kind of what
Scott: do you want this call to look like now?
Scott: And then it's like, here's the 47 other places that you're going to have a problem
Scott: with. And you're like, I'll just start going through the list, right?
Scott: Like it's, it's, if, you know, if you don't have some tool kind of helping you
Scott: do this type of stuff, it's very clear that you've done your job or not. Right.
Scott: And like 99% of the time you fix all those things and then you run it and it's
Scott: like, yep, everything works. That's great.
Scott: I've never, that's not in my, my, you know, history of working with software
Scott: before. So it's, it's very nice.
Kiril: There is one thing on this subject matter that I've been thinking about,
Kiril: and I don't know the exact answer that is good.
Kiril: So now that we have our code base relatively modular, we have 31 crates.
Kiril: Well, some crates have modules, and in some cases we export the entire modules.
Kiril: And it is more difficult to discover
Kiril: what the API of a crate is when you
Kiril: have like a more nested or like more
Kiril: hierarchical surface area that is
Kiril: exported and I've recently been
Kiril: toying around with this idea of putting the or
Kiril: exporting the functions that are from inner modules of a crate just putting
Kiril: them in the root for easier discoverability and making it more obvious what
Kiril: the API is and what one can do with something. I do not know if that's a good idea.
Kiril: I would love to hear from somebody. Do you know if this is a good idea?
Matthias: So there is a blog post by Matt Clad, the creator of Rust Analyzer,
Matthias: and he describes that he likes to keep his hierarchy extremely flat,
Matthias: mostly for pragmatic reasons because he has a hard time coming up with names for things.
Matthias: And then if you put things into the wrong directory or into the wrong crate
Matthias: and sub-crate and module and whatever, then it becomes harder to move that out again.
Matthias: So it tries to keep it as flat as possible.
Matthias: So it goes along the lines of what you just described.
Kiril: So not totally wrong.
Matthias: It's a bit like Git branching. You can have branches upon branches,
Matthias: but at some point I do like to keep my hierarchy flat at least because I need
Matthias: to keep track of it in the end.
Matthias: Do you use something like preludes or a glob import?
Kiril: We avoid that. I don't think we do that anywhere.
Matthias: Yeah. I agree because I literally also wrote a blog post about it that maybe
Matthias: you shouldn't have a glob import or a preload for that.
Matthias: Does it mean you have something like an application and then on top of it you
Matthias: have a couple of library craze that technically you could use for any other reason?
Matthias: For example, interacting with Git itself.
Kiril: Well so we we have 31 crates
Kiril: and most of the if you if you just read what the
Kiril: titles are they're like different features from from the app and
Kiril: one of those crates is the to gitbutler-tauri that is the binary crate that
Kiril: bootstraps everything so we mentioned earlier that we yeah we're using Tauri
Kiril: but we are not really the core of the app is not necessarily dependent on There
Kiril: is one crate that combines the APIs,
Kiril: sets everything up, and exposes.
Kiril: But then we also have a CLI, a GitButler-CLI crate, which is mostly useful testing.
Kiril: But we have multiple binaries.
Kiril: So nothing in there is necessarily library-grade to be used or to be consumed
Kiril: by another application necessarily.
Kiril: But we have multiple things that can be built and composed. we can just as easily
Kiril: create a web server if that's what we needed to do out of the API.
Matthias: Nowadays, there's also Leptos and Dioxus and a couple of other UI libraries like Slint.
Matthias: Are you still content and happy with Tauri or did you run into any issues so far?
Scott: Well, I mean, the user interface is Svelte, right?
Scott: So it's basically just, here's a WebKit thing. It gives us a way to invoke calls to Rust.
Scott: And so I think we're relatively happy with that because, you know,
Scott: we have a bunch of JavaScript,
Scott: programmers who are good at, I mean, we like CSS, we like, you know,
Scott: we like, we like being able to, to build user interface with the tooling that
Scott: we know from, from web, from building on the web.
Scott: And, and Svelte gives us a lot of stuff that I think it would be difficult to go.
Scott: I, I, I find it would be really difficult, I think, for what we're trying to
Scott: do, which is, which is very doable in, in HTML and JavaScript to,
Scott: to go down like the, the Zed route, right.
Scott: Of, of being like, let's, let's do a completely new sort of user interface stuff.
Scott: Cause that's now you're, you're reinventing all the wheels and it can be much
Scott: faster, right. Or it can be, it can be great for what you're trying to do.
Scott: But, but right now I think we're not a hundred percent sure of exactly where we want to land.
Scott: And it would be, it's easier to kind of use the wheels that are there to,
Scott: to get us real close to that before we go down some, some larger,
Scott: road that's that difficult.
Kiril: Zed builds their own UI library, GPU accelerated and everything,
Kiril: and it's fascinating, but it would be so much more difficult to iterate and
Kiril: try things with such an approach.
Matthias: We had them on the show. So if you want to check it out, listen to the episode
Matthias: we've said where they described that UI approach.
Matthias: I think it's nice to compare those two approaches because I looked at GitButler
Matthias: and what I found was it looks nice.
Matthias: It's clean, it's snappy, it almost feels native.
Matthias: And I don't know how you'd pull it off, but definitely you did a great job there.
Scott: Yeah, I mean, it's an interesting question, right?
Scott: Like going back to what do we want
Scott: to build? Like we are still very much experimenting with stuff, right?
Scott: Like we, we, we, we're, all we know is we want to throw everything off the table
Scott: and then figure out, you know, what do we want to be on the table a year from now?
Scott: And we're still constantly kind of arguing about stuff and, and we try stuff
Scott: out and we see what works and we use it ourselves and we dog food it.
Scott: And we're like, okay, this feels good.
Scott: This needs to be changed. This is going in the right direction.
Scott: Let's rethink this, blah, blah, blah.
Scott: I think with the Zed guys, you know, I mean, I've known Nathan for,
Scott: for since GitHub days. So, but like, I feel like they knew what they wanted
Scott: to build, right? They want to build an editor.
Scott: Like they know what editors look like. They know what, you know,
Scott: VS Code looks like. They know what Atom, he worked on Atom before that.
Scott: And so he had a good idea of like, really, where do we want this to go down?
Scott: They had a lot of taste and they knew where they wanted to go.
Scott: And so I think they could be, it was much, it made more sense to say,
Scott: here's what we need a UI library to do because we want to do kind of this, but much faster.
Scott: Right. And, and so that, that makes it, whereas we, we haven't,
Scott: I feel like we have no idea where we're going to land, you know,
Scott: two years from now, what this is really going to look like and how it's going to feel.
Scott: We just, we know that we're getting closer to what makes us happy,
Scott: sort of doing, doing these, these code management things every day.
Scott: And, and so, yeah, it really depends on what you're trying to build.
Scott: Like, do you really know what it's going to be and, and making it faster or
Scott: doing it a rust or, you know, whatever will definitely help you get there.
Scott: Or are you inventing and if you're inventing then then it's much easier to have a general toolkit.
Matthias: And is it the same experience when you move things
Matthias: around on the front end side in the ui do
Matthias: you have the same feeling like when you do something in the rust core
Matthias: where refactoring is easy and the language helps you move things around and
Matthias: you can make changes with confidence or do you have this i would say chasm from
Matthias: the front end to the back end a typical thing where you change something and
Matthias: then you throw things over the fence yeah.
Scott: I mean that's really a question of like what's easier or harder than that like
Scott: javascript or or rust like i prefer to do stuff in rust because because i feel
Scott: more confident that i'm not screwing something up than i do in typescript but
Scott: yeah you work more in both of those than i do i.
Kiril: Work in both but my preference would be yeah refactoring the back end we have
Kiril: the api or in in the Tauri language we have those commands that are,
Kiril: the kind of the thing that needs to be stable or when we change it,
Kiril: we change it consciously.
Kiril: But yeah, change to me, change in Rust is much, much easier.
Matthias: The other thing I noticed when I played around with Git Butler was that certain
Matthias: operations were snappy, even though they were, I guess, in the background, quite complex.
Matthias: And I wonder how you pulled this off. Do you have a lot of async Rust code in the core?
Matthias: Or how do you handle that part? Because is Tauri essentially async as well?
Kiril: So, yeah, it's specific. So if you look at our functions, the whole chain,
Kiril: the whole stack, there's no async mentioned.
Kiril: However, on the top level where we define the Tauri command, there is a macro
Kiril: where we annotate it or we declare it as an async function.
Kiril: So my understanding of the framework is that it will certainly run this in its
Kiril: own thread, the entire command.
Kiril: But within that scope, it is all synchronous functions. And this is actually,
Kiril: at some point, we did have async functions in those calls.
Kiril: And as you may know, mixing sync and async code is very, very, or can be painful.
Kiril: There is a constraint for our use case where certain structures that come from
Kiril: git2 or the libgit2 bindings in Rust, Because there is this C operation,
Kiril: those structures are not sent sync.
Kiril: And because of that, yeah, they need to be in this sync context.
Kiril: And that made it quite difficult to do certain things. We had to do a spawn
Kiril: thread manual and do certain things.
Kiril: So I think we are in a much better place now that everything within an API code
Kiril: or within a command is sync.
Matthias: Yeah. I personally also believe that the core of an application should be sync
Matthias: ideally because then you can use it in other contexts. As you say,
Matthias: mixing sync and async is not easy.
Matthias: And if you have a library that cannot use async, then you're kind of bound to
Matthias: building a weird bridge between the two.
Matthias: For example, you could technically run that thing on an embedded system,
Matthias: which maybe is not fit to run async code.
Matthias: It could be with embassy, but it's not necessarily the case.
Matthias: So keeping that separate I think was a good decision and this is how you keep
Matthias: the UI snappy too because at
Matthias: the end of the day this macro that you described is that a part of Tauri?
Matthias: Is that something that is built into the yes.
Kiril: This is a Tauri.
Matthias: Macro okay and they dispatch it in the back and then it comes back with the result this.
Kiril: Is my understanding that they do the dispatching themselves.
Matthias: So all the git operations they complete at some point and then you update the user interface.
Kiril: So if you look at our API, we have commands, which are things that you trigger,
Kiril: and we have subscriptions or one subscription.
Kiril: Which is for for the state of of of the workspace so there is things that happen
Kiril: let's say on the file system or things that you've triggered in the user interface
Kiril: and doesn't matter on which thread that happened or it's just things that can happen,
Kiril: that is that is being propagated to the interface through through um yeah a subscription almost.
Matthias: Like an event system.
Kiril: Yeah i think from the java so we we use the we use the the tooling uh by by
Kiril: Tauri and to me that looks very much like a web socket subscription on the javascript side and yeah,
Kiril: on the rust side we have a uh how
Kiril: to say like a file system watching that that is observing the file system if
Kiril: something occurs it gets picked up it gets processed and then then you know
Kiril: we have a channel in which uh that that change is propagated and then ends up
Kiril: in the user user interface or in the javascript code.
Matthias: So that's a nice separation of concerns.
Kiril: Right so there's no need to do polling for example in the front end.
Matthias: How many people write rust at git butler.
Kiril: You count me probably not i Actually.
Scott: Give me a 0.5.
Kiril: Well, if we can't you. Okay, so we actually, I want everybody to be writing Rust.
Kiril: So we encourage everybody to, including folks that have, I have to say,
Kiril: primarily front-end JavaScript background.
Kiril: We encourage everybody to get their hands dirty or rusty.
Scott: Let's say.
Scott: You're waiting the whole episode for that one.
Kiril: We should do the joke part. No, so we encourage everybody to get into this because
Kiril: A, everybody's asking for it. Like it's interesting.
Kiril: It's interesting to try to expand one's horizon.
Kiril: And B, actually it makes sense to work full stack.
Kiril: With that said, the people who work regularly in the Rust side of the code is
Kiril: probably three, four people out of say seven.
Scott: Yeah, engineering-wise, yeah.
Matthias: How does the onboarding work when you tell someone to write some Rust code?
Matthias: Do you just throw them into the cold water? Do you have them go through the
Matthias: Rust book or some tutorial?
Matthias: Or do you sit with them for a while?
Kiril: They just jump straight into it. I think this is what we did.
Kiril: I mean, there is a pattern that one can follow, right? You can see how,
Kiril: just let's imagine any front-end developer that has never touched Rust.
Kiril: So the part where the front-end or the JavaScript code talks to the Tauri part, that's obvious.
Kiril: You can see how other commands or requests work. So you can copy-paste that.
Kiril: And then you can see, you can search for the string in the code base.
Kiril: And you can see, oh, this is where we declare those.
Kiril: Okay, this is the name of the thing. I can see what we're doing.
Kiril: And you can just, you know, copy paste yourself into something.
Scott: That's how I do it.
Kiril: That's how we all do it, you know. And then hopefully you're following a good pattern.
Kiril: And, you know, you should be brave. You should try things.
Kiril: I think this is what makes us also happy as developers, you know,
Kiril: just trying things and seeing what works and what doesn't.
Matthias: And still, I also do the same. I'm with you on this one.
Matthias: Still, sometimes I wish for some coding guidelines when I start with a new project
Matthias: or start with a new company.
Matthias: I'd like to be a good citizen of the code base.
Kiril: Right?
Matthias: Do you have something like that? Any internal guidelines?
Kiril: So we use Clippy. So we have rules. We also, I mean, the way I do it for me
Kiril: is I look at other projects.
Kiril: I look at how other projects structure their application logic and how they
Kiril: approach abstracting things, to what extent they use traits and how they use
Kiril: traits, how they, I mean,
Kiril: you know, extension traits for certain things, but not for certain other things,
Kiril: or just multiple implementation blocks, just getting into the dramatic rust process.
Kiril: I sometimes would write some code and I would reach out to somebody more experienced
Kiril: on the team and be like, is this idiomatic?
Kiril: Is this how you do it? And then I would learn that you can actually express
Kiril: it in a more beautiful way or in a more succinct way.
Kiril: One phrase that I've heard within the Rust ecosystem score is this idea or this
Kiril: sentence of make invalid state unrepresentable.
Kiril: So you can express the states of your application or of that particular piece
Kiril: of logic in a way that you can't have the wrong state using the some types,
Kiril: enums and such.
Kiril: Which is really cool to think about just your programming as putting a puzzle
Kiril: together and just creating a structure that ultimately represents the kind of
Kiril: your application truth or the thing that it's supposed to do and it's not supposed
Kiril: to do, like thinking in terms of invariance.
Matthias: I come from Python, and it's a bit similar to Ruby in a sense that sometimes
Matthias: I had a larger change and I would run the project for maybe 20 or 30 minutes or so.
Matthias: And then it would crash, crash way down in the stack with some silly mistake
Matthias: that I made because the type system wasn't saving me. It wasn't a compiled language.
Matthias: And I think at GitHub, you had some sort of code style guide.
Matthias: You had something like that. I guess there was something.
Matthias: I can remember you wrote a bit about it on the blog, on a GitHub blog,
Matthias: and at least the code itself was written by expert Ruby programmers.
Matthias: Some of that do you miss it in rust sometimes where there are not that those
Matthias: clean guidelines for example when to write functional code when to write object-oriented
Matthias: code and and stuff like that.
Scott: I don't i mean i don't miss it like i like i said i'm fairly practical i i i
Scott: do there's a lot more now i think especially than in the ruby world there's
Scott: a lot of stuff like clippy and prettier and, and with like, there's, there's,
Scott: you know, I save the file in VS code and it, it fixes sort of idiomatically,
Scott: you know, what, like, like what everything kind of should look like from a formatting
Scott: perspective or tells me when I'm doing something wrong in JavaScript or something.
Scott: So, you know, I have, I have at least a little bit of a hint beforehand that
Scott: I'm, that I'm formatting something wrong or, or that it's, it's going to look
Scott: wrong or something like there's no, there's no spaces tab sort of like arguments
Scott: and, you know, anymore, right?
Scott: Like, like, I think the whole industry has kind of moved on from that.
Scott: But from a – man, I don't know. It's like from this type of thing, I think –.
Scott: I've been around enough of these where it changes over time.
Scott: And I've seen a lot of this in the Ruby community as well, right?
Scott: Where people are saying, here's how you should, you know, do you have,
Scott: you know, fat model, skinny controllers or blah, blah, blah.
Scott: And they'll come up with something and then everybody will try to do that.
Scott: And then five years later, it'll kind of change a little bit.
Scott: And then you'll like refactor code and the new kids will come in and be like,
Scott: this is all bullshit, right?
Scott: And so like, like, I think as long as the code works and customers are happy,
Scott: like they're not looking at your code, right? Like a lot of it is going to be
Scott: what does the next person that comes on, can they understand your code?
Scott: Can they contribute to your code?
Scott: I don't like clever code, right?
Scott: Like I like dumb code that is easy to understand and easy to modify.
Scott: And so I always kind of go away from super clever stuff because even though
Scott: it makes you feel smart, it may not.
Scott: And that's why it makes you feel smart is because somebody else has a harder
Scott: time understanding it or figuring it out. Like I don't like magic.
Scott: Anyways, yeah, I don't know. I
Scott: would move towards as simple and as understandable as it possibly can be.
Scott: But you have to make the next person that comes on feel like they can own the code too, right?
Kiril: And to your point, if you optimize for deletion, if you optimize for making
Kiril: the code base modular, you can always take bits out, replace,
Kiril: reimplement, and swap parts out.
Kiril: I think that's what makes it easier to move faster because that's one of the
Kiril: things that are really important for us, to be able to iterate on our ideas.
Kiril: As Scott said, we have no idea what we're doing.
Scott: That may not be the message that we want to put across. We're slowly getting
Scott: a better idea of what we're doing.
Kiril: I mean, this is tongue-in-cheek, but we iterate, we get feedback,
Kiril: and we always need to incorporate those learnings.
Kiril: And sometimes our approach for a particular solution is not ideal.
Kiril: So we take it out or we want to be able to take it out and replace it with something better. Yeah.
Matthias: How much of the code base is functional and how much is object-oriented?
Kiril: Well, object-oriented, I don't think we necessarily have any object-oriented.
Kiril: I mean, not everything is purely functional. We would have mute, if that's what you mean.
Kiril: We would have things that we mutate. But in terms of state, you start up GitButler
Kiril: as an application, and there is very little to no state that the application holds,
Kiril: when you get a command or a request, something happens and now there is more state.
Kiril: But that state goes out of scope when that command is over or has been completed.
Kiril: The only kind of state that is, the ultimate piece of state is,
Kiril: okay, which repository are we working on? Like which is the repository?
Kiril: And that's just the path. So a path is the core piece of state.
Kiril: And then, because if you consider that our application is dealing with, well, Git structures,
Kiril: files on disk and the Git state, which the source of truth is on disk,
Kiril: not in our application's memory while it's running.
Kiril: And for that reason, after each operation, there is no more state that is relevant.
Kiril: We completed the operation, we return, and that's that. Which is, I think, beautiful.
Kiril: It's nice to not have to maintain controllers that...
Matthias: That means you don't have any
Matthias: long-running mutexes, any synchronization that you need to take care of.
Kiril: Correct.
Matthias: Mostly depend on the file system, and then you do your next operation.
Kiril: Correct. So we initially had those simply because of our background,
Kiril: and we assumed that we did need that.
Kiril: And then through some help and guidance, we've come to understand that we don't
Kiril: need it, and we've been able to take it out.
Kiril: And by taking it out a lot of things have become simpler things that used to
Kiril: get a control project controller or a user controller now get nothing the only
Kiril: thing that you need to know is okay what which which path am i dealing with
Kiril: and then everything can be derived at any point in time.
Matthias: It's very cool because what you said was you
Matthias: optimize for deletion and that makes a lot of sense in my opinion and what you
Matthias: said is that you also have a very pragmatic approach and you want the next person
Matthias: to have a good time do i hear that you also want to have simple rust you want
Matthias: to have a code base that is understandable is simplicity a core value.
Kiril: Yes my very soft yes no actually i want to say i want to share a piece for for
Kiril: the audience early in my career i watched a video by Rich Hickey called Simple Made Easy.
Kiril: And he makes the distinction between simple and easy. And he talks about the
Kiril: value of simplicity in software.
Kiril: So I watched that talk and it really changed my perspective on software engineering profoundly.
Kiril: And I have since rewatched that talk together with colleagues at any given time
Kiril: with different set of colleagues.
Kiril: But I've seen this talk, I would say more than 10 times and I think it's really valuable.
Kiril: So simplicity in software is a core value for us.
Matthias: And what's the difference between simple and easy?
Kiril: Well, I would not do it justice. I think people should watch the talk,
Kiril: but in a nutshell, simple relates to having not interleaving concepts.
Kiril: If you have something that is dealing with let's say.
Kiril: Okay, firstly, you don't want to mix up state and functionality.
Kiril: So there is that separation.
Kiril: And secondly, you don't want to have or you want to avoid this endangling of
Kiril: concerns. Like you have a struct that is responsible for this and that.
Kiril: Can it be separate? Is it appropriate for it to be separate?
Kiril: And the difference with easy is so
Kiril: rich makes a very eloquent point about how easy
Kiril: it's more relates more
Kiril: to if if a if something is at hand
Kiril: or familiar so it's it's a distinction in okay
Kiril: familiarity so this is resembles something i've
Kiril: done before and and that familiarity is
Kiril: good it's great if something can be familiar but simple is has a has a more
Kiril: more pure and and this this talk he he talks about actually simple comes from
Kiril: from from the latin or simplex and that means one braid you're not yeah you're
Kiril: not complecting it i'll not do it i will not do it in the podcast,
Kiril: the talk is called simple made easy by rich hickey this is the creator of the
Kiril: closure programming language and i had a closure phase for lasted many years yeah.
Matthias: And in that talk he also refers to that and says just because something is familiar
Matthias: doesn't mean that it's simple because maybe you got used to it in some weird
Matthias: way maybe we got used to svn at some point or We got used to the complexity,
Matthias: maybe not complexity, but with the familiarity of Git.
Matthias: And maybe that might not have been the perfect abstraction. We just got used
Matthias: to it, to branching and naming things and rebasing and so on.
Matthias: But those things are easy in the sense that you said is familiar,
Matthias: but maybe not simple. Yeah.
Matthias: Not intertwined with other ideas.
Kiril: Right yeah and.
Matthias: When you when you talk about deletion i guess you enforce it somehow because
Matthias: if you can only delete things that are isolated.
Kiril: Correct yes yes so packaging or creating by by feature as like a core tenant
Kiril: like that way preventing the the complecting the word is complect common word in english.
Scott: I thought you said it was latin so So I've never heard the word complect before, so.
Kiril: Okay.
Scott: If it is, I'm going to look it up now.
Kiril: Yeah, I think that word spiked in popularity in 2011 after that talk.
Matthias: Was that a similar principle that you lived up to at GitHub where you said,
Matthias: make it easy to, I'm sorry, make it simple,
Matthias: make it isolated? Or was it a large code base and it kind of grew organically?
Scott: That's a great question. I mean, it really depended. I feel like for our user
Scott: interface, for user-facing stuff, it was different, right?
Scott: Like we really wanted, there was a lot of thinking about and understanding what
Scott: do we present our users and this concept of everything added dilutes everything else, right?
Scott: So we didn't want to be Jira or something. Like we didn't want to just add features
Scott: because people said that they wanted features or said that they would pay for
Scott: features. Like we really wanted to keep it.
Scott: I mean, we wanted to keep it simple, right? Like we wanted to keep it that there
Scott: were only so many things you could do and that we felt that these were the important
Scott: things to do because everything else that you add makes it more complex by definition, right?
Scott: From a backend standpoint, from a code standpoint, from an infrastructure standpoint,
Scott: I think because it wasn't customer facing, you know, we could experiment more.
Scott: We had a lot of people coming on at a relatively fast rate at some point.
Scott: And so like a lot of it, it just depended on what system you were in and what
Scott: that particular team cared about, right?
Scott: Like, did it care about performance? Did it care about maintenance?
Scott: Did it care about observability, right? Like there were different things that
Scott: different teams cared about and would optimize for. So I don't know that we,
Scott: I would say that, you know, every team had like some, like GitHub had some overarching
Scott: sort of concept. I think it really depends.
Scott: It was very, it was very, I don't know, tribal, right?
Scott: Like, like there were groups and they had their things and it wasn't like,
Scott: here's the GitHub philosophy.
Matthias: When GitHub started, Ruby was also pretty new, I guess, wasn't it?
Scott: I mean, boy, that's a good question. I mean, Rails was new-ish,
Scott: I think, you know, five years or four years or something.
Scott: Ruby was around longer, but I think Rails really kind of picked up Ruby.
Kiril: It was the prime time of Rails.
Scott: Yeah. I mean, it was when, I mean, there's still, you know, Shopify and Twitter
Scott: and, you know, like all of these.
Kiril: Airbnb.
Scott: Airbnb, like all of these companies. And they were all in San Francisco and
Scott: we knew all these guys, right?
Scott: And so, like, I think it was a really nice culture of entrepreneurship and building
Scott: interesting things, right? And having customer focus.
Scott: Like it was a great environment for, for all of that. I think the Ruby community
Scott: and, and, you know, like I may have said at the beginning, I think it really
Scott: helped make Git the, the thing that won, right.
Scott: Is, is because, you know, we started part of the reason I think is we started
Scott: GitHub and we were giving everybody, we obviously preferred Git and everybody in these,
Scott: all of these communities started using Git to, to some degree because of,
Scott: of GitHub or because of us personally, just, we knew a lot of these, these people.
Scott: I'm really curious if GitHub hadn't come along, if Mercurial would be what everybody's
Scott: using now, right, or something else.
Scott: But, yeah, I mean, like you were saying before, like, we're all familiar with Git.
Scott: There's kind of this local maxima problem. Like, it's not, there's nothing better
Scott: than that. It's where everybody's kind of entrenched to some degree.
Scott: So we do, we are familiar with it. It does have this easy, you know,
Scott: even though it's not easy, like, it's easier than learning something else.
Kiril: So I- It is not easy, but it's simple. Yeah.
Scott: Is it?
Kiril: Okay, maybe not.
Scott: Maybe. It works.
Matthias: The reason why I was asking was that back in the day when you started a new
Matthias: application, Ruby, was it a positive signal to the outsiders, maybe investors?
Matthias: I know that GitHub never took any investments as far as I remember,
Matthias: but would it have raised any eyebrows?
Matthias: Or did investors not care at all?
Scott: You know, I, so we, we bootstrapped until we were four years in,
Scott: we had almost, almost a hundred employees from, from, you know,
Scott: such a sort of a bootstrap background.
Scott: So when we talked to investors, it was, they didn't care what we were building it on, right?
Scott: Like we, we had millions of users at that point and everybody, we had taken no VC.
Scott: So, so everybody wanted in on that. So I didn't have normal VC conversations
Scott: at that time. I, I don't, even now I don't, I do some angel investing or I have,
Scott: I've talked to lots of investors about this.
Scott: Nobody's cared about the tech stack so far.
Scott: I don't remember seeing it in lots of decks or something like,
Scott: I don't know that, that most investors care so much about how you're building
Scott: it as much as what you're building.
Scott: Like, like that is important. Like, is there conceivably a market, right?
Scott: Like doing it in Rust versus Ruby versus whatever, like whatever you're familiar
Scott: with and whatever you think you can move fast on or get to product market fit quickly.
Scott: I'm not sure that there's that many investors. I mean, I haven't run into a
Scott: lot of investors who have really cared.
Matthias: If you talk to someone else, a friend from another company and they started
Matthias: building up their tech stack and they were considering Rust and maybe other
Matthias: languages like Go or Zig, what would you tell them, what advice would you give?
Scott: Yeah, I mean, I would say work with whatever the founders or the technical founders,
Scott: enjoy working in right can can move fast in because
Scott: you can always i mean you know twitter's not ruby anymore i think
Scott: they they moved to Scala or something at some point like once
Scott: you get once you once you find product market fit
Scott: like once you start getting users and you start getting traction like and you
Scott: make it you can rewrite it in anything you want like it's it's actually kind
Scott: of interesting that that shopify and github and you know some of these big big
Scott: companies are still running on ruby stacks because they they still like using
Scott: it i think for the most part i'm sure there are people in those companies that
Scott: are like we should rewrite this and go or whatever.
Scott: But, but yeah, in the beginning, I think honestly, from a VC or from a,
Scott: from a startup standpoint, I, I would, I would heavily say it does not matter,
Scott: right? Like we could have chosen Electron.
Scott: I think we'd be roughly as far as, as we are today that I, I think that Rust
Scott: and Tauri were a better choice for, for, you know, future reasons and things like that.
Scott: But like, you know, From trying to find out, is what I'm building valuable,
Scott: I honestly, I have a hard time saying you can't work your way around.
Scott: Everything has problems in some way and everything has strengths in some way.
Scott: And so, you know, like it just depends. I think it's all shakes out.
Scott: Like you'll work around the problems if you make it.
Matthias: But that's also a very positive thing because maybe someone is considering to use Rust.
Matthias: Maybe they are considering that it would be harder to get investments.
Matthias: And you as an angel investor, you know how these conversations work.
Matthias: So they shouldn't be concerned about that.
Scott: Yeah, no, I don't think any, from a VC, from a raising money standpoint,
Scott: I don't think anybody really cares.
Scott: I think they'd much rather that you do what you're comfortable with and you
Scott: feel like you don't have to have a big learning curve, you know,
Scott: so that you can experiment and figure it out.
Scott: But it's the same in any, like it's like, you know, what JavaScript framework
Scott: do I use if I like job? Like who cares, right?
Scott: Use Angular, use Svelte, use React, who cares?
Scott: There's pluses and minuses to all these things. It's just, you know,
Scott: what can we move fast with at first and then we'll figure it out.
Matthias: Do you like to work on the code base every day, Kiril? How does it feel to
Matthias: come to work and touch the Rust code?
Matthias: Do you feel you know, do you feel,
Matthias: Like you're making progress? Do you feel like there's a lot of velocity?
Matthias: Like it's maintainable?
Matthias: What's your feeling on the current code base right now?
Kiril: I mean, it's very exciting. I think
Kiril: it's a little bit like a puzzle that's coming together more and more.
Kiril: It's coming together in terms of performance or fixing issues that people are
Kiril: having. So that's very exciting to me.
Kiril: Like knowing that you fix an issue that somebody has reported gives me a huge kick.
Kiril: Actually, just this morning, we made a release. And I know that in that release
Kiril: comes some fixes that I made yesterday and people have reported those problems
Kiril: and that feels really good.
Kiril: So that's the part that gives me the biggest satisfaction. But just from a technical
Kiril: standpoint, like working with Rust, it is satisfying.
Kiril: It is interesting because I feel like I'm over the initial hump where,
Kiril: you know, I struggle with, you know, the systems that are different in Rust.
Kiril: And now I can just focus on what we're building rather than what we're building with.
Kiril: So from that perspective, it's cool. I'm very happy with Rust as a choice.
Kiril: I feel, so to add to what Scott said, iteration speed is everything.
Kiril: The ability to say, all right, I have an idea, I wanna try it and see if it
Kiril: works and then iterate from there.
Kiril: That's critical for somebody who is making something new and trying to understand
Kiril: if other people want it. So...
Kiril: With that said, I mean, Rust can be slower to prototype in if one is not at
Kiril: all familiar with Rust or if it's something that is...
Kiril: I actually honestly think the user interface stuff would be quite difficult
Kiril: to do in Rust just because of the nature of user interaction.
Kiril: But for something that feels very functional, like I described earlier with
Kiril: a command that gets executed, that fits very nicely with the Rust model.
Kiril: Like you don't need a lot of state you don't have to think about state very
Kiril: much you're you're transforming something on disk you you it's something that
Kiril: you can test in a good way and then it's a very good fit so depending on the
Kiril: use case depending on the kind of context yeah it can be just the right to to to for the job you.
Matthias: Say you're happy with the code base but one thing that people always criticize
Matthias: are the compile times the rust compile times do you have any issues with that in your code pace i.
Scott: Wish it was faster i wish it was in in developer mode it takes about if it's
Scott: if it's an iterative build and i've made a change to one crate for us it takes about,
Scott: two seconds or three seconds to to kind of make the new target and run it again
Scott: of course i wish it was faster and i wish it can do it as fast as go go is really
Scott: fast if if i need to build everything from scratch it takes about a minute with
Scott: that said it's not a huge issue.
Matthias: I've seen way worse.
Scott: Yeah, I haven't. I was, I've never really, like when I'm working on the Rust
Scott: code, I haven't really noticed it being horrible.
Scott: I mean, the big thing for us is that we're dogfooding it, right?
Scott: So we're working on the version control system that we're using to try to version
Scott: control the version control system that we're working on.
Scott: And so, like, we have, we can't have our main code base in the development build
Scott: of the thing because then you change some Rust code and it dies, right?
Scott: Or you do something and it corrupts, like, your database, right?
Scott: Like i've run into that several times so like i have to have the
Scott: nightly now that we have a nightly it's much nicer because i do the nightly
Scott: for the for the gip other code and then and then other repositories with the
Scott: development build but like yeah that that type of thing where it just kill it
Scott: and then start it back up again was but i mean yeah it only takes a couple seconds
Scott: even even for this this larger sort of gui type program it's it's not bad at all.
Matthias: We need to keep an eye on the time because you need to go
Kiril: the jokes we.
Kiril: Haven't done the jokes can we do the jokes so.
Matthias: Yes but
Matthias: be
Matthias: careful what you say in the podcast.
Matthias: So whatever
Matthias: you say we'll be able.
Kiril: Okay i have a good one so firstly let
Kiril: me set this up well we at gate butler have a dad joke culture we like puns we
Kiril: like funny dad jokes to the extent where during our friday all hands meeting
Kiril: we do an event where everybody goes on a stage, tells their dad joke of the week.
Kiril: And then whoever gets the biggest laughs wins a little trophy.
Kiril: And then we pass the trophy around. So we got it out, that, that joke off and yeah.
Kiril: So today we are having an old hands and I've prepared a joke.
Scott: I want to hear your joke.
Kiril: So what do you call a dog that can make magic tricks?
Kiril: You call it the labracadabrador.
Scott: That's a good one. I like that one.
Kiril: Make sure you laugh just as much later when the jury's out.
Scott: So last night I was just about to fall asleep and the ghost of Gloria Gaynor came into my room.
Scott: First I was afraid. I was petrified.
Scott: It's a song. That one didn't land as well.
Kiril: I didn't know the song.
Matthias: I liked it.
Scott: Oh, first I was afraid. I was petrified. Is that better? Should I do it that way?
Kiril: Yes.
Scott: Yeah, I got to sing it.
Kiril: I'm so sorry. You should sing it for the job. Oh, this is good.
Kiril: You should sing it later.
Scott: He's rethinking all of his decisions, inviting us on this podcast.
Matthias: A friend of mine is trying to date a woman from the south of France.
Matthias: And he was unsure if he could approach her and talk to her. And I said Corsican.
Scott: That's a good one.
Matthias: Oh, my God. That's a good one.
Matthias: So you should make this a thing on your podcast.
Scott: Too. You should make all of your guests at least share one to start it out with.
Kiril: We should do it on our YouTube channel.
Scott: Yeah, we should. Yeah.
Matthias: Okay. And it has become a bit of a tradition in this show. That's the actual tradition.
Matthias: To have one last statement about the Rust community.
Matthias: So if you had the chance to address the Rust community as a whole,
Matthias: anything you could say, what would you say?
Matthias: Could be positive or negative, could be about the community ecosystem,
Matthias: compile times, whatever.
Scott: I mean, I love the crates system and the crates ecosystem actually like coming
Scott: from, you know, sort of Ruby gems and, you know,
Scott: sort of the, I don't know, crating the gem sort of system there.
Scott: I feel like it's, it's, or like, you know, NPM or, or whatever,
Scott: like I, I actually really, really appreciate how nice it is and how nice it
Scott: has been to work with and to find stuff and to get documentation.
Scott: So, you know, from my perspective, I've, I've been very, very surprised by, by how good that is.
Scott: And then, you know, and then from a personal standpoint, I would say it's funny. Steve has been great.
Scott: Like, like he's my, he's like the biggest introduction to the Rust community that I know.
Scott: And I found him in the JJ chat rooms. And he was like, hey, Scott,
Scott: thanks for the pro git book.
Scott: And I was like, hey, Steve, thanks for the Rust book. Fantastic.
Scott: And then everybody's like, oh, these guys patting each other on the back.
Kiril: I love the language. Thanks for Rust. Thanks for the ecosystem things.
Kiril: I mean, the libraries have been great.
Scott: Yeah, I mean, it's interesting. Like if we I think if we think back,
Scott: like we didn't really know at the beginning of this, like, is,
Scott: is Electron the right call?
Scott: Is, is Tauri the right call? I think, you know, after having worked it in,
Scott: in, in two years, we would, I believe we would both probably recommend that
Scott: somebody uses that use, use Tauri, learn Rust.
Scott: Like, I think we've, if we had to do it again, we would do the same thing again,
Scott: which is actually very nice. Like, like, as opposed to being like,
Scott: man, I wish we'd gone down the Electron route or something.
Scott: So So we really do like using the system to build our company on,
Scott: which is not a not scary thing to do.
Kiril: Actually, I have something useful here. And now that I've thought about this a little bit longer,
Kiril: I like that the Rust community is generally very thoughtful for making things
Kiril: in the ecosystem that work and that are relatively well thought through.
Kiril: It's not not just tossing tossing crates out in the open and it's like okay,
Kiril: that doesn't matter there is there is some some consideration for for okay producing
Kiril: high quality software i think there
Kiril: there are i was thinking about the dependencies that we use uh we have.
Kiril: As we discussed git 2 which is bindings for libgit 2
Kiril: which works really well it's uh it's documented and it functions very really
Kiril: well we we have used a library called notify for file system watching and that
Kiril: works slightly differently under the hood for different platforms but it works
Kiril: for us in a transparent way which is brilliant.
Kiril: You have Tauri which has a very healthy
Kiril: attitude towards security like the way they treat
Kiril: isolating let's say the JavaScript code from the Rust which has access to the
Kiril: file system and just handling things in a secure way and not least Git Oxide
Kiril: which is a piece of software that is well thought through as well in terms of
Kiril: security, in terms of performance.
Kiril: And it feels like the tooling in the ecosystem produced by the community is of high quality.
Kiril: So I think this is probably the highest praise I can give.
Kiril: Just the median quality of a library or crate that you can find it's greater
Kiril: than the medium quality of other ecosystems.
Kiril: And I have been exploring languages for many years now, and I genuinely feel this way.
Matthias: Amazing clothing words. Where can people find out more about Git Butler?
Scott: Yeah, I mean, the easiest thing is to go to gitbutler.com, and we have links
Scott: to our source code on GitHub and our Discord, which is kind of interesting.
Scott: We just recently kind of did this experiment where our entire corporate chat
Scott: is on the same Discord that is public.
Scott: So we have some private rooms for just us. But for the most part,
Scott: a lot of what we do is build in public and it's on Discord.
Scott: So you can find our blog there, which you mentioned, I think,
Scott: at the beginning of this as well.
Scott: But yeah, gitbutler.com is also a really pretty website.
Scott: Actually, Pavel, our designer, approached it in a really interesting,
Scott: awesome way that I think is very unique. So it's not hard on the eyes.
Matthias: Find all the links in the show notes. And I guess that sums it up.
Matthias: Scott, Kiril, thanks so much for taking the time.
Scott: Yeah, thanks for having us.
Kiril: Thank you very much.
Matthias: Rust in Production is a podcast by corrode. It is hosted by me,
Matthias: Matthias Endler, and produced by Simon Brüggen.
Matthias: For show notes, transcripts, and to learn more about how we can help your company
Matthias: make the most of Rust, visit corrode.dev Thanks for listening to Rust in Production.