[HN Gopher] Jujutsu - A Git-compatible DVCS that is both simple ...
       ___________________________________________________________________
        
       Jujutsu - A Git-compatible DVCS that is both simple and powerful
        
       Author : rolisz
       Score  : 283 points
       Date   : 2022-02-19 17:17 UTC (5 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | habitue wrote:
       | I like that this is not "a dvcs written in rust" but rather "a
       | dvcs with these awesome improvements over git." which
       | incidentally happens to be written in rust because of course it's
       | the right language for this.
        
       | kazinator wrote:
       | In git you can reorder any sequence of commits without any
       | conflicts. Howwever, there is no nice "porcelain" for it.
       | 
       | The basis for it is the _read-tree_ command.
       | 
       | In git, every commit is a snapshot and not a delta. (Repeat that
       | three times.)
       | 
       | Any arbitrary snapshots of files can be arranged into a git
       | history. They don't even have to be related. We could take a
       | tarball of GCC, and make that the first commit. Then a tarball of
       | Clang and make that the second commit.
       | 
       | The _read-tree_ command will read any commit 's state into the
       | index, and from there you can make a commit out of it.
       | 
       | To reorder some N commits you're looking at, save all of their
       | hashes somewhere, and then rewind the branch: git reset --hard
       | HEAD~N. Then use git read-tree to read those hashes in whatever
       | order you want, committing them one by one. To reuse their commit
       | messages you have to use commit -C <hash>, though most them
       | likely don't make any sense, because the text of commit messages
       | usually talks about changes between a commit and its main parent.
       | 
       | What will happen is that your history now as N commits which
       | represent the same _states_ as the N you had there before, in a
       | different order. For instance if you reverse them, then the
       | oldest commit has all the features (is the same code baseline) as
       | what the newest HEAD was previously. And then the subsequent
       | child commits basically remove all the changes that were made, so
       | the latest now looks like what the N-th looked like.
       | 
       | How I sometimes use this:
       | 
       | Suppose I made a fairly complex change that I would like to break
       | up so that it is presented as a sequence of two or more states of
       | the code.
       | 
       | There are cases when the following workflow is easy: first I make
       | a commit out of the changes. One commit with everything. That
       | commit is what I want the final state to look like. Then I revert
       | some of the changes to produce the state before that state. If I
       | have mostly been adding things, this might consist of just
       | deleting them. Or I can do a git reset --patch HEAD^ to
       | selectively revert. I commit this penultimate state. Then repeat
       | the process: revert some more changes from that one, commit and
       | so on, as many times as I see fit.
       | 
       | So what I end up with is the states of the code I want to present
       | as a history, but exactly in the wrong order. Using "git rebase
       | -i" doesn't work nicely; there are ugly conflicts, and some of
       | them have to be encountered twice. Here is where the git read-
       | tree trick comes into play: I simply reverse those exact states
       | of the code to put them in the right order on the branch. After
       | that I might do a rebase -i just to reword the commit messages to
       | frame the code states from the POV of being changes from their
       | parents.
       | 
       | You might think: why not just "git commit --patch" from the
       | original working state to produce commits in order. The reason is
       | that doesn't always make sense. For that you had to remember to
       | make the commit as you were working. Because say you refactored
       | something and then made a change. You can't easily do a "git
       | commit --patch" which separates the refactoring from the change.
       | Sure, if you do the refactoring and then a commit, and then make
       | the change, you are good. But suppose you've conflated them
       | already; now what? You can commit everything and then back out
       | the changes that were done on top of the refactoring, and commit
       | that. Then reorder the two states.
        
         | mastazi wrote:
         | > In git, every commit is a snapshot and not a delta.
         | 
         | I know this, but also I cannot reconcile this whit what happens
         | when you cherry-pick a commit from another branch. I'm confused
         | because cherry-pick really seems to be taking out the delta not
         | the snapshot.
         | 
         | I'm thinking that cherry-pick takes that commit and makes a
         | diff with its parent and then that's what you get when you call
         | it. Is it how it works behind the scenes?
         | 
         | I'm also thinking that the fact that each commit has at least
         | one parent means that, conceptually, we can use it as if it was
         | a delta (at least in the case of commit with one parent only),
         | if you get what I mean.
         | 
         | EDIT: I'm not familiar with the internals of Git, just a user.
         | Commenting out of curiosity.
        
           | kazinator wrote:
           | When you cherry-pick a commit from another branch, it's not
           | doing anything like a read-tree to make your current work
           | look like that commit's snapshot state. It's doing something
           | like three-way merge between that commit, your baseline and a
           | common ancestor (I'm guessing: the same one that would be
           | identified by git merge-base <hash0> <hash1>.) That's why
           | cherry-pick identifies conflicts.
           | 
           | A cherry-pick deos not just do a diff with its parent 0 and
           | then patch it onto your work. In many cases, that wouldn't
           | work because that's not a three-way-merge, but a two-way
           | merge, which has disadvantages.
           | 
           | However: there may be situations when the commits are so
           | distant, it might make sense just to turn that one into a
           | patch and work the patch onto your baseline. Even if that
           | needs manual work, it can be simpler. You will only get
           | conflicts (patch hunk rejects in that case) that are relevant
           | to that change. I've had lots of experience working with
           | patch stacks (both before and after Quilt was introduced to
           | make that a bit easier) so I'm comfortable migrating patches
           | from one code base to another without a three-way-diff
           | process within version control.
        
             | mastazi wrote:
             | Yes, I agree about distant commits and turning it into a
             | patch.
             | 
             | Thank you for explaining the three-way merge between
             | baseline, commit and common ancestor, makes sense.
        
       | em-bee wrote:
       | jujutsu looks interesting, but one thing that i find missing from
       | git is historical branch tracking. once two branches are merged,
       | git does not tell me which series of commits used to belong to
       | which branch. i can't check out main from two weeks ago if a
       | merge happened in the meantime because that information is lost.
       | 
       | i fear to add such a feature additional information would need to
       | be stored in the git repo itself which would require a change to
       | git
        
       | mberning wrote:
       | Congrats and good luck. Git desperately needs a radically
       | simplified and radically consistent set of porcelain interfaces.
        
       | cryptonector wrote:
       | > It combines features from Git (data model, speed), Mercurial
       | (anonymous branching, simple CLI free from "the index", revsets,
       | powerful history-rewriting), and Pijul/Darcs (first-class
       | conflicts), with features not found in either of them (working-
       | copy-as-a-commit, undo functionality, automatic rebase, safe
       | replication via rsync, Dropbox, or distributed file system).
       | 
       | You lost me at "free from the index". The index is one of the
       | most important parts of Git that makes _my_ life easier.
       | Opinionated DVCS UIs make my life harder -- all of them.
       | 
       | > The working copy is automatically committed
       | 
       | Right, so, the reason the index is powerful is that I get to do
       | `git add -e`, `git commit`, and repeat until I'm done or ready to
       | throw remaining changes away. I very much want the index /
       | workspace distinction.
       | 
       | > Automatic rebase
       | 
       | > Comprehensive support for rewriting history
       | 
       | This is very welcome. At the very least this confirms something
       | important: the fallacious argument that "rebase rewrites history,
       | so it's eeeevil" is finally dead.
        
         | throw0101a wrote:
         | > _You lost me at "free from the index". The index is one of
         | the most important parts of Git that makes my life easier.
         | Opinionated DVCS UIs make my life harder -- all of them._
         | 
         | Mercurial has an 'index' / staging area, but not exposed by
         | default. You can access it with some extra CLI options, but
         | there is an optional idea that may be 'better' and worth
         | looking into:
         | 
         | > _If you need the index, you can gain its behavior (with many
         | additional options) with mercurial queues [1] (MQ).[2] Simple
         | addition of changes to the index can be imitated by just
         | building up a commit with hg commit --amend (optionally with
         | --secret, see phases [3])._
         | 
         | * https://www.mercurial-
         | scm.org/wiki/GitConcepts#Git.27s_stagi...
         | 
         | [1] is "A Git User's Guide to Mercurial Queues"
         | 
         | * https://stevelosh.com/blog/2010/08/a-git-users-guide-to-
         | merc...
         | 
         | MQs (optionally) expand on the idea of only a single staging
         | area:
         | 
         | > _This single "intermediate" area is where git stops. For many
         | workflows it's enough, but if you want more power MQ has you
         | covered._
         | 
         | > _MQ is called Mercurial Queues for a reason. You can have
         | more than one patch in your queue, which means you can have
         | multiple "intermediate" areas if you need them._
         | 
         | If you only want to use one queue/index then that's fine too.
        
           | cryptonector wrote:
           | I find Mercurial very difficult to use. I find Git much
           | easier.
        
             | andrewshadura wrote:
             | It's just because you've been using Git for too long.
             | Mercurial is much easier to use if you're not exposed to
             | Git.
        
         | [deleted]
        
         | yjftsjthsd-h wrote:
         | If you can rewrite the history that actually got committed, do
         | you really need a temporary pre-commit staging area?
        
           | bonzini wrote:
           | The index is mostly useful to me to split a commit in
           | multiple ones. You do that with a sequence of "git add -p"
           | and "git commit" commands. I am interested in how to do this
           | with jj, because otherwise it looks like a very interesting
           | tool.
        
             | erik_seaberg wrote:
             | I prefer "git stash -p" to exclude unfinished changes,
             | because if I build up a partial commit in the index there's
             | no way to test it.
        
               | cryptonector wrote:
               | I do that later. I do `git rebase -i` and add `exec`
               | lines to build each commit that must build.
        
             | cryptonector wrote:
             | `git add -e` is infinitely better.
        
             | andrewshadura wrote:
             | Try git-crecord.
        
             | masklinn wrote:
             | > You do that with a sequence of "git add -p" and "git
             | commit" commands.
             | 
             | You can do that with git commit -p.
        
               | bonzini wrote:
               | True but there's usually a "git diff --staged" in the
               | middle to check what I am committing.
        
               | cryptonector wrote:
               | Exactly!
        
             | martinvonz wrote:
             | > I am interested in how to do this with jj
             | 
             | `jj split -r <commit>`, where `<commit>` may be the working
             | copy commit (which is the default). See
             | https://github.com/martinvonz/jj/blob/main/docs/git-
             | comparis... for more examples.
        
               | detaro wrote:
               | so just for understanding: repeated `git add -p` followed
               | by a `git commit` turns into repeated `jj split; jj
               | squash`, since you create a commit each time?
        
               | martinvonz wrote:
               | That would work, yes, but there's also `jj squash -i` to
               | move part of the child commit into the parent. There's
               | also the more generic `jj move` command for moving part
               | of any commit into any other commit (ancestor,
               | descendant, sibling), so you `jj squash -i` is equivalent
               | to `jj move -i --from @ --to @-` (where `@` is syntax for
               | the working copy commit and `@-` is syntax for its
               | parents).
        
           | cryptonector wrote:
           | Yes, I do. I often do this (usually in detached HEAD mode!):
           | : ; $EDITOR some-file ...       : ; $build       : ; git add
           | -e # take a few chunks, maybe change them       : ; git diff
           | --staged; git status -uno       : ; # lather, rinse, repeat
           | : ; git commit -m '...' -ev       : ;        : ; git status
           | -uno; git diff       : ; git add -e # ..       : ; # lather,
           | rinse, repeat until happy       : ;        : ; git fetch
           | origin       : ; git rebase origin/master       : ; # fix any
           | conflicts       : ;        : ; # continue until all bug fix /
           | feature       : ; # activity for this issue is complete
           | : ;       : ; # review my changes:       : ; git log --patch
           | origin/master..       : ;       : ; # if I have to clean my
           | history a bit:       : ; git rebase -i origin/master       :
           | ; # re-order commits, `edit` commits, `drop`       : ; #
           | commits as needed       : ; $build       : ; # fix remaining
           | issues...       : ;        : ; # finally ready to push:
           | : ; git push myclone HEAD:refs/heads/this-thing       : ;
           | : ; # open a PR
           | 
           | Repeat as needed to deal with code review comments until done
           | and integrated.
        
             | c-smile wrote:
             | Are you human?
             | 
             | > detached HEAD mode
             | 
             | Ah, I see, not anymore...
        
         | indygreg2 wrote:
         | The index is a power user feature. Its forced presence in Git
         | effectively constitutes a usability barrier for new users.
         | After all, a VCS is effectively a glorified abstraction for
         | "save a file." Any barrier imposed between changing a file and
         | committing it can get in the way and confuse people. The Git
         | index does this.
         | 
         | Furthermore, the index is effectively a pseudo commit without a
         | commit message. Any workflow using the index can be implemented
         | in terms of actual commits itself.
         | 
         | I think because Git doesn't have strong usability in general
         | and especially around history rewriting, many Git users feel
         | that the index or an index equivalent is somehow a required
         | feature of a VCS because Git's shortcomings give that illusion.
         | However, if you use a VCS with better history rewriting (such
         | as Mercurial with evolve), you'll likely come around to my
         | opinion that the index can be jettisoned without meaningful
         | loss of functionality or productivity.
        
           | cryptonector wrote:
           | I don't deny that the index is a power feature and that it's
           | difficult to explain it to newbies.
           | 
           | Perhaps there's room for new UIs.
           | 
           | All I'm saying is I need this power. And it has to be easy to
           | reach for it.
        
         | martinvonz wrote:
         | > You lost me at "free from the index".
         | 
         | If you click the link that text points you to (i.e.
         | https://github.com/martinvonz/jj/blob/main/docs/git-
         | comparis...), there's an explanation there for how to achieve
         | the same workflows. I get that it's _different_ , but I don't
         | think it's worse. I consider myself a (former) git power user
         | (I think I have ~90 patches in Git itself) and I've never
         | missed the index since I switched to Mercurial ~7 years ago.
         | 
         | > This is very welcome.
         | 
         | Thanks :)
        
           | omegalulw wrote:
           | > With Jujutsu, you'd instead use jj split to split the
           | working copy commit into two commits.
           | 
           | This is more confusing? Often times when debugging/writing a
           | fix I would have extraneous code that I wouldn't want to
           | commit. With an index I'm always sure if what I commit, but
           | with this workflow you have to keep track of such stuff all
           | the time and if you forget that stuff makes it in?
           | 
           | Not to mention that another benefit of an index is being able
           | to change commits and git replaying your working diff.
        
             | em-bee wrote:
             | yeah, i feel this is going to bother me, or at least be
             | difficult to get used to.
             | 
             | i often have temporary files that i do not want to commit,
             | nor do i want to add them to .gitignore (because i want to
             | commit them later)
             | 
             | but then, i'll have to spend some time using jj split. if
             | it is powerful enough then maybe the end result is just
             | that those files only live in the last commit.
             | 
             | also, what happens on push? i'd never ever want the working
             | copy to be pushed to the remote repo. i could not find
             | anything in the documentation about that.
             | 
             | (according to the answer here:
             | https://news.ycombinator.com/item?id=30399554 the working
             | copy is not supposed to be pushed)
        
           | cryptonector wrote:
           | You cover `git add -p`, but I want `git add -e`.
           | 
           | Also, I often rebase and `edit` commits to split them or undo
           | parts of them.
           | 
           | Rebase and all this is all about making commits that have
           | just the right content, and keeping history clean and linear.
           | The tools have to make this possible and easy.
           | 
           | I get that git feels... barebones for this. You really have
           | to understand what you're doing when using git like I do, so
           | I get that it's not very accessible.
           | 
           | Better UIs are great, but on the other hand, we need to be
           | able to get down to the low level.
           | 
           | IMO.
        
             | martinvonz wrote:
             | > You cover `git add -p`, but I want `git add -e`.
             | 
             | Interesting. I don't think I've heard anyone use `git add
             | -e` before. It should be easy to add that feature, but it
             | would be very low priority since so few users seem to like
             | to manually edit patches.
             | 
             | > Also, I often rebase and `edit` commits to split them or
             | undo parts of them.
             | 
             | You can do that by checking out the commit, then `jj
             | squash/amend` (aliases) and all descendants will be
             | automatically rebased on top, and branches pointing to them
             | will be updated too. There's also `jj edit` for editing the
             | changes in a commit without updating to it. And there's `jj
             | split` for splitting a commit (without needing to update to
             | it).
             | 
             | > Rebase and all this is all about making commits that have
             | just the right content, and keeping history clean and
             | linear. The tools have to make this possible and easy.
             | 
             | Yes, that's definitely a goal. I think Jujutsu does a much
             | better job at that than Git does. Did you read
             | https://github.com/martinvonz/jj#comprehensive-support-
             | for-r...?
        
           | alwillis wrote:
           | Something that's backend compatible with Git but uses some of
           | Mercurial's sensibilities?
           | 
           | Sign me up!
        
         | dilap wrote:
         | I like and use the index in git too, but I wouldn't be so quick
         | to dismiss other models that might end up solving the same use
         | cases in a different way...
         | 
         | From the README, it looks like there's robust support for
         | editing and splitting commits. So maybe in practice the flow is
         | similar to using the index, with the added the added benefit
         | that your work is backed via commits along the way, and the
         | simplicity of not having the index as an extra concept.
         | 
         | In general when exvaluating X from the perspective of Y, we
         | will immediately see the thing's about Y we like that X lacks;
         | it takes more time to see if perhaps in the fuller context of X
         | those things are not necessary.
        
         | masklinn wrote:
         | > Right, so, the reason the index is powerful is that I get to
         | do `git add -e`, `git commit`, and repeat until I'm done or
         | ready to throw remaining changes away.
         | 
         | You don't need the index for that. In fact I'd say it gets in
         | the way because the presence of the one means less pressure on
         | improving the ability to edit commits: while it's easy to add
         | stuff to HEAD it's much more painful to remove content from it.
         | 
         | If that is solved, then the value of the index drops
         | precipitously, because you can create a commit with a purpose
         | and select its content instead of having to do it the other way
         | around then forgetting what change you were trying to craft.
        
       | [deleted]
        
       | jjthrowaway wrote:
       | It would be nice if this were in nixpkgs, it's a pain to manage
       | all the different language environments and it would save me from
       | trying to get it to compile.
       | 
       | Right now                   error[E0554]: `#![feature]` may not
       | be used on the stable release channel       -->
       | lib/src/lib.rs:15:12        |
       | 
       | 15 | #![feature(assert_matches)] |
        
         | gmfawcett wrote:
         | If you get it working, please share a flake. :)
        
       | kuboble wrote:
       | 1) What are the advantages of using native backend as compared to
       | git?
       | 
       | 2) Are there any potential issues one has to be aware of when
       | using jj contributing to git repository?
       | 
       | I remember when I was the only team member using git-svn plugin
       | my coworkers were confused when I svn-committed many commits at
       | once with some of them breaking the time order of the svn history
       | (as git-svn commits in svn were recorded with git timestamp and
       | not the actual svn- commit timestamps)
        
         | martinvonz wrote:
         | > 1) What are the advantages of using native backend as
         | compared to git?
         | 
         | Very few. The disadvantages are generally much larger. The main
         | advantage is that you won't run into a (harmless) race that
         | happens once in a while with the git backend
         | (https://github.com/martinvonz/jj/issues/27). Disadvantages
         | include not being able to interact with git repo and
         | performance problems (both size and speed).
         | 
         | I should add a note about this to the README.
         | 
         | The backend exists mostly to prove that it's possible and to
         | make sure that the backend API doesn't become tied to Git.
         | 
         | > 2) Are there any potential issues one has to be aware of when
         | using jj contributing to git repository?
         | 
         | The main one is that you should avoid pushing commits with
         | conflicts. It won't corrupt the remote repo, but git clients
         | won't know what to do with the conflicted files. The fix is to
         | fix the conflict and force push the conflict-free commit.
         | 
         | I'll file a bug to prevent pushing commits with conflicts.
        
       | swagonomixxx wrote:
       | > A Git-compatible DVCS that is both simple and powerful
       | 
       | We all know the dig here - Git is not simple.
       | 
       | Like many tools, Git has evolved significantly over the years.
       | Git today was not like Git 10 years ago.
       | 
       | Also, like many replacements to existing tools and software, they
       | always start out simple and beautiful. Then they grow in
       | complexity to serve the domain. The reason Git is complicated -
       | not "simple" - is mostly because version control _is_ complex.
       | 
       | I also don't agree that Git is hard to use. I feel it is an odd
       | goal to try to make everything - even tools that experts use -
       | simple to use, when they are fundamentally not simple. I feel
       | like Git is sufficiently complex - no more than it needs to be
       | and certainly not less.
        
         | hinkley wrote:
         | I am by all accounts the SME on git at my company. I often am
         | the VCS expert at my company. I don't like using tools I don't
         | understand, and my brain is pretty good at handling problems
         | that look like graph theory.
         | 
         | After using git for 6 years git still terrifies me. After 9
         | months of svn I performed open heart surgery to remove a 1GB
         | zip file that some dummy merged before anyone thought to stop
         | him. It was at least 18 months before I tried something similar
         | with git and I made copies of my copies to make sure I didn't
         | fuck it up. And I still almost needed a do-over.
         | 
         | The level of dread I have using git is pretty close to how I
         | feel when using a newly sharpened chef's knife -
         | hypervigilance. And that feeling gets stronger when I hand that
         | knife to someone else. Be very careful, that's super sharp...
         | hold still, I'll get you a bandaid. Now you get a mini lecture
         | on how to hold a knife without cutting yourself next time.
        
         | martinvonz wrote:
         | > I feel like Git is sufficiently complex - no more than it
         | needs to be and certainly not less.
         | 
         | Perhaps the biggest mistake (IMO) was to expose the index to
         | the user. I happened to just watch
         | https://www.youtube.com/watch?v=31XZYMjg93o (by the person
         | behind Gitless). They explain the issues well there.
        
           | hinkley wrote:
           | > They told me offline use was a big advantage of git over
           | svn. But, how are you supposed to use git without Google?
           | 
           | Shots fired.
        
           | KerrAvon wrote:
           | I haven't watched that video, but I agree -- the index is one
           | of the biggest hurdles to making git easy to understand and
           | use for newcomers. It's not hard to explain the fundamental
           | model of how git works -- it's hard to explain the UI, and
           | it's hard to explain the index. If you remove the index,
           | you're only working with commits, and that simplifies the UI
           | enormously.
        
           | hinkley wrote:
           | I'm gonna watch this video. What's been bugging me for a long
           | time, as someone who didn't quite get to see all of the
           | supposed ugliness of Subversion (which by description alone
           | sounds an awful lot like the rerere situation with Git, which
           | I have).
           | 
           | It really feels to me like a commit identifier should be the
           | combination of a monotonically increasing number and a hash
           | of the content, rather than an either-or. If I merge or
           | rebase branches in git, I lose the index, just as I would in
           | subversion. But at least in svn I have some notion of how far
           | back commit 12345 is in the tree. ac4def2 could be HEAD or
           | four years ago.
        
       | dark-star wrote:
       | git is already very simple, at least for the 95% of use-cases
       | that I need. add, commit, checkout, push, pull.... maybe a branch
       | and merge here and there, but that's it.
       | 
       | Of course I cannot remember how exactly the "git rebase" command
       | works and have to look it up every time, same as all those
       | switches to the "simpler" commands.
       | 
       | I guess it all depends on what you need. Python looks really
       | complicated too, if you start by browsing the function and class
       | reference. But for someone starting to learn programming, it is
       | apparently pretty easy (or so I've heard)
        
       | freedomben wrote:
       | This looks like an interesting project, and I'm glad that people
       | are still thinking about how to improve on version control.
       | 
       | That said, building a version control system seems like a problem
       | similar to a social network: the network affect causes an
       | enormous amount of friction. i.e. most people don't want to use
       | it until other people are using it. A vicious cycle.
       | 
       | The fact that it's compatible with git as a backend is really
       | great though, and is probably the key to driving adoption.
       | However I have several immediate thoughts that come to mind that
       | cause me hesitancy. Answers in the README.md would be super
       | helpful for marketing to me (and deep apology if it's there and I
       | missed it):
       | 
       | 1. How does it look to _others_ working on the repo using just
       | git? For example,  "when the working copy is automatically
       | committed," where does it go? is there a remote branch that
       | someone could see if they `git fetch` while I'm working? I often
       | put all sorts of things in the code that I don't want to have
       | committed, ranging from harmless (a bunch of personal comments or
       | `IO.puts()`), to very important (API keys and such that I'm
       | testing with. I always move them to env vars before committing
       | but for first-pass testing to prove the concept I "hardcode" them
       | at first).[1]
       | 
       | 2. Similar to "how does it look to others," what sort of burden
       | does "all operations you perform in the repo are recorded, along
       | with a snapshot of the repo state after the operation" put on the
       | git backend? If I'm hacking on an ffmpeg script and I
       | (temporarily) copy a 4GB mp4 file into the working directory so I
       | can easily run `./mycode video.mp4`, does that whole thing get
       | committed, potentially every time it changes? That could easily
       | turn into a 40GB set of changes.[1]
       | 
       | 3. Do you _have_ to use the jj backend to get all the feature?
       | For example, with a git backend could you get the two things
       | mentioned above and also  "Conflicts can be recorded in commits"
       | as well?
       | 
       | A quick section in the README.md about which features require the
       | jj backend instead of git would be super helpful, and if written
       | well could answer all of the questions above.
       | 
       | To sum up my comment in a TL;DR: To really sell me on a project
       | like this it has to work with git, and being able to quickly tell
       | which features I can use _with git_ , would make this
       | substantially more interesting to me.
       | 
       | [1]: Related: https://xkcd.com/1172/
        
         | martinvonz wrote:
         | > For example, "when the working copy is automatically
         | committed," where does it go?
         | 
         | It becomes a regular git commit with a git ref called something
         | like `refs/jj/keep/9f1a0fb0-a0aa-4a4b-922f-d6d48687996a`
         | pointing to it (to prevent GC). It won't get fetched or pushed
         | by default, except with `--mirror`, I think.
         | 
         | > If I'm hacking on an ffmpeg script and I (temporarily) copy a
         | 4GB mp4 file into the working directory so I can easily run
         | `./mycode video.mp4`
         | 
         | Yes! You'll have to more diligent about keeping your .gitignore
         | (or .git/info/exclude, etc) file updated. I plan to add
         | commands for fixing such mistakes by forgetting the commit.
         | 
         | > Do you have to use the jj backend to get all the feature?
         | 
         | Nope, conflicts work with the git backend as well.
         | https://github.com/martinvonz/jj/blob/main/docs/git-compatib...
         | has some info.
         | 
         | > To sum up my comment in a TL;DR: To really sell me on a
         | project like this it has to work with git, and being able to
         | quickly tell which features I can use with git, would make this
         | substantially more interesting to me.
         | 
         | Makes sense. Thanks for the suggestion! I'll put it on my TODO
         | list.
        
           | freedomben wrote:
           | Awesome, thanks for the answers and thanks for sharing your
           | project! I'll give it a try :-)
        
       | skrebbel wrote:
       | Wow, this scratches a lot of my itches about Git. I teach a Git
       | course at my alma mater, and the things that confuses people the
       | most (the index, how to undo mistakes etc etc) all seem addressed
       | head-on. At first glance, this seems substantially easier to
       | teach than Git.
       | 
       | The Git compat seems like a great idea for this to really take
       | off. My team is totally PR based though so if/when doing (Git
       | compatible) feature branches lands in JJ I'm excited to switch.
        
         | wcarss wrote:
         | > My team is totally PR based though so if/when doing (Git
         | compatible) feature branches lands in JJ I'm excited to switch.
         | 
         | I'm trying to find the part of the docs that refers to this
         | functionality as missing but I can't -- does jj not have the
         | ability to create, update, pull from, merge branches, etc?
        
           | intrepidhero wrote:
           | > For example, pull-request workflows currently require too
           | many manual steps.
           | 
           | Supported but not great I guess?
        
         | stouset wrote:
         | While I agree that git could use a rethink from a user tooling
         | perspective, I _really_ appreciate the existence of the index.
         | I'm not tied necessarily to this specific implementation of it,
         | but having a staging area where chunks are added piecemeal is
         | an enormous benefit.
         | 
         | I honestly wish git forced `-p` for operations that support it.
         | I've worked on too many teams where people would just commit
         | everything in their working directory, and it would inevitably
         | make reviewing their PRs a nightmare. Particularly with times
         | where changes were accidentally committed wholesale that
         | shouldn't have been part of that set of changes.
        
           | skrebbel wrote:
           | I'm not opposed to carefully crafting a good commit, I'm
           | opposed to a state-heavy, badly named, inconsistent feature
           | to do it. And if you use any decent git UI (including -p on
           | the CLI), you don't really need it to be that persistent very
           | often. It could just be a list of chunks to select in the
           | "make commit" window, which is of course exactly how most git
           | UIs "make commit" window looks. It's a single step then, no
           | intermediary persistent state (with three names).
           | 
           | JJ seems to workaround this in the other direction, by making
           | the concept of commits and rebases much more lightweight,
           | which i think is a refreshing enough take that I'd like to
           | try it.
        
           | Hendrikto wrote:
           | > I've worked on too many teams where people would just
           | commit everything in their working directory, and it would
           | inevitably make reviewing their PRs a nightmare.
           | 
           | And they always claim to review and clean their commits
           | before pushing, or at least before merging, but never do.
        
           | pjc50 wrote:
           | > just commit everything in their working directory
           | 
           | But that's what they've tested. I've had far more problems in
           | the other direction, where the commit doesn't contain the
           | complete set of things that it's supposed to but because all
           | the tooling - every single IDE and compiler - is looking at
           | the working directory not the index, I've missed something.
           | 
           | The index is _definitely_ confusing for new users and users
           | of other VCS.
           | 
           | > having a staging area where chunks are added piecemeal is
           | an enormous benefit.
           | 
           | It would be quite fun if we could have hierarchical commits,
           | so I could add bits to a commit without having to
           | squash/amend. Then you'd see the top-level work item as a
           | "commit" and the individual changes as "subcommits".
        
             | stouset wrote:
             | Like I said, I'm not sold on git's specific implementation.
             | But breaking things into smaller, focused commits is--in my
             | experience--a hallmark of good development practice.
             | 
             | There should absolutely be better tooling around it, so
             | that these piecemeal commits can be tested in isolation
             | from one another. That's a far better approach than just
             | throwing up our hands and committing everything in the
             | working tree, even if half of it has nothing to do with
             | what's intended.
        
             | throw0101a wrote:
             | > _It would be quite fun if we could have hierarchical
             | commits, so I could add bits to a commit without having to
             | squash /amend. Then you'd see the top-level work item as a
             | "commit" and the individual changes as "subcommits"._
             | 
             | Would something like Mercurial's queues be something what
             | you're looking for?
             | 
             | * https://stevelosh.com/blog/2010/08/a-git-users-guide-to-
             | merc...
             | 
             | See especially "...with Two (or More) Patches" onwards.
        
       | hinkley wrote:
       | "Powerful" has become to me a shibboleth for people who are full
       | of it.
       | 
       | I can't recall the last time a coworker who liked things because
       | they were powerful didn't end up being untrustworthy. Even
       | dangerous. It's like nobody remembers the Principle of Least
       | Power.
       | 
       | That said, I will take someone obsessed with "powerful" over
       | "flexible" any day of the week.
        
         | kjeetgill wrote:
         | Hm, I guess for tools like this I always read "powerful" _as_
         | "flexible" - as in: this tools has strictly more
         | power/capabilities making it more flexible. In terms of "dev
         | tool marketing speak" I guess it's the opposite of "robust"
         | meaning: fewer features that are less likely to break on you.
        
           | hinkley wrote:
           | The only flexible tool I use in the real world is the
           | Leatherman, and that's for situations when I don't know what
           | I'll need, or if I'll need it. For every other task I have a
           | tool that is designed (sometimes quite well) for a set of
           | tasks that includes the one at hand (see also Alton Brown, no
           | single-purpose tools).
           | 
           | The Leatherman is part of my EDC, along with an LED
           | flashlight with some respectable lumens so I don't have to
           | use my phone to see in the dark.
           | 
           | In software this is known as the Unix Philosophy, but we
           | violate it quite often, and call those tools 'powerful' or
           | 'flexible'. Everything is a Swiss Army Knife all the time,
           | and we aren't self-aware enough to see how consistently - and
           | sometimes badly - we struggle with this.
           | 
           | But you can't tell an addict they're an addict. They will
           | fight you to the death about how they Don't Have a Problem.
        
       | mdaniel wrote:
       | That's quite impressive, congratulations!
       | 
       | The git comparison docs have:
       | 
       | > Start working on a new change based on the <main> branch -- jj
       | co main
       | 
       | Did you consider the recent git nomenclature change to use
       | "switch" for branch operations, and "co" for file operations? I
       | actually can't tell from so deep in my "git Stockholm syndrome"
       | whether that distinction is really hard on new users or not, but
       | the fact that git expended the energy meant they thought it was
       | meaningful
       | 
       | And, do you have plans on supporting signed commits, either via
       | gpg or the newfound SSH key signing?
       | 
       | I'm super excited to try out the conflict resolution mechanism,
       | because that's a major painpoint for my long-lived PR branches
        
         | martinvonz wrote:
         | Thanks!
         | 
         | > Did you consider the recent git nomenclature change to use
         | "switch" for branch operations, and "co" for file operations?
         | 
         | Actually, isn't "restore" for file operations? My impression
         | was that everyone agrees that `git checkout` does too many
         | different things. In particular, it's both for switching
         | branches and for restoring file content. So they added the new
         | `git switch` and `git restore` with limited scope. I strongly
         | suspect that they would have used `git checkout` for the former
         | if that wasn't already taken by the existing command.
         | 
         | > And, do you have plans on supporting signed commits, either
         | via gpg or the newfound SSH key signing?
         | 
         | No, that's not something I've even started thinking about. I'll
         | have to read up on how it works in Git first. Patches welcome,
         | though :)
         | 
         | > I'm super excited to try out the conflict resolution
         | mechanism, because that's a major painpoint for my long-lived
         | PR branches
         | 
         | You mean so you can continuously rebase them without having to
         | resolve conflicts right away? Yes, that's one of the benefits
         | of first-class conflicts. Another benefit, which took me a long
         | time to realize how useful it is, is the auto-rebase feature.
        
           | mdaniel wrote:
           | > No, that's not something I've even started thinking about.
           | I'll have to read up on how it works in Git first. Patches
           | welcome, though :)
           | 
           | I opened an issue and provided links to the docs, and a link
           | to the current way that git implements it:
           | https://github.com/martinvonz/jj/issues/58
           | 
           | As I was trying to find the correct command in jj for where
           | to add the new argument, I realized that this may not play
           | nice-nice with jj's commit-everything model, so I'm actually
           | prepared for the issue to be closed WONTFIX :-)
           | 
           | As for the patches welcome part, I notice that the Google CLA
           | bot is on your repo. While I do have the CLA signed for my
           | Gmail address, it seemed like some major tomfoolery to try
           | and add my current github email address (and the one which
           | backs my GPG key, to bring this full circle!) to the existing
           | CLA process. Do you intend to keep that CLA mechanism in
           | place, or was it just an oversight?
        
             | martinvonz wrote:
             | > I realized that this may not play nice-nice with jj's
             | commit-everything model
             | 
             | Yes, I suppose you might not want to sign every working
             | copy commit, but as you noted on the issue, it would
             | probably make sense on `jj close/commit` (aliases).
             | 
             | > Do you intend to keep that CLA mechanism in place
             | 
             | I started working on this project internally and then open-
             | sourced it. I don't think I'm allowed to remove the CLA
             | bot. I understand that it's annoying :(
        
           | smichel17 wrote:
           | I had a discussion about the git cli UX around
           | branching/stashing/checkout a while back. Perhaps you'll find
           | it useful: https://news.ycombinator.com/item?id=23807410
           | 
           | (I post this somewhat selfishly, as I'm basically describing
           | how I wish git worked ;)
        
       | CGamesPlay wrote:
       | Interesting ideas! I especially like the automatic rebasing and
       | associated ideas.
       | 
       | It's a bit strange to see "jj st" will automatically add all
       | files to the "working copy" commit. This means that when I
       | initially create my project, run "npm install" to install 500 MB
       | of dependencies, and then run "jj st" to figure out what to
       | include in my first commit, the command is going to copy all of
       | that into a commit object for no reason. I don't think I like
       | that behavior, to be honest. Is this a requirement of any of the
       | other unique features? Could this be turned off, or modified to
       | be an explicit operation?
       | 
       | [append]
       | 
       | To be clear, the fact that it's `jj st` is actually a big part of
       | the problem for me: this is the command I use to figure out what
       | to put into my `.gitignore` in the first place! I don't think
       | that any of the "read-only" commands should be making these kind
       | of changes.
        
       | giovannibonetti wrote:
       | > The command-line tool is called jj for now because it's easy to
       | type and easy to replace (rare in English). The project is called
       | "Jujutsu" because it matches "jj".
       | 
       | Yeah, it's just a coincidence that the world Jujutsu means magic
       | in japanese (Zhou Shu )
        
       | jayd16 wrote:
       | > Entire repo is under version control
       | 
       | I wonder how this works out for large files and cleaning them up.
        
         | martinvonz wrote:
         | I doesn't work very well yet. See
         | https://news.ycombinator.com/item?id=30399554.
        
       | qbasic_forever wrote:
       | That's very cool to have support for rsync/dropbox collaboration
       | of the repo files. I'm always sad that there isn't a maintained
       | p2p git implementation anymore. I'd love to just dump a bare repo
       | to a syncthing share and collaborate with a small group of people
       | accessing it.
        
       | danbmil99 wrote:
       | Does it support lfs, or deal with large binary assets in some
       | other way?
        
         | martinvonz wrote:
         | No, there's no particular support for large files yet.
        
       | jareds wrote:
       | This looks interesting and I'm glad to see that people are not
       | viewing SCM as a solved issue. While I don't think I'd use this
       | on professional projects yet I'm interested at looking at this
       | for personal projects since I can use the Git back-end and
       | continue to use Github to host my code. I feel like Git has
       | become such a DeFacto standard that nothing is going to replace
       | it any time soon. I've been programming for long enough to
       | remember feeling the same way about SVN though so I assume
       | something will eventually supplant Git.
        
         | freedomben wrote:
         | I remember that well too (along with Rational Clearcase), and
         | you may totally be right, but git does feel different because
         | it works so well with all sorts of projects, big and small.
         | There were always operations that required hacks. With git that
         | doesn't feel the case to me,perhaps with one exception (but I
         | don't think this is git's fault as much as it's mine for not
         | knowing git well enough to use the tools it provides): if I'm
         | working simultaneously on two different branches (for example
         | one branch is a bug fix that requires 20 minutes to build and
         | deploy before I can test it, so I work on other things while
         | it's running), I often have two different checkouts so I can
         | (mostly) avoid having to git stash.
         | 
         | That said though, you are probably right something will
         | eventually supplant git. It would be arrogant to think that my
         | failure to imagine something better means there isn't anything.
        
           | Hendrikto wrote:
           | What you are describing sounds as if you want worktrees:
           | https://git-scm.com/docs/git-worktree
        
             | freedomben wrote:
             | Whoa, thank you! That does look like the answer!
        
           | jeltz wrote:
           | I totally agree. Back when I used Subversion it felt to me
           | like there obviously must be a better way to version control
           | and that the tool got in my way all the time. Git on the
           | other hand almost always can solve my problems and while some
           | things could be improved (confusing UX, a bit too complex,
           | plus bad handling of conflicts) it is much closer to the
           | right tool for VCS than Subversion ever was.
        
             | fsloth wrote:
             | What are the problems that Subversion has? My only
             | experience of svn is of simple personal projects and in
             | that scope it worked pretty well - not contesting your
             | opinion, but would like to know at which point svn becomes
             | problematic.
        
               | netghost wrote:
               | If subversion had branches, they were not nearly as easy
               | to use as in git. It also didn't have a great notion of
               | offline work (to my memory).
               | 
               | For what it's worth, SVN was pretty straightforward and
               | worked well enough at the time. Later, Mercurial
               | addressed SVN's deficiencies with a familiar interface.
        
       | adamnemecek wrote:
       | Rust has truly reinvigorated these types of tools.
        
       | kyrra wrote:
       | For those that didn't look, this is 100% rust.
        
         | tonetheman wrote:
        
         | tuwtuwtuwtuw wrote:
         | Seems irrelevant to me. Why do you care about the language
         | choice?
        
           | throwaway81523 wrote:
           | Because this is hacker news, not user news.
        
           | usrusr wrote:
           | People do tend to see tools written in a systems language in
           | another light than tools written in a glue language. Did you
           | read it as "rust (not C)" or did you read it as "rust (not
           | Python)"?
        
             | em-bee wrote:
             | i used to look down on languages other than C, considering
             | programs written in C a better choice than eg. python. i
             | have since reversed my stance because i realized that
             | python is a lot more hackable. i haven't tried rust yet,
             | but i would prefer it over C for sure. compared to python i
             | won't know until i actually get familiar with rust.
        
           | KerrAvon wrote:
           | On the negative side: In some environments it's a hurdle to
           | build programs in Rust.
           | 
           | On the positive side: It signifies a certain likelihood of
           | memory and data safety that you won't get in most other
           | languages.
        
           | binarypaean wrote:
           | Language matters quite a bit to those considering
           | contributing. It also provides some context for expectations
           | about performance and reliability thanks to language idioms,
           | features and culture.
        
             | detaro wrote:
             | But the info is right on the linked page. Somehow I don't
             | think people who haven't even followed the submission link
             | aren't the ones to worry about yet for "potential
             | contributor".
        
           | ccbccccbbcccbb wrote:
           | Because it's trendy to praise brushes instead of paintings,
           | vinyl pressing quality instead of music, and languages
           | instead of software these days.
           | 
           | Jean Baudrillard would call it another level of simulation.
        
         | martinvonz wrote:
         | Note, though, that it depends on libgit2 (which is written in
         | C). (As pointed out by someone in
         | https://github.com/martinvonz/jj/issues/56.)
        
       | AnonC wrote:
       | I'm curious to know if this has any similarities with fossil
       | (https://fossil-scm.org/ ). If it does, it would be nice to see
       | that in the documentation.
        
         | throwaway81523 wrote:
         | Fossil is ideologically different, it wants to preserve every
         | artifact, no rebasing allowed.
        
       | BiteCode_dev wrote:
       | " It also means that you can always check out a different commit
       | without first explicitly committing the working copy changes (you
       | can even check out a different commit while resolving merge
       | conflicts)."
       | 
       | That's really interesting. Having to manage stashes is annoying.
        
         | halfdan wrote:
         | Try using git worktrees: https://geekmonkey.org/rethink-your-
         | git-workflow-with-git-wo...
        
           | pjc50 wrote:
           | Surprise limitation: you cannot have two worktrees set to the
           | same branch, or at least that confronted me when I tried it.
        
             | jomar wrote:
             | If you had two worktrees set to the same branch and made a
             | new commit in one of them (thus changing the commit the
             | branch ref points to), what would happen in the other
             | worktree?
             | 
             | Either it wouldn't have the right commit checked out
             | anymore, or git would have to miraculously change what
             | files are checked out in it -- which would likely come as a
             | big surprise to whatever you were doing in that working
             | tree.
             | 
             | Ergo, it is forbidden.
             | 
             | I periodically find myself creating a new (temporary)
             | branch referring to the same commit when I want a new
             | worktree looking at the same place, or just create a new
             | worktree with a detached HEAD looking at the same commit.
        
             | hpfr wrote:
             | Can you elaborate on why you would want two worktrees set
             | to the same branch? I think if I were trying to compare two
             | approaches involving incompatible changes, creating a
             | branch for one approach would feel more natural anyway, and
             | then I'd be able to use the worktrees.
        
           | CorrectHorseBat wrote:
           | What is the advantage of using worktrees over another
           | checkout in another folder?
        
             | 0xdky wrote:
             | You will need a full repository in other directory to
             | checkout and this will waste storage unless you share
             | objects via alternate.
        
             | jomar wrote:
             | When you're done with a worktree, you just delete it (via
             | `git worktree remove`). Any additional branches or stashes
             | etc are part of the repository that the worktree was part
             | of, and they (of course) remain.
             | 
             | When you're done working in a separately cloned repository
             | in another folder, if you're anything like me, before
             | deleting it (via `rm -rf`) you'll want to check very
             | carefully for additional branches, unpushed work, anything
             | stashed. Deleting an entire repository that's been around
             | for a while is a risky operation in that it may have
             | accumulated other unrelated work in addition to the current
             | branch (which was the primary reason for the clone), and
             | you'll want to check carefully before deleting the whole
             | lot.
             | 
             | Additional worktrees within the same repository are great
             | for medium-term ephemeral separate strands of work. They
             | can be created and removed without concern.
        
             | ossusermivami wrote:
             | Optimizations and management really
        
             | halfdan wrote:
             | Duplicate storage as already mentioned, but you will also
             | lose the ability to merge / doff cross branches if you have
             | separate checkouts.
        
               | cortesoft wrote:
               | Why would you lose that ability? You can just pull from
               | the other checkout as an upstream, right?
        
               | jonathanlydall wrote:
               | Worktree allows you to checkout other branches, stashes
               | or commits which are local only / not yet pushed.
               | 
               | What's also great is that you don't need to do a pull in
               | the other folder. Before I discovered worktree, I had my
               | repository checked out in two places, so was either
               | pulling both constantly, or when I needed the alternate,
               | it was often very far behind and I had to pull a lot.
        
               | CorrectHorseBat wrote:
               | Hmm, I tried it once and iirc I couldn't see
               | commits/branches of the other workspace without pushing
               | and fetching so I really didn't see any difference. With
               | different checkouts you can also easily do that by adding
               | the other checkout as a remote.
        
               | dataflow wrote:
               | Something probably got messed up on your setup (or maybe
               | you checked out a commit instead of a branch?) because
               | you definitely can see all worktrees' branches from
               | inside each other when using git worktree.
        
               | CorrectHorseBat wrote:
               | That makes sense. Now I think about it, The issue
               | probably was that I was working in a submodule and those
               | branches are probably not shared.
        
               | jonathanlydall wrote:
               | Yes, as per my other comment, I've noticed with
               | submodules that the references are isolated between the
               | different folders, but they do share the same objects in
               | the .git folder, so you still get efficiency there in not
               | needing to store or pull duplicate data.
        
               | jonathanlydall wrote:
               | Not sure what you were doing wrong, but I use worktree
               | regularly and you can absolutely see the same commits
               | from both the primary and worktree side.
               | 
               | The great thing about worktrees is that everything local
               | is still available in the worktree and vice-versa, you
               | can even stash push on the one side and pop on the other.
               | You also don't need to push or pull on either side first.
               | 
               | I have noticed that for submodules, although they share
               | the .git folder, they don't share references, so you
               | can't see local branches and stashes between the
               | worktrees, but sub module pulls are still quicker since
               | they share objects so those don't need re-pulled on the
               | other folder.
        
         | floatboth wrote:
         | rebase.autostash=true is also a thing, but the "working copy as
         | commit" concept does look more interesting.
        
       | blagie wrote:
       | This seems really nice.
       | 
       | git got the data model really right, and the user space really
       | wrong. The data model is more important than the user space.
       | 
       | This is the first project I've seen which appears to understand
       | and respect /how/ and /why/ the git data model is so elegant.
        
         | dane-pgp wrote:
         | > The data model is more important than the user space.
         | 
         | For those interested in the different perspectives on how to
         | weigh those priorities, I recommend starting here:
         | 
         | https://en.wikipedia.org/wiki/Worse_is_better
        
           | somebodythere wrote:
           | I think the programmer tendency to think of usability as an
           | implementation detail is probably why open-source app UX was
           | considered a joke for so many years. Only now is that
           | perception starting to change, because enough people have
           | taken an interest in the space who make usability a priority.
        
         | carlhjerpe wrote:
         | The pijul model makes even more sense to my brain, being patch
         | based solves a lot of branching issues.
        
       ___________________________________________________________________
       (page generated 2022-02-19 23:00 UTC)