* Unexpected behavior in git diff --relative=<path>
@ 2026-01-05 22:56 Harrison McCullough
2026-01-06 16:58 ` Ben Knoble
0 siblings, 1 reply; 2+ messages in thread
From: Harrison McCullough @ 2026-01-05 22:56 UTC (permalink / raw)
To: git
What did you do before the bug happened? (Steps to reproduce your issue)
- Create a "foo.txt" file
- Commit the "foo.txt"
- Modify the "foo.txt" file
- Create a "foo/bar.txt" file
- Commit the "foo/bar.txt"
- Modify the "foo/bar.txt" file
- Run `git diff --name-only --relative=foo`
What did you expect to happen? (Expected behavior)
I would expect to only see modified files inside the "foo/" directory. For
example, I would expect this to be the output:
```
$ git diff --name-only --relative=foo
bar.txt
```
What happened instead? (Actual behavior)
Both the "foo/bar.txt" _and_ the "foo.txt" files were listed--but the "foo.txt"
file had the "foo" prefix stripped, appearing as just ".txt".
```
$ git diff --name-only --relative=foo
.txt
bar.txt
```
What's different between what you expected and what actually happened?
Using the `--relative=<path>` flag to `git diff` appears to simply remove the
prefix from each file, regardless of whether that is a full path prefix or just
part of the file name.
Anything else you want to add:
This is the relevant part of the man page for `git-diff`:
> When run from a subdirectory of the project, it can be told to exclude changes
> outside the directory and show pathnames relative to it with this option. When
> you are not in a subdirectory (e.g. in a bare repository), you can name which
> subdirectory to make the output relative to by giving a <path> as an argument.
> --no-relative can be used to countermand both diff.relative config option and
> previous --relative.
When I read this for the first time, I imagined that the behavior would be as
follows:
- `git diff`: include all changes, display file names beginning from repository
root
- `git diff .`: include all changes in the current directory and "below",
display file names beginning from repository root
- `git diff --relative=. .`: include all changes in the current
directory and "below",
display file names beginning from the current directory
- E.g. if the repository root is `/home/bob/repo/` and the current directory
is `/home/bob/repo/foo/bar/`, then a modified file
`/home/bob/repo/foo/bar/baz/qux.txt` would be displayed as `baz/qux.txt`
- `git diff --relative=.. ..`: include all changes in the parent
directory and "below",
display file names beginning from the parent directory
- E.g. if the repository root is `/home/bob/repo/` and the current directory
is `/home/bob/repo/foo/bar/`, then a modified file
`/home/bob/repo/foo/bar/baz/qux.txt` would be displayed as
`bar/baz/qux.txt`
I understand that my initial assumption may not be the intended
behavior. However, I don't think that stripping a prefix of a file name just
because the file name matched the argument to `--relative` makes much sense. If
that _is_ the desired behavior, I think that `--strip-prefix` or something
similar would be a better name. The name "relative", to me, makes it sound like
it is logically connected to the directory structure.
In addition, the description of the `--relative` flag claims that "it can be
told to exclude changes outside the directory ...". This implies that the
argument should be a directory. In practice, the argument _can_ be a directory,
but that isn't verified.
If this flag is working exactly as intended, then perhaps a clarifying comment
can be added to the documentation to explicitly state that the argument is
matched against the full file path, starting at the repository root, and is
removed from the beginning of the path (and the file is included in the output)
if it matches--regardless of whether the match matches a full directory path or
just the first portion of a file name.
I will note that if you want to make sure that the argument to the `--relative`
flag only matches against entire directories, not file name prefixes, you can
simply append a trailing slash to the end. In the case of the example I provided
above, I can run the following and get reasonable behavior:
```
$ git diff --name-only --relative=foo/
bar.txt
```
[System Info]
git version:
git version 2.46.2
cpu: arm64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
libcurl: 8.4.0
zlib: 1.2.12
uname: Darwin 24.6.0 Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:55
PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6031 arm64
compiler info: clang: 15.0.0 (clang-1500.3.9.4)
libc info: no libc information available
$SHELL (typically, interactive shell): /opt/homebrew/bin/bash
[Enabled Hooks]
-Harrison McCullough
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Unexpected behavior in git diff --relative=<path>
2026-01-05 22:56 Unexpected behavior in git diff --relative=<path> Harrison McCullough
@ 2026-01-06 16:58 ` Ben Knoble
0 siblings, 0 replies; 2+ messages in thread
From: Ben Knoble @ 2026-01-06 16:58 UTC (permalink / raw)
To: Harrison McCullough; +Cc: git
> Le 5 janv. 2026 à 17:56, Harrison McCullough <mccullough.harrison@gmail•com> a écrit :
>
> What did you do before the bug happened? (Steps to reproduce your issue)
>
> - Create a "foo.txt" file
> - Commit the "foo.txt"
> - Modify the "foo.txt" file
> - Create a "foo/bar.txt" file
> - Commit the "foo/bar.txt"
> - Modify the "foo/bar.txt" file
> - Run `git diff --name-only --relative=foo`
>
>
> What did you expect to happen? (Expected behavior)
>
> I would expect to only see modified files inside the "foo/" directory. For
> example, I would expect this to be the output:
>
> ```
> $ git diff --name-only --relative=foo
> bar.txt
> ```
>
>
> What happened instead? (Actual behavior)
>
> Both the "foo/bar.txt" _and_ the "foo.txt" files were listed--but the "foo.txt"
> file had the "foo" prefix stripped, appearing as just ".txt".
>
> ```
> $ git diff --name-only --relative=foo
> .txt
> bar.txt
> ```
Easy to reproduce (with f or fo, too).
> What's different between what you expected and what actually happened?
>
> Using the `--relative=<path>` flag to `git diff` appears to simply remove the
> prefix from each file, regardless of whether that is a full path prefix or just
> part of the file name.
>
>
> Anything else you want to add:
>
> This is the relevant part of the man page for `git-diff`:
>
>> When run from a subdirectory of the project, it can be told to exclude changes
>> outside the directory and show pathnames relative to it with this option. When
>> you are not in a subdirectory (e.g. in a bare repository), you can name which
>> subdirectory to make the output relative to by giving a <path> as an argument.
>> --no-relative can be used to countermand both diff.relative config option and
>> previous --relative.
The wording implies to me that “=<path>” is only intended for use with bare repositories. With working trees, use just the relative option from within a directory:
(cd foo && git diff - -relative)
If that’s right (?), then the docs should probably be more direct about the way each is intended to be used. I can imagine some use cases for the stripping behavior in non-bare repos, but mostly around ad-hoc scripts.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-01-06 16:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-05 22:56 Unexpected behavior in git diff --relative=<path> Harrison McCullough
2026-01-06 16:58 ` Ben Knoble
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox