Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions docs/git-experts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Jujutsu for Git experts

People who are proficient with Git often ask what benefit there is to using
Jujutsu. This page explains the practical advantages for Git experts, with
examples showing how common workflows become easier, safer, or faster with
Jujutsu.

## Git can be used side-by-side in the same repository

Jujutsu repositories are colocated by default, so you can use `jj` and `git`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would skip the colocated jargon and just talk about how they're next to each other.

side-by-side. If you find a situation that's easier with Git, run the `git`
command and return to `jj` when you're done.
Comment on lines +11 to +12
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Add "Also please file a feature request" or similar?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have worries about destructive git commands in this case? I don't want to get too into the weeds right at the start, though...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git clean -x comes to mind of course, perhaps that deserves a special mention as it seems to be more common with experts (I never used it in my entire time of using git).


Colocation makes migration easier because you can adopt Jujutsu for the
workflows it improves without losing access to the Git commands and tools you
already know.

## Automatic and safer history editing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably mention the staging area somewhere. I don't know if that would be part of this section or somewhere else. Feel free to just leave a TODO if you agree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make it a section right above this one, it's going to be the largest change that someone runs into immediately.


If you frequently amend, reorder, or squash commits, Jujutsu can often perform
the same operations in fewer commands.

Suppose you want to amend an older commit and squash it into earlier history.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence sounds a bit redundant to me because "amend an older commit" and "squash into earlier history" sounds like about the same thing. Maybe "Suppose you want to amend some changes in the working copy into an older commit" or something like that?

With Git you might do this in three steps:

```sh
git add file1 file2
git commit --fixup abc
git rebase -i --autosquash
```

With Jujutsu, you simply squash the changes directly into the commit you want to
amend. All descendants are automatically rebased on top of the amended commit:

```sh
jj squash --into abc file1 file2
```

## Undo is more powerful than using the reflog

Git's reflog is powerful, but it's per-ref and can be awkward to use when
multiple refs and operations are involved.

Jujutsu's operation log records the state of the entire repository: Every change
is an operation you can inspect, and you can restore to any earlier state with
one command.

Common uses of the operation log:

- `jj undo` reverts the last operation in one step, without needing to figure
out which ref to reset. You can repeat `jj undo` to continue stepping backwards
in time.

- `jj op log -p` shows operations with diffs so you can inspect what happened.

- `--at-operation ID` lets you run commands as if the repository were in a
previous state.

## The evolution log shows the history of a single change

The Git reflog shows how refs moved over time, but makes it difficult to see how
a particular commit evolved over time. Jujutsu's evolution log ("evolog") shows
exactly this: Each time a change is rewritten, the update is visible in the
evolog.

You can use the evolog to find a previous version, then `jj restore` to restore
the complete or partial contents to the current version.

## Conflict resolution can be deferred
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a big one that we'll have to iterate on, a lot of people want to see something more concrete here. like they don't get the "well you can just do it later" without more details. I had a good example of this somewhere recently and now I've lost it, ugh...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was an example I read (I don't see it in the docs) that explained how a command could generate a conflict which is then resolved automatically in the next command, which is the best case for deferring.
See Advantages in the docs for scenarios to form an example around.

Copy link
Contributor Author

@jennings jennings Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added one paragraph about the "need to go fix a critical bug" situation, and then a second paragraph for, "I did another rebase and it resolved all the conflicts for me". What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's somewhat rare that the "rebase again resolves conflicts" is very useful in practice. I'm not sure it's going to convince many. Perhaps it will be more confusing that it's helpful.

I wonder if this paragraph should be about the conflict algebra (probably without using that term). If it is, I think I would rank 3 things it provides like this:

  1. Rebase/merge always succeeds, so we can always rebase descendants
  2. We can define the changes in a merge commit well
  3. Conflicts resolutions can be deferred

My point is that I think deferring conflict resolution is actually less important as a feature. Just a thought; feel free to ignore.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a new git-minded user this is probably true. But FWIW, in practice I've found that on long-running branches I routinely have conflicts at or near the tip, which I just keep around for weeks or months. These commits typically started as a nontrival change where I decided to go a slightly different direction, by pulling out individual changes into new commits that I put in front of the original one.

After a while, the original commit becomes an increasingly-conflicted mess but I keep jj showing it to remind myself what I had been thinking, and to copy/paste parts of the diff out into new commits, and eventually I'll abandon it ... but with jj there's no particular rush to abandon stuff because it's not hurting anything to have the conflicts there. I'll also throw random notes into the description.

But anyway, I don't think I would find this story very convincing when I was a git user starting out with jj. It sounds super ugly and it's impossible in git. So it may not belong here.


Git forces you to resolve conflicts immediately while merging or rebasing is
in progress. Jujutsu lets you defer that work, which is useful when conflicts
are complicated or when you want to switch context to fix something else.

You can leave a commit in a conflicted state, continue other work, and return
later. This reduces the cost of context switching when resolving a large number
of conflicts.
Comment on lines +75 to +77
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An advantage of this is that you can rebase like really old work on top of trunk() support without ever needing to solve it, I currently do that for Noah's Topic branch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do that too. I wonder if that sounds like a benefit, though. I imagine the rebuttal: "If the conflict isn't resolved, you can't use the branch, so why bother even rebasing it?"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this is something we can let people discover later. They'll likely even discover it on their own.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if that sounds like a benefit, though. I imagine the rebuttal: "If the conflict isn't resolved, you can't use the branch, so why bother even rebasing it?"

I mean having the ability to revive any patch from the past of a codebase is to me a big plus. But your rebuttal is correct though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I came here to suggest a similar thing; I have a rebase-all alias that I use often, so I'm rebasing all of my branches. This lets me continue to work on a non-conflicted branch, and know which ones I'll need to fix later. Hard to describe this without getting into the alias, though...


Because Jujutsu records the inputs to conflicts, not just conflict markers, it
can sometimes automatically resolve conflicts after a rebase. When performing
several rebases in sequence, some conflicts may be introduced by one and then
later automatically resolved by another, without any manual effort to resolve
the conflicts.
Comment on lines +79 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this paragraph should reference that this makes Git's rerere functionality obsolete since it is built in


## `jj absorb` makes it easier to update a patch stack

When amending several commits in a stack of changes, Git requires you to run
`git commit --fixup <ID>` at least once for each commit before running `git
rebase --autosquash`.

`jj absorb` is useful when you've made small fixes in the working copy and want
them incorporated into recent commits. It automatically moves each change in the
working copy into the previous commit where that line was changed.

It doesn't solve all cases: If multiple commits in the stack modified the same
line as was changed in the working copy, it will not move that change. But it
does help the trivial cases, leaving you to decide how to squash the remaining
changes.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ nav: # This lists all the files that become part of the documentation
- Git comparison: 'git-comparison.md'
- Git command table: 'git-command-table.md'
- Git compatibility: 'git-compatibility.md'
- Jujutsu for Git experts: 'git-experts.md'
- Sapling comparison: 'sapling-comparison.md'
- Other related work: 'related-work.md'

Expand Down