git/contrib/git-jump
Greg Hurrell 621ce9c1c6 git-jump: make `diff` work with filenames containing spaces
In diff.c, we output a trailing "\t" at the end of any filename that
contains a space:

    case DIFF_SYMBOL_FILEPAIR_PLUS:
            meta = diff_get_color_opt(o, DIFF_METAINFO);
            reset = diff_get_color_opt(o, DIFF_RESET);
            fprintf(o->file, "%s%s+++ %s%s%s\n", diff_line_prefix(o), meta,
                    line, reset,
                    strchr(line, ' ') ? "\t" : "");
            break;

That is, for a file "foo.txt", `git diff --no-prefix` will emit:

    +++ foo.txt

but for "foo bar.txt" it will emit:

    +++ foo bar.txt\t

This in turn leads `git-jump` to produce a quickfix format like this:

    foo bar.txt\t:1:1:contents

Because no "foo bar.txt\t" file actually exists on disk, opening it in
Vim will just land the user in an empty buffer.

This commit takes the simple approach of unconditionally stripping any
trailing tab. Consider the following three examples:

1. For file "foo", Git will emit "foo".
2. For file "foo bar", Git will emit "foo bar\t".
3. For file "foo\t", Git will emit "\"foo\t\"".
4. For file "foo bar\t", Git will emit "\"foo bar\t\"".

Before this commit, `git-jump` correctly handled only case "1".

After this commit, `git-jump` correctly handles cases "1" and "2". In
reality, these are the only cases people are going to run into with any
regularity, and the other two are rare edge cases, which probably aren't
worth the effort to support unless somebody actually complains about
them.

Signed-off-by: Greg Hurrell <greg.hurrell@datadoghq.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-08-11 08:58:21 -07:00
..
README git-jump: add an optional argument '--stdout' 2022-11-27 10:49:51 +09:00
git-jump git-jump: make `diff` work with filenames containing spaces 2025-08-11 08:58:21 -07:00

README

git-jump
========

Git-jump is a script for helping you jump to "interesting" parts of your
project in your editor. It works by outputting a set of interesting
spots in the "quickfix" format, which editors like vim can use as a
queue of places to visit (this feature is usually used to jump to errors
produced by a compiler). For example, given a diff like this:

------------------------------------
diff --git a/foo.c b/foo.c
index a655540..5a59044 100644
--- a/foo.c
+++ b/foo.c
@@ -1,3 +1,3 @@
 int main(void) {
-  printf("hello word!\n");
+  printf("hello world!\n");
 }
-----------------------------------

git-jump will feed this to the editor:

-----------------------------------
foo.c:2: printf("hello word!\n");
-----------------------------------

Or, when running 'git jump grep', column numbers will also be emitted,
e.g. `git jump grep "hello"` would return:

-----------------------------------
foo.c:2:9: printf("hello word!\n");
-----------------------------------

Obviously this trivial case isn't that interesting; you could just open
`foo.c` yourself. But when you have many changes scattered across a
project, you can use the editor's support to "jump" from point to point.

Git-jump can generate four types of interesting lists:

  1. The beginning of any diff hunks.

  2. The beginning of any merge conflict markers.

  3. Any grep matches, including the column of the first match on a
     line.

  4. Any whitespace errors detected by `git diff --check`.


Using git-jump
--------------

To use it, just drop git-jump in your PATH, and then invoke it like
this:

--------------------------------------------------
# jump to changes not yet staged for commit
git jump diff

# jump to changes that are staged for commit; you can give
# arbitrary diff options
git jump diff --cached

# jump to merge conflicts
git jump merge

# documentation conflicts are hard; skip past them for now
git jump merge :^Documentation

# jump to all instances of foo_bar
git jump grep foo_bar

# same as above, but case-insensitive; you can give
# arbitrary grep options
git jump grep -i foo_bar

# use the silver searcher for git jump grep
git config jump.grepCmd "ag --column"
--------------------------------------------------

You can use the optional argument '--stdout' to print the listing to
standard output instead of feeding it to the editor. You can use the
argument with M-x grep on Emacs:

--------------------------------------------------
# In Emacs, M-x grep and invoke "git jump --stdout <mode>"
M-x grep<RET>git jump --stdout diff<RET>
--------------------------------------------------

Related Programs
----------------

You can accomplish some of the same things with individual tools. For
example, you can use `git mergetool` to start vimdiff on each unmerged
file. `git jump merge` is for the vim-wielding luddite who just wants to
jump straight to the conflict text with no fanfare.

As of git v1.7.2, `git grep` knows the `--open-files-in-pager` option,
which does something similar to `git jump grep`. However, it is limited
to positioning the cursor to the correct line in only the first file,
leaving you to locate subsequent hits in that file or other files using
the editor or pager. By contrast, git-jump provides the editor with a
complete list of files, lines, and a column number for each match.


Limitations
-----------

This script was written and tested with vim. Given that the quickfix
format is the same as what gcc produces, I expect other tools have a
similar feature for iterating through the list, but I know nothing about
how to activate it.

The shell snippets to generate the quickfix lines will almost certainly
choke on filenames with exotic characters (like newlines).

Contributing
------------

Bug fixes, bug reports, and feature requests should be discussed on the
Git mailing list <git@vger.kernel.org>, and cc'd to the git-jump
maintainer, Jeff King <peff@peff.net>.