# jj – Jujutsu용 CLI

> Clean Markdown view of GeekNews topic #28534. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=28534](https://news.hada.io/topic?id=28534)
- GeekNews Markdown: [https://news.hada.io/topic/28534.md](https://news.hada.io/topic/28534.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-04-15T09:49:37+09:00
- Updated: 2026-04-15T09:49:37+09:00
- Original source: [steveklabnik.github.io](https://steveklabnik.github.io/jujutsu-tutorial/introduction/what-is-jj-and-why-should-i-care.html)
- Points: 2
- Comments: 1

## Topic Body

- **Jujutsu의 명령줄 인터페이스**인 `jj`는 **분산 버전 관리 시스템(DVCS)** 기반 도구
- **`git`보다 단순하고 직관적이면서도 더 강력한 기능**을 제공
- **`git`과 Mercurial의 장점을 결합**해 핵심 도구 수를 줄이고 유기적 연동을 강화
- **`git` 호환 백엔드**를 사용해 기존 협업 환경을 유지하면서도 독립적 실험 가능
- 고급 사용자는 `git`으로는 어려운 **추가 버전 관리 기능**을 활용할 수 있는 점이 중요

---

### jj 소개와 특징
- ## `jj`는 Jujutsu의 CLI(명령줄 인터페이스)**로, Jujutsu는**분산 버전 관리 시스템(DVCS)
  - 사용자는 `git`과 같은 다른 DVCS에 익숙할 수 있으며, 튜토리얼은 `git` 사용자 관점을 전제로 함
  - `jj`는 **`git`보다 단순하고 사용하기 쉬우면서도 강력한 도구**로 설계됨
  - 일반적으로 “강력함”과 “복잡함”은 상충하지만, `jj`는 이 균형을 새롭게 제시함
  - `jj`는 **`git`과 Mercurial(`hg`)의 장점을 결합**해 새로운 형태의 DVCS를 구성
  - 핵심 도구 수를 줄이고, 각 도구 간의 **유기적 연동**을 통해 효율적인 작업 환경 제공
  - 고급 사용자는 `git`으로는 어려운 **추가 버전 관리 기능**을 활용 가능
  - `jj`는 **`git` 호환 백엔드**를 사용해 협업 환경을 변경하지 않고도 독립적인 실험 가능
  - 기존 `git` 저장소와의 호환성을 유지하며, 필요 시 손쉽게 `git`으로 복귀 가능
  - 튜토리얼은 이러한 특성을 통해 `jj`가 **왜 주목할 만한 도구인지 직접 보여주는 과정**을 예고함

## Comments



### Comment 55354

- Author: neo
- Created: 2026-04-15T09:49:38+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=47763759) 
- 많은 논의가 **git과 jj의 차이점**에 집중되어 있지만, 나는 그냥 git을 잊고 jj의 기본 워크플로우에 집중하는 게 낫다고 생각함  
  깨끗한 저장소에서 `jj`를 실행하면 상태를 확인할 수 있고, 변경 후 `jj commit -m "made changes"`로 커밋하면 됨  
  실수했을 땐 수정 후 `jj squash`로 마지막 커밋에 합치면 됨  
  새로운 브랜치처럼 특정 리비전에서 작업하고 싶을 때만 `jj new -r lmnop`을 사용하면 됨  
  git 히스토리는 `git log`로 확인 가능하며, jj 내부 동작은 보이지 않음
  - 나도 비슷한 걸 원해서 `alias.save="!git add -A; git commit -m"` 같은 **git alias**를 만들어서 `$ git save "made changes"`로 쓰곤 함

- JJ가 나에게 **거꾸로 생각하라**고 요구하는 것처럼 느껴짐  
  git에서는 변경 후 커밋 메시지를 작성하지만, jj는 먼저 새 커밋을 만들고 설명을 붙이는 식임  
  여러 기능이 섞인 더러운 상태에서 필요한 변경만 골라 커밋하는 게 익숙한데, jj 튜토리얼만 봐서는 그게 가능한지 확신이 안 섬
  - `jj new`는 비어 있는 git 스테이징 영역 같은 개념임  
    jj에서는 항상 커밋이 존재하고, 그 커밋은 폴더 내용에 따라 계산된 값으로 **안정적인 changeid**를 가짐  
    여러 변경을 나눠 커밋하고 싶다면 `jj split`을 쓰면 됨
  - 나는 자주 `jj new`로 임시 커밋을 만들고 메시지는 비워둠  
    나중에 준비가 되면 여러 커밋을 **squash**해서 하나로 합치고 메시지를 추가함  
    이 방식은 일종의 **undo 히스토리**처럼 작동해서 실험하기 훨씬 편함
  - 사실 `jj new`는 단순히 “새 커밋을 위에 만들기”일 뿐이라, 바로 설명을 쓸 필요는 없음  
    나도 처음엔 습관을 들이려 했지만, 오히려 비효율적이었음
  - JJ에서는 이런 방식이 **표준적**임  
    Git에서도 비슷한 워크플로우를 추천해왔고, [Squash Workflow](https://arialdomartini.github.io/pre-emptive-commit-comments)를 참고하면 Git의 인덱스와 유사한 흐름을 만들 수 있음
  - 나도 여러 변경을 하다 보면 서로 다른 기능이 섞이곤 함  
    그래서 여러 워크스페이스를 두고 **shelve** 기능(IntelliJ)을 자주 씀  
    때로는 git 패치로 diff를 임시 저장해두기도 함  
    이런 혼란스러운 과정을 동료에게 숨기며 조금 더 **프로페셔널**해 보이려 함

- jj를 써보니 마음에 안 드는 점은 파일 수정이 자동으로 커밋된다는 것임  
  과거 커밋을 탐색하려고 checkout 후 파일을 수정하면, 그 커밋이 바뀌고 이후 히스토리가 전부 리베이스됨  
  그래서 방어적으로 빈 커밋을 새로 만들어야 함  
  git은 내가 명시적으로 커밋하기 전까지는 저장소가 변하지 않아서 더 편함
  - 나도 예전에 그렇게 생각했지만, `jj evolog`를 알고 나서 바뀌었음  
    jj는 스테이징보다 더 나은 해결책을 이미 갖고 있었음  
    git CLI에 익숙한 게 오히려 jj 학습의 **장애물**이었음  
    흥미롭게도 jj를 쓰면 git의 **저장 엔진 구조**를 더 잘 이해하게 됨
  - `edit` 대신 `jj new`를 쓰면 깔끔하게 변경을 추적할 수 있음  
    git의 stash를 juggling하는 것보다 훨씬 낫다고 느낌
  - `jj edit`은 jj의 **가장 큰 함정**임  
    대신 `jj new`를 쓰고, 실수했을 땐 `jj undo`로 복구 가능함  
    jj는 커밋을 값싼 **스냅샷**으로 다루므로, 커밋보다 “변경”에 집중하는 게 맞음  
    자동 리베이스는 push 이후엔 불변으로 고정되어 안전함
  - 파일 수정이 자동 커밋되는 건 jj의 **핵심 기능**임  
    `jj new`와 `jj squash`를 조합해 git 브랜치 헤드처럼 관리하면 됨  
    detached head 상태에서 작업하는 걸 jj가 쉽게 만들어줌
  - 아마 `jj edit`으로 과거 커밋을 checkout한 것 같음  
    `jj new`로 바꾸면 문제가 해결됨

- jj의 마지막 문단이 핵심임  
  git과 **완전히 호환되는 백엔드**를 사용하므로, 팀 전체가 바꿀 필요 없이 혼자 써볼 수 있음  
  마음에 안 들면 언제든 git으로 돌아갈 수 있음
  - 단, LFS나 submodule, hook을 쓰는 조직에서는 예외임
  - 완전한 호환은 아님. 상호운용은 가능하지만 **완벽히 매끄럽진 않음**  
    git 작업은 jj 로그에 기록되지 않아 수동으로 import해야 함  
    프로젝트에서는 한 가지 인터페이스만 쓰는 걸 권장함
  - 예전엔 나도 git을 CVS, Subversion과 함께 그렇게 썼음
  - 하지만 git과 jj를 **같은 디렉토리에서 동시에** 쓰면 망가질 수 있음

- 내가 가장 좋아하는 기능은 **`jj absorb`** 임  
  현재 리비전의 변경을 이전 관련 커밋으로 자동 이동시켜줌  
  설정 파일이나 `.gitignore` 수정 깜빡했을 때 유용함  
  `jj new` 후 변경하고 `jj absorb` 하면 됨  
  게다가 **merge conflict**를 다루지 않아도 되는 게 최고임
  - 만약 `jj absorb`가 잘못 적용되면 `jj undo`로 되돌릴 수 있음  
    이 기능 덕분에 복잡한 rebase도 두렵지 않음
  - 참고로 git에도 `git absorb`가 존재함

- 튜토리얼을 오랫동안 업데이트 못 했지만, 여전히 매일 jj를 쓰고 있음  
  스타트업 [ersc.io](https://ersc.io)에서 바빠서 upstream 작업을 못 했음  
  질문이 있으면 언제든 환영함
  - git과 jj의 **DAG 불변성 차이**가 핵심임  
    jj는 stable change ID를, git은 immutable commit ID를 사용함  
    그래서 jj에서는 **undo나 rebase가 훨씬 유연**하게 느껴짐
  - jj는 “흥미롭지 않은” 변경을 자동으로 숨김  
    가끔 더 많은 변경을 보고 싶을 때가 있는데, 이를 한 번에 표시하는 옵션이 있는지 궁금함

- jj가 git과 달라서 시도해볼 가치가 있음  
  다른 접근 방식을 경험하는 것만으로도 **엔지니어링 시야**가 넓어짐  
  모든 걸 다 시도할 필요는 없지만, 다양한 워크플로우의 **트레이드오프**를 이해하는 건 중요함
  - 물론, 99%의 경우 **이득이 미미한 시도**는 시간 낭비일 수도 있음

- git과 jj의 관계는 **C와 Python**의 관계처럼 느껴짐  
  git은 포렌식 추적이고, jj는 **이야기의 장(chapter)** 같음  
  때로는 초반 챕터를 다시 써야 후반이 더 자연스러워짐
  - jj가 하는 일은 git에서도 가능하지만, git의 **습관적 사고방식**이 방해가 됨  
    jj는 “working tree 자체가 커밋”이고 “conflict도 커밋 가능”하다는 철학으로 설계됨

- “더 강력하고 쉽다”는 주장엔 **구체적 예시**가 필요하다고 느낌
  - jj의 장점 몇 가지를 꼽자면:  
    - rebase/merge conflict를 즉시 해결하지 않아도 됨  
    - 커밋 조작이 매우 쉬움 (특히 **jjui** 사용 시)  
    - jj는 git의 상태 변화를 추적하는 **operation log**를 가짐  
    - 이름 없는 브랜치 덕분에 실험적 작업이 자유로움  
    - git과 완전히 호환되어 팀 내 혼용이 가능함
  - 우리는 SVN에서 git으로 옮겼을 때 큰 개선을 느꼈지만, 지금 git 워크플로우엔 큰 불편이 없음
  - 여러 PR을 한 저장소에서 동시에 작업하고 각자에 맞게 푸시할 수 있음  
    이런 필요가 없다면 jj의 가치를 못 느낄 수도 있음
  - jj의 매력은 명령어가 아니라 **직관적인 워크플로우**에 있음  
    직접 써봐야 이해됨
  - `jj undo` 하나만으로도 충분히 값어치가 있음  
    git에서는 복구 불가능한 상태가 되기 쉬운데, jj에서는 몇 번의 undo로 해결 가능함

- jj 덕분에 **비선형 DAG**를 활용하는 데 자신감이 생김  
  여러 부모나 자식이 있는 변경을 자유롭게 다룸  
  예전엔 불필요하게 순서를 강제했지만, 이제는 **의존 관계를 명확히 표현**할 수 있음  
  리뷰와 제출 과정도 훨씬 효율적임
  - 이런 분기된 변경 위에서 **mega-merge + absorb** 워크플로우를 쓰는지 궁금함
