So do they want people to watch this or not?
To find bugs, I use "bisect but visually" (I usually use jetbrains IDEs, so I just go to the git history, and do binary search in the commits, displaying all the files that were affected, and jumping easily to such versions).
Git conflicts are easily solvable as well with a gui (jetbrain IDEs) via the cli or via something like Sourcetree. Easily, the most used "feature" of git that i use is:
- for a given line of code, see all the files that were touched when that line was introduced
But I usually do that via the IDE (because to go through dozens of files via cli is a bit of a hassle for me)
So, what am I missing? I know jujutsu is much simple (and powerful) than git, but I only have used the "good parts" of git and it has never been a bottleneck... but ofc, you don't know what you don't know.
I regularly have multiple commits being worked on at a time across different parts of the codebase. If I have to sync to head (or any rebase) and one of my side branches that I'm not actively working on hits a merge conflict, I don't have to deal with it in that moment and get distracted from my work at hand (ie: I don't need to context switch). This is a big productivity win for me.
If you want some other points, check out: https://fallthrough.transistor.fm/43#t=0h31m5s
Some points from the episode:
* With no separate index vs commit, (everything is just a commit), you don't need different commands and flags to deal with the different concepts, they are all just marked together. In JJ, if you want to stack/stage something, it's just a normal commit (no reason to have different concepts here).
* You don't have to name/commit a change at all. Every time you run any JJ command (like `jj log`, or `jj status`), it will snapshot the changes you have. This means that if you want to go work on some other branch, you don't have to go and commit your changes (they auto-commit, and you don't have to write a description immediately), then update to master branch and start working again.
* Or you can just `jj split` (https://jj-vcs.github.io/jj/latest/cli-reference/#jj-split), and split a working changeset into 2 separate commits.
I also really like that every change is automatically committed. It’s a great mental model once you get used to it.
Rebases must be done linearly. And right now! Oops, you made an error in an earlier stage of the rebase? Start over, good luck! Want to check something from earlier while you’re in the middle? Sorry, you’re in a modal state and you don’t get to use your regular git tooling.
You can use all the regular git tools in a rebase, in fact it would be quite useless without. You can also just jump to other branches or record a fix to a previous commit. It doesn't matter what you do in the meantime, it only cares what is the HEAD, when you call git rebase --continue, and then it only performs what commands you specify in the rebase todo. You can even change the todo list at any time.
A few months back I had to sanitize the commit history of a repo that needed certain files removed from the entire history. I could have read the manpage for `git filter-branch`, but in jj editing commits is just a normal, sane part of your workflow. It was a blindingly obvious one-liner that just used all the commands I use every day already.
Even better, it was fast. Because “edit the contents of a bunch of commits” is a first-class operation in jj, there’s no need to repeatedly check out and re-commit. Everything can be done directly against the backing repository.
1. We're rewriting some commits. Let's say a chain of commits A through G. We want to make some change to commits A and D.
2. As we're editing commit D, we realized that we need to make some changes to B to match the updated A.
3. Also while editing D we realized that we want to take a look at the state in A to see how something worked there.
With jj, here's what I would do:
1. Run `jj new A`, make the changes, then `jj squash` to squash the changes in to A and propagate them through the chain.
2. Run `jj new D` to make changes. We now notice that we wanted some changes to go into B. We can make the changes in the working copy and run `jj squash --into B -i` to interactively select the changes to squash into B.
3. Run `jj new A` to create a new working-copy commit on top of A, look around in your IDE or whatever, then run `jj edit <old commit on top of D>`. Then run `jj squash` to squash the remaining changes in the working copy into D.
I think you know the steps to do with Git so I won't bother writing them down. I find them less intuitive anyway.
2. Edit changes for D. Also edit changes for B. Interactively `git add` changes for B. `git commit --fixup=B`.
3. Finish changes for D, then call git commit --fixup=D
Before push I run `git rebase --autosquash`, optionally `git rebase --exec='make check'` to rerun all the tests on the changed commits.
Where is that "much harder"?
I wouldn't say I avoid this, I also run `git rebase -i` several times per day, and I also often use `git commit --fixup` during a rebase.
> Makes sense, but doesn't it break down when there are conflicts between the changes you're making in the working copy and the target commit?
Yes, but wouldn't this be the same in JJ, when you do your changes on top of A, and later squash them into D? If you don't want to have the changes, you can also checkout D and do the changes there. Then you have two options:
- `git commit --fixup`, later do `git rebase`
- `git commit --amend`, and `git rebase --onto`
Most times I do the thing described earlier and just solve the conflicts, because that's just a single command. Also when its only a single case, I use `git stash`. (The workflow then is do random fix, git stash, then figure out where these should go, git rebase)
> How do you adjust the steps if there were conflicts between the changes we wanted to make to A and the changes already present in B?
I just resolve them? I think I don't understand this question.
In order to make changes to commit A when there are conflicting changes in B, I was thinking that you would have to use interactive rebase instead because you can no longer make those changes in the working copy and use `git commit --fixup`, right? And because there will now be conflicts in commit B, you will be in this "interrupted rebase" state where you have conflicts in the staging area and it's a bit tricky (IMO) to leave those and look around somewhere else and then come back and resolve the conflicts and continue the rebase later.
> Yes, but wouldn't this be the same in JJ, when you do your changes on top of A, and later squash them into D?
The difference is that we don't end up in an interrupted rebase. If we squashed some changes into A and that resulted in conflicts in B, then we would then create a new working-copy commit on top of the conflicted B (I call all of the related commits B even if they've been rewritten - I hope that's not too confusing). We then resolve the conflicts and squash the resolution into B and the resolution gets propagated to the descendants. We are free at any time to check out any other commit etc.; there's no interrupted rebase or unfinished conflicts we need to take care of first. I hope that clarifies.
Yes.
I don't see the drawback honestly. Invoking git rebase, means I want to resolve conflicts now, when I want to do that later, I can just call git rebase later. When you want to work on top of the B with conflicts, the code wouldn't even compile, so I expect JJ, to just give you the code before the squash, right? How is this different from in Git?
Anyway, I'm just explaining how jj works and what I prefer. As Steve always says, you should use the tools you prefer :)
Yes, I do the same. I think it's not too different. You can also commit randomly somewhere else, it is only a problem once you try to start another rebase or merge. (But I never needed to do it, I just tried it out during discussions like this.)
> Anyway, I'm just explaining how jj works and what I prefer. As Steve always says, you should use the tools you prefer :)
Sure. I'm not objecting to you using JJ, I was objecting to you stating, that it is "much harder" in Git. This is seems to be a common sentiment among JJ users, but it always seem to amount to that people bother to read the manual and understand the tool AFTER they used a VCS for years.
Perhaps, but I don't think that's true for me (or for Steve). I've contributed something like 90 patches to Git itself (mostly to the rebase code). To be fair, that was a while ago.
My impression is actually that many people who disagree with the sentiment that jj is much easier to use seem to have not read its manual :) Some of them seem to have not even tried it. So, the way it looks to me, it's usually the people who argue for jj who have a better understanding of the differences between the two tools.
Have you tried jj yourself and/or have you read some of the documentation?
So actually no, and you have a point. :-)
I often just read "this is hard in Git" and think isn't this just this command? JJ has some nice features, but what appeals to me seems to not to be that hard to add to Git, so I will just wait a bit.
feels the same when people say, "jq is hard i use python instead" like ok
Two examples from recent memory:
Someone merged the develop branch into their branch, then changed their mind and reverted the merge commit specifically (i.e. reversing all the incoming changes), then somehow merged all of this into the develop branch, undoing weeks of work without noticing. I had to go in and revert the revert to undo the mistake. Yes they messed up, but these things happen with enough people and time.
Another very interesting issue that happened to a less technical person on the team was that their git UI somehow opened the terminal in the wrong folder. They then tried to run some command which made git suggest to run 'git init', creating another git repo in that wrong location. Fast forward some days and we had an issue where people had to clean their repos, so I was in a call with the person helping them run the clean command. The UI opened the wrong location again, I helped them put in the command and it started cleaning. The problem was that this git repo was essentially at the top level on their disk, and since was a fresh repo every single file was considered a new file so it tried to delete EVERYTHING on their disk. This was of course mostly my fault for not running git status before the clean command, but this potential scenario was definitely not on my mind.
An example of something that the reflog isn't going to capture is a git reset --hard losing your unstaged changes, whereas the equivalent flow and commands in jj would allow you to get those contents back.
Git does version everything that is in the repository and all these states occur in the reflog.
Yes. I think that this difference is what introduces a lot of friction, both in the model, and how people use it. The divergence between the files that exist on disk inside your working copy and what's actually tracked means lots of opportunities for friction that go away once you decide that it should. That doesn't mean things are perfect, for example, by default jj only snapshots the filesystem when you run a `jj` command, so you can still lose changes from in between those, you need to enable Watchman to get truly full logging here.
> all these states occur in the reflog.
Well, let's go back to the documentation for reflog:
> Reference logs, or "reflogs", record when the tips of branches and other references were updated in the local repository.
It only tracks changes to refs. That is, the states that refs have been in. So, one big example is detatched HEADs: any changes you make to those, which still are contents of the repository, are not tracked in the reflog.
Even for refs, there's differences: the reflog says "ref was in state x and changed to state y" without any more details. jj's oplog keeps track of not only the state change, but the reason why: "rebased commit <sha> with these args: jj rebase -r <sha> -d trunk"
The reflog only tracks individual refs. Say we rebase multiple commits. The reflog still just says "the head of this branch was in state x and changed to state y" but the oplog says "a rebase happened, it affected all of these commits refs in these ways," that is, it's just inherently more rich in what it tracks, and does it across all relative commits, not only the refs.
This doesn't mean the reflog is bad! It's just a very specific thing. Git could have an operation log too, it's just a different feature.
$ git checkout HEAD
$ git commit --allow-empty -m "_"
$ git checkout master
$ git reflog
a91 (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: checkout: moving from b94 to master
b94 HEAD@{1}: commit: _
28d (origin/feature, feature) HEAD@{2}: checkout: moving from feature to @
> Even for refs, there's differences: the reflog says "ref was in state x and changed to state y" without any more details. jj's oplog keeps track of not only the state change, but the reason why: "rebased commit <sha> with these args: jj rebase -r <sha> -d trunk"> The reflog only tracks individual refs. Say we rebase multiple commits. The reflog still just says "the head of this branch was in state x and changed to state y" but the oplog says "a rebase happened, it affected all of these commits refs in these ways," that is, it's just inherently more rich in what it tracks, and does it across all relative commits, not only the refs.
68e HEAD@{15}: rebase (finish): returning to refs/heads/feature
68e HEAD@{16}: rebase (pick): message #6
7ff HEAD@{17}: rebase (pick): message #5
797 HEAD@{18}: rebase (pick): message #4
776 HEAD@{19}: rebase (pick): message #3
c7d HEAD@{20}: rebase (pick): message #2
f10 HEAD@{21}: rebase (pick): message #1
c0d HEAD@{22}: rebase (start): checkout @~6
a7c HEAD@{100}: rebase (reword): message ...
3b1 HEAD@{229}: rebase (reset): '3b1' message ...
4a4 HEAD@{270}: rebase (continue): message ...jj still ends up keeping information in here that the reflog doesnt, but you're right that these aren't the strongest points.
I think Git will just gain a oplog. You just need to append a commit hash to a list before each command and implement undo as remove item and checkout. The hardest thing will be race conditions, but Git already knows how to be a database.
Git has lots of sharp edges that can get hairy or at least tedious really rapidly. You have to keep a ton of random arcana in working memory at all times. And a bunch of really useful, lovely workflows are so much of a pain in the ass that you don’t even conceive of doing them.
I learned jj in one day and never went back.
I'm not a welder or a metalworker, but I do know how to weld. I use a welder a handful of times per year when I need/want to. Welding is dangerous, and achieving excellence is a difficult and long road. But I can use the same tools as a pro and still get a few pieces of metal stuck together without having to relearn and restudy the whole system each time something goes wrong.
I haven't used jj in anger yet, but I think it might at least be approaching that style of developer tool.
Now, once you teach them it’s a commit graph with names, some of them floating, some people get it.
The thing is, not everyone is comfortable with a commit graph, and most people are not - just like people get lists and arrays but graphs are different.
So I agree with you on principle ( it shouldn’t be difficult), but most people don’t have a graph as a mental model of anything, and I think that’s the biggest obstacle.
You can see where you were and hard reset back, no matter what state you are in.
The feeling of complexity comes from not yet understanding that commits are just sets of changes to files. They are then thrown off the scent by new terms like origin clone vs push and pull, merge vs rebase, HEAD increment notation vs other commit hashes.
Once people start with a local understanding of using git diff and git add -p they usually get the epiphany. Then git rebase -i and git reflog take them the rest of the way. Then add the distributed push and fetch/pull concepts.
I understand how to do these things, but git’s interaction model makes it tedious at best and hard at worst.
jj’s interaction model makes these things simple, straightforward, and obvious in the overwhelming majority of cases.
I don't see this anywhere nearly as drastically with other tools.
And the significant time and effort amounts to a total of 15 seconds.
It’s exactly like folks in 1995 telling you to rtfm when you’re trying to install Linux from a floppy disk. It’s doable, but annoying, and it’s not that easy.
Just in case, I'm talking about the Pro Git book [0]. I remember reading it on my kindle while commuting to office by train. It was so easy to understand, I didn't even need a computer to try things. And it covers everything from bare basics, to advanced topics that get you covered (or at least give you a good head start) if you decide to develop your own jujutsu or kurutu or whutuvur.
The book says that ‘ To really understand the way Git does branching, we need to take a step back and examine how Git stores its data’ then it starts talking about trees and blobs.
At that point you’ve lost almost everyone. If you have a strong interest in vcs implementation then fine, otherwise it’s typically the kind of details you don’t want to hear about. Most people won’t read an entire book just to use a vcs, when what they actually want to hear is ‘this is a commit graph with pointers’.
I agree with you : the information is there. However I don’t think you can in good faith tell most people to rtfm this, and that was my point.
The git mental model is more complex than cvs, but strangely enough the docs almost invariably refer to the internal implementation details which shouldn’t be needed to work with it.
I remember when git appeared - the internet was full of guides called ‘git finally explained ‘ , and they all started by explaining the plumbing and the implementation. I think this has stuck, and does not make things easy to understand.
Please note I say all this having been using git for close to 20 years, being familiar with the git codebase, and understanding it very well.
I just think the documentation and ui work very hard towards making it difficult to understand .
I can, and I do.
The explanation in that book creates a strong coherent and simple mental model of git branching. I honestly can't think of a better explanation. Shorter? Maybe. But "graph with pointers" wouldn't explain it.
So let's agree to disagree.
Hell, I've personally mentored people who struggled with git and I could feel their struggle.
I'm not saying that learning git was an insurmountable task for them, but their struggle was not something that I had to go through.
It does `git pull <default remote> foo`.
> vs a remote
It gives an error, because you haven't specified the remote.
I don't know what behaviour you find intuitive here?
> how do you fix it if you messed up/which is preferred when both exist?
git pull is YOLO mode, so I never do it, but I would just reset the branches where I want them to be? You get a summary with the old and new commit hashes, so resetting is really easy.
But whatever state I'm in, I'm sure I can reset back to where I were using reflog.
Here: git rebase is slightly broken in conflict handling. It can be made simpler to understand with jj.
You can do this, but due to file locking, you can corrupt the state if it's shared. jj is specifically designed so that it won't corrupt the repo in this way: https://jj-vcs.github.io/jj/latest/technical/concurrency/
That said, I haven't tried this lately, maybe it's gotten more robust over time. But historically, even a bare repo on something like Dropbox has issues.
I fully agree that this is a niche use-case.
This wasn't what I was talking about, I meant that you should create a bare repo and push to it, not that you work directly in a directory in Dropbox.
This is a very git command.
It calls "git" to "init"ialize a repository, which we don't need a working tree for ("bare") and that it's going to be "shared" with members of the "group".
You sure that exists?
Git repositories that contain terabytes of source code?
I could imagine a repo that is terabytes but has binaries committed or similar... But source code?
Having 86 TB of plain text/source code - I can't fathom the scale, honestly
Are you absolutely sure there aren't binaries in there (honestly asking, the scale is just insane from my perspective - even the largest book compilation like Anna's isn't approaching that number - if you strip out images ... And that's pretty much all books in circulation - with multiple versions per title)
It was made to make working on Windows source code possible with Git.
[0] https://www.slideshare.net/slideshow/death-by-powerpoint/855...
My feedback:
- I think you could improve by being more excited / exciting (the Death By Powerpoint slide deck says "passionate"). Personally, I try to mitigate this problem by drinking coffee shortly before I'm expected to be engaging. It is a drug, and for me it works.
- You could also draw the main impactful points out of the background info. The presentation you give here has a lot of deep technical detail, which is certainly of interest for the correct audience, but I think generally fits poorly in a powerpoint presentation. I think you'd generally want to focus on more high-level performance characteristics, or particularly interesting details. Perhaps a 3-4 page document would be better for this sort of deep technical material. Or maybe the level of detail is actually perfect, and I'm just not the correct audience.
I really love your response here. You seem like a great person, I think your coworkers are lucky to have you.
The presentation was mainly for the audience that was present at the conference, which was mainly people who have used jj for a relatively long time, so I think part of the problem is just a mismatch between audiences there and on YouTube.
I agree about being more exciting. Not sure how to improve that :P I drink too much coffee all the time that I don't notice any difference. Harder drugs, perhaps :)
I'd also flag that the audio is not good which isn't your fault. The trend towards conferences just pointing a camera at a lectern and throwing the footage on YouTube is unfortunate especially when it replaces circulating the slides as opposed to augmenting them. As a form of archive for attendees to review it works but not as a distribution channel.
If you struggle with being engaging, then you want even less text on each slide so that the audience doesn't get an additional reason to tune you out.
Also, present things that you are passionate about if you want to make people care about your presentation.
> Also, present things that you are passionate about if you want to make people care about your presentation.
Haha, this topic is something I'm very passionate about. That's how I look when I'm excited :)
I can confirm this (we've worked together)
1. You haven't practiced enough. Practice more.
2. If you think you're talking too slowly, slow down even more. (Can't tell you why it's worded like that.)
This is a really hard topic since it's hard to understand the significance of the jj contributions without explaining a ton of internal details like Piper, CitC, TAP, blaze, etc. I think you struck a good balance here.
I don't think you need to "be more engaging" or be more passionate, and when people say that, it indicates they aren't engaged, but it's not a useful suggestion of how to improve.
I think the main issue was that on just about every slide, I found myself wanting to read ahead on the slides instead of waiting to listen to you talk. There are a couple factors to this:
1. Impatience. I want to ingest information faster. Believe it or not, the "talk slowly" advice is usually not good for a technical talk with decent acoustics. E.g. listen to a talk by Bryan Cantrill and notice how fast he talks while still being clear. Rehearsal helps, but if you simplify your slides, you can also make them easier to perform. Listen to a random slide in your video and notice how much time is filled with silence or filler words.
2. Scanning the slide because I'm unsynchronized with the speaker. E.g. if everything you say isn't clearly correlated with the content of the slide in a linear way, then I have to scan the slide to attempt to "resychronize" and figure out what bullet you are on. Sometimes presenters don't want to read the bullets verbatim, which makes it difficult to match up the spoken language with the written language, whereas if you said the first word in a bullet, I could quickly seek to that line. Skipping bullets also causes this, especially at the end of a slide, since then I want to try to read all the bullets on a slide ahead of you in case you decide to skip them in the future.
Fewer bullets per slide and fewer words per bullet help with both of these. Aggressively cut or summarize material so you don't have to skip over anything (e.g. instead of listing 6 jj piper commands and only talking about 2, list just 2 and write the number of total commands e.g. "we added 22 subcommands including mail and submit"). Put extra material (if any) in an appendix after the end if you think you might have extra time or want to use it for Q&A. Rehearse until you can belt out what you want to say on each slide without fillers or pauses (and record yourself so you can tell how much you are doing this). When I'm sharing my screen, I actually like to point my mouse cursor at the bullet I'm on so nobody has to guess where we are, but sometimes that's not available.
Your first slides essentially teach the audience how to consume your talk. E.g. a good pattern is if (1) all your bullets are short (2) you read every bullet verbatim, elaborate on that bullet for a bit, and then repeat on the next bullet. If you stick with a pattern like that, then your audience knows how to follow along. Other patterns work too.
I'm sorry this wasn't shorter and I hope it's helpful.
https://www.essayselevate.com/post/how-to-structure-a-winnin...
"SCAR", which I learned as "Situation, Consequences, Actions, Results" but the above essay will let you go deeper.
Bad: "Two people stood up there, said a few words, and then everybody had cake and went home"
Good: "The situation was... it was a beautiful venue, everybody was dressed nicely, there was music, a slow walk. What these two people were doing was going to bond them together for the rest of their life (or until they had an ugly divorce, whichever came first). They gave a great speech that they'd been practicing all morning in the mirror, gave each other a kiss and a ring to seal the deal, then everyone had cake, danced, and went home tired but happy!"
...this is obviously (hopefully!) exaggerated, and there's a whole bunch more fluffery in the 2nd than the first but imagine this:
1) The situation is that google on perforce or git was dog slow and blah blah not designed for the scale of our monorepo, etc.
2) The consequences was reduced development velocity and increased errors in prod b/c people were trying to bypass CI/CD steps b/c everything was so slow
3) We introduced CitC / Cloud Commits, and => {your technical brilliance described here...}
4) ...and the result was butterflies and rainbows, and here's a graph that shows the production incident rates going down and the changelist rates going up after we GA'd `jj` on linux.
5) The End!
As it stands, much of the presentation is #3 but you're not even giving yourself the credit of bragging about how you discovered the problem (challenge) and the cleverness that went in to inventing your solution.
re: bookmarks:
"We often had people mailing around patches -or- Sometimes PR's were tough to review due to ... -or- I've always wanted an easy way to ..."
=> "Without good bookmark support [adoption would suffer|it would be seen as a step back|collaboration wasn't instant|...]"
=> "So I built bookmarks for `jj`, they work like ..., and solves most of the problem"
=> "It's [better|faster|cheaper|quicker|more fun] than [GitHub|Our Old System|getting yelled at by Linus Torvalds|...etc..."
=> "The IMPACT of bookmarks is: ..." => "It IMPACTED the technical bits here: ..." => "The USER IMPACT is: ..." => "...and finally the business gets: ..." => "What a powerful impact!"
I'd _LOVE_ to see you run a breakdown of any kindof arbitrary slide in the deck and post a deconstruction in this format as kindof a practice/workshop.
It's very OK if (at first) it's pretty mechanical! It's just super-helpful to basically "disassemble" what you're trying to talk about in this mechanical way, and then you can take the proper bits and put them back together.
Situation => Consequences (or Challenges) => Actions => Results => IMPACT!
If you just string a bunch of technical details or technical choices together, you're missing the whole "compelling story" that exists. Even if you just "set the stage" with a single "Situation" slide at the beginning, and a single "Results/Impact" slide at the end... each interior "loop iteration" can be easily set up with a short "Challenge/Consequence" & "Action/Detail/Choice"
"Git + Monorepo was yuck!" => [ "Slow FS" + "CitC" ] => [ "Big Checkouts" + "VFS" ] => [ "Branches?" + "Chose `cp $FILES branches/*` ; Feedback?" ] => "JJ has been well accepted and has a bright future, inside and outside of el-goog!"
My target audience were the people at the conference, who are mostly long-term jj users. The topic was "Jujutsu at Google: Architecture and future plans", i.e. explaining how it works and what our plans are at Google. I'm mentioning this because I think what you're suggesting is for a different presentation, more explaining what the advantages of Jujutsu at Google are rather than how it works. My goal was not to sell the solution to this audience because they're presumably already sold on it.
Sorry if this was obvious to you and you're saying that part of my problem was that I should have chosen a different topic and/or target audience (focusing more on potential new users, perhaps).
Just basically flip the first two bullet points:
Situation: "Our repo shape can assume: ..."
Consequences: "Non-mainline graphs fit in memory ..."
Actions: "Tada! Revset engine!"
Result: "Monotonic commit numbers"
Impact: "b/c we can sort ranges => unlocks filtering, client-side processing, etc"
(please excuse my poor understanding of the DETAILS of `jj-at-goog` internals, so I'm butchering some of the details of impact, etc).
...another comment mentioned "death by powerpoint". You can still do/make your slides as you're currently doing it, but when you're "done", just move all the text down into the "speakers notes", and focus on providing some illustrations or comparisons for the visual portion.
Example here: https://share.google/images/tWSmujLgnX2gDvtgL
On the revset, a bunch of it could be helped by "illustrating the impact" or "compare and contrast"
| RevSet | Git-on-ext3 |
+----------------+----------------+
| Indexed | FS-Traversal |
| Working Memory | Disk Cache |
| Strong Server | Local Limits |
| 456 > 123 | $RAND != $RAND |
...etc...
...and in your speakers notes, you can record some of the technical details you want to talk through.You're so deep in the weeds it's like asking a fish what they think about water (and to clarify: I'm absolutely not meaning this in any sort of insulting way)... it's just that when you're communicating to others, you may have to end up moving "back and forth" or "up and down" ... illustrated: https://www.youtube.com/watch?v=3amL4O8BSAg ... stretching things out so you can see the individual threads then putting them back, or giving them a twist and blending in a new topic.
Because of your intimate familiarity with the inner workings, sometimes in your talk you're describing an inner working (ie: there's 206 bones in the human body!) but there's no context about what makes that better, or worse, or how they're conceptually connected with each other.
On the grand scale, what is the IMPACT you want your talk to have? To put words into your mouth: "We're about to go GA at google, which is a big deal."
How do you get there? Where did you start from? To put words into your mouth: "JJ is solving google-scale problems, and there's _demand_ and _support_ for bringing it about." [that's your situation]
Consequences? Actions? => now you have set the scene for your very same technical deep dives on JJ.
1) Google has big problems, JJ is solving lots of them!
2) The consequences of (jj-solving-them) or (suffering-further-with-git) are: ...
3a) The actions that have helped jj forge ahead (better than git) are: ...
3b) The actions that jj reduces suffering compared to git are: ...
4) ...as a result, we're about to go GA
5) The impact is increased community trust, improved internal development capabilities, etc...
...again: it's _mostly_ about rearranging things, and providing a little bit more context so that what you _are_ presenting hits your audience better. (3a and 3b are kindof what your current presentation was all about... just set it up a little more on how those interact with the larger picture)
Situation: You've done a great technical thing, and are being asked to present more and be an advocate for it (and yourself)
Consequences: ...if people don't understand JJ, there will be less adoption, or people that would be well-served by it won't use it, or won't contribute
Action: ...you're taking feedback on presentation skills, will continue your systematic learning and iterative improvement approach to this tech-adjacent skill
Result: Butterflies! Rainbows! 150% increase in JJ contributors and 5000% increase in JJ adoption... world peace imminent! :-P
<3 ... best of luck, and free free to reach out if you'd like to continue the conversation!
If you really want me to explain it for you, and just one issue:
There are way too many words on your slides.
P.S. You should click that link and go through it again. If you still don't get it, try once more.
Adding a false excitement signal to the information is a hindrance to me as a viewer. If you want Tony Robbins then go and see him. If you want an overview of the new product architecture lets keep calm and get on with it.
My view is that if you’re going to talk like a bored robot, then I need a transcript or a paper which is much shorter than a talk. I distinctly remember not going to classes at university because the teachers wouldn’t give me anything beyond reading a book aloud. I just read the book at home.
Now, if you’re able to indicate what’s important and not important, what’s interesting and what isn’t , and why you like it , I’ll be delighted to watch your talk.
I think it’s very difficult to be interested in something new if the presenter doesn’t seem to care about it. This is different from something written , where I expect something dry anyway.
If you can't be passionate, don't make it a presentation. Passionate doesn't need to mean over-the-top, but it means speaking on the topic effectively and in a way that reflects believing there's a reason for these people to sit there and listen to you.
No one is forcing people to do presentations, but once you put people in a situation where they're expected to give you their undivided attention for a block of time, those are very reasonable table stakes.
There's always blog posts, articles, mailing lists, HN posts, etc. if you don't believe there's a strong need for people to set aside time consume your information in the form of a presentation.
To the contrary, pretty much every presentation I've ever given has been one that I would not have done if it were up to me
Please do continue to give bad presentations and insist it's just not in you to do better.
If I want to listen to someone read a slide deck word for word in a monotone voice, I can have an AI do it. I'd much rather read a blog post at that point though.
Yes, lets pretend “make *meaning*” is a meaningful thing to say, when compared to “I'm required to do this” or “I have information to convey”
Getting rid of the staging area and allowing conflicts are the biggest wins for me day-to-day. No more stashing/popping or littering my workspace with WIP commits. It's so easy to whip up a change, send it for review, then ping-pong between writing new code on top of the change and making reviewer-requested edits further down the stack.
Lots of other opinions in that thread too.
You can modify any* commit in `jj` regardless of whether it has commits on top of it at any time. Either by another commit into it, or by directly checking out the commit and editing the source tree. If this creates conflicts with commits on top of it `jj` just records those commits as having conflicts/adds conflict markers without interrupting the workflow.
* Commits pushed to remotes are marked immutable so you have to pass an extra flag to say ignore that and modify them anyways. Which you generally wouldn't want to do.
How does recording the conflict, but not introducing it (if I'm understanding correctly), ... how does this affect my build/ci workflow?
Nothing until you pull and rebase B on top of C (two distinct steps). Once B is on top of C, when B is checked out there will be conflict markers in the source tree that will presumably break your build until you resolve the conflict (unless the conflict is in README or something).
My CI workflow has always been on top of a git based forge. As far as the forge is concerned jj is git and absolutely nothing changes with regards to that.
Let's remove the merge conflict and keep the commits in alphabetical order
B pushes a breaking change, I push a commit to C without knowing.
Are my builds and PRs now at the mercy of changes and events outside of my control?
(my hunch is that there are a bunch of confusing situations in jj like git, and that being different enough will cause user churn and people will stick with the tool they already understand the quirks of)
> iiuc jj uses stacked commits instead of branches
Locally jj doesn't really use branches, you can just create a commit on top of any other commit without creating a branch. It does represent branches (it calls them "bookmarks" for whatever reason) and pushing is pushing a bookmark to a git-branch on the remote.
> Are my builds and PRs now at the mercy of changes and events outside of my control?
I don't believe there's any circumstance where your work is silently rebased on top of other work, or anything else that fits this description.
Since jj does not have branches, it sounds like we are forced into the rebase environment?
With git, I can push my changes without a force, regardless of what the work I build on does
I think jj's biggest challenge to adoption or replacing git is not technical, it's that it requires people changing how they think about and perform a very central act of their non-coding activities. CUE suffers from this as well. The biggest pushback I hear is about being able to wrap their heads around it. Devs seem to be largely burnt out on tooling changes right now, we left that hype cycle as the ai/agent cycle was emerging
> I don't believe there's any circumstance where your work is silently rebased on top of other work, or anything else that fits this description.
This sounds like merge conflicts are "shifted-left"? Today we see merge conflicts when a PR is opened and devs fix as needed. With jj it sounds like they couldn't push until the merge fix is resolved. Many times it's not important to deal with that straight away and the dev can continue to get their task done, see builds and results for their changes, etc...
Is this "shift-left" of conflict resolution an accurate way to describe jj's approach / philosophy?
No, I tend to use rebase by default (because I like linear history) so its the language I use but it's equally valid in both git and jj to merge via merge commits instead of rebases.
While JJ doesn't have a concept it calls branches, it has all the same semantic power of branches. The difference here is just that git insists on each leaf commit in the source control tree being tagged with a name it calls a branch, jj is perfectly happy to have leaves in the source control tree where you haven't given them a branch-name.
> This sounds like merge conflicts are "shifted-left"? Today we see merge conflicts when a PR is opened and devs fix as needed. With jj it sounds like they couldn't push until the merge fix is resolved. Many times it's not important to deal with that straight away and the dev can continue to get their task done, see builds and results for their changes, etc...
The behaviour here is the exact same between git and jj. If both you and a coworker push to the same remote branch you have to handle conflicts before pushing with either VCS. If both you and a coworker push to different remote branches and then you submit the change through a pull request you see conflicts when you try to merge the branches (or a reasonable forge like github will test merging behind the scenes and surface it early).
> Is this "shift-left" of conflict resolution an accurate way to describe jj's approach / philosophy?
No. jj never shifts conflict resolution left. JJ does sometimes shift conflicts right, allowing you to defer fixing the conflict until later.
If I amend a commit, all children are rebased automatically.
Yes, jj very much supports this workflow. It's not a single feature, though:
- `jj absorb` automatically guesses what patches in your stack your changes should go to and puts them there, leaving uncertain ones behind. Combine this with `jj undo`, and you can first try an absorb and then immediately undo it if it gets it wrong. - `jj squash --interactive --into X` (aka `jj squash -i -t X`) is the more controlled option, where you can select the specific files/hunks/lines to amend X with. The auto-rebasing then adjusts the rest of the stack to match. If it creates conflicts, you can either undo, fix them now, or fix them later. - if you want to experiment with reordering your stack (or more generally, reorganizing your DAG), you can do so without it making a bigger mess than is absolutely necessary. That's not just because of undo. If you try to rebase a patch too early and it produces tons of conflicts, you can rebase it back and the conflicts will be gone (assuming you didn't have some in the first place, but if you did you'll be back to the same ones). You can try different places within the stack and see what'll work best. - As an expansion of the above, you can also split off pieces of one diff and insert it or squash it anywhere in the stack (eg `jj split --revision X --insert-after Y` aka `jj split -r X -A Y`, or `jj squash --interactive --from X --into Y` aka `jj squash -i -f X -t Y`). You don't need to be "at" X to rip off pieces and put them elsewhere, you can do it anytime.
In summary, the full answer is "hell yeah!"
Note that this doesn't magically eliminate all problems that arise from collaboration. You can't push your stack somewhere and have other people start working off of it and modifying it while modifying it yourself locally. Or rather, you can, but you'll end up with a mess. Perhaps much less of a mess than eg git, because jj tracks evolving changes and not just commits and so you might be able to have some idea of what's going on once you've pulled the conflicting mutations back into your local repo. But generally speaking, you still have to be disciplined about changing anything that other people can see and possibly depend upon. (jj can help by automatically making such things immutable once you've made them visible to others, but that too can be a bit confusing and require setup specific to your situation.) This comes up a lot in code review, and there are solutions that handle parts of the problem with varying degrees of success, but I've already rambled quite a bit.
> `jj absorb`
git absorb exists.
The absorb command originated in mercurial, which is where I've used it most. With `hg absorb`, I'd only use it when I was fairly sure that it would do the right thing, and I imagine it'd be the same with git. With jj, having `jj undo` as a fallback means I can use it just to see what it does and if it gets something wrong, undo it and do what I want in a different way. (But not that different -- `jj squash -i --into X` means I can do the same thing as it was doing manually.)
SVN -> Git -> jj
I still remember feeling like a badass using Git-SVN on my SVN-based team, and being the only guy who could actually correct bad merges and restore lost data without having to plead to our SVN admin.
And now I'm feeling like a badass using jj on my Git-based team :)
Changing git hosts happens less frequently than changing clouds, which is infrequent. Changing VCS tools is even less frequent than either of those
Hooks are a bigger change, though, for sure.
At the same time, not everyone requires those features. All I mean to say is, the degree of support is varied out of the things mentioned, not just "no support for any of them."
It's still pre-1.0 software. We'll get there :)
I'm going to take the docs for what they say about support over an HN comment
Why do people believe it's going to replace git if it won't do basic things we need. Why is it hard for jj to create a tag?
It’ll get there! Early days.
jj claims there are these really bad problems with git, which is not my experience. Git is not on my list of pains in dev work
This is a Google-internal only GA. JJ is available externally just fine. Google is mainly a linux-dev shop, with all other platforms being second-class citizens.
The main exceptions to this are devs who work on iOS or macOS software, who will sometimes do local builds on their physical machine. They would benefit from jj support, but there are more hoops to jump through, and the jj port will most likely be less about running on macOS and more about jj supporting the weird ways in which source is accessed.
... but Google solves the "A Linux fleet requires investment to maintain" problem by investing. They maintain their own in-house distro.
Not really, it is just a well known outside distro plus internal CI servers to make sure that newly updated packages don't break things. Also some internal tools, of course.
It's downstream of Ubuntu (unless that's changed) but it's tweaked in the ways you've noted (trying to remember if they also maintain their own package mirrors or if they trust apt to fetch from public repositories; that's a detail I no longer recall).
In 2018, Google replaced Goobuntu with gLinux, a Linux distribution based on Debian Testing
Well FreeBSD exists, just look at Netflix
edit: apparently Contributor License Agreement
They don't want to accidentally bring in GPL-3 or private code into an Apache licensed project, and my understanding is this is a self-certifying statement that you won't and have full rights to make the contributions