Last active
May 27, 2026 14:38
-
-
Save mystor/10111f7bc9fd14fea1301ce1b33b593d to your computer and use it in GitHub Desktop.
jj git-index diff editor (v2)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This diff editor uses the state of the git index (staged files) to edit the diff. | |
| # This gives an effect similar to `git commit`, which can be useful due to tooling | |
| # often being high-quality for using the git index to split up changes. | |
| # | |
| # This tool is designed to be used with the commit, split, and squash commands. | |
| # This is made easier with some aliases. A custom merge-editor definition is unneeded. | |
| # | |
| # LIMITATIONS: | |
| # 1. jj doesn't allow a diff editor to edit files which are only changed in the index, | |
| # and unchanged in the working copy, those will be discarded. | |
| # 2. You must run this command within the worktree, such that the `git` commands | |
| # implicitly derive the index from the working directory. | |
| # 3. This naturally only works in colocated workspaces, and only if the source | |
| # revision is the working copy. | |
| [aliases] | |
| icommit = ["commit", "--tool", "/path/to/jj-diffedit-git-index.sh"] | |
| isplit = ["split", "--tool", "/path/to/jj-diffedit-git-index.sh"] | |
| isquash = ["squash", "--tool", "/path/to/jj-diffedit-git-index.sh"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -euo pipefail | |
| export LC_ALL=C | |
| TEMP=$(mktemp -d) | |
| trap 'rm -rf -- "$TEMP"' EXIT | |
| LEFT="$1" | |
| RIGHT="$2" | |
| # Snapshot the index state into a tree. This strips intent-to-add index entries | |
| # which are treated as empty files by ls-files & restore. jj implicitly adds | |
| # intent-to-add index entries for new files. | |
| TREE="$(git write-tree)" | |
| # jj checks out a sparse working copy, limit to that sparse set. | |
| find -P "$LEFT" "$RIGHT" \( -type f -o -type l \) -printf '%P\0' | | |
| sort -zu > "$TEMP/sparse" | |
| # Every pathspec passed to git restore must be in $TREE | |
| git ls-tree -rz --name-only --full-tree "$TREE" | | |
| sort -zu | | |
| comm -z -12 "$TEMP/sparse" - > "$TEMP/restore" | |
| # Clear out $RIGHT, then restore $TREE state into it | |
| rm -r -- "$RIGHT" | |
| mkdir -- "$RIGHT" | |
| if [[ -s "$TEMP/restore" ]]; then | |
| git --literal-pathspecs --work-tree="$RIGHT" restore \ | |
| --source="$TREE" \ | |
| --pathspec-from-file="$TEMP/restore" \ | |
| --pathspec-file-nul | |
| fi |
Author
Sure, I've added it to the top of the script
Thank you. I'm using this together with git gui. It's amazing :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is nice stuff.
Please consider adding
export LC_ALL=Cor anything similar to the script, ascommandsortmay disagree otherwise: