Making git diff --stat show full file path

GitGit Diff

Git Problem Overview


On doing git diff --stat some files are listed with full path from repository base but some files are listed as:

.../short/path/to/filename.  

That is the path starts with ... and only short path is shown.

I would like git diff to list full file path for all files for it to be easily processed by a script. Is there some way I can get git diff to always show full path

Git Solutions


Solution 1 - Git

By default git diff truncates its output to fit into a 80-column terminal.

You can override this by specifying values using the --stat option:

--stat[=<width>[,<name-width>[,<count>]]]
       Generate a diffstat. You can override the default output width for
       80-column terminal by --stat=<width>. The width of the filename
       part can be controlled by giving another width to it separated by a
       comma. By giving a third parameter <count>, you can limit the
       output to the first <count> lines, followed by ...  if there are
       more.

       These parameters can also be set individually with
       --stat-width=<width>, --stat-name-width=<name-width> and
       --stat-count=<count>.

For example, by setting the output value to a very large number:

git diff --stat=10000

Note that produces the path relative to the root of the git repository.

(For scripting you might want to use git diff-tree directly since it's more of a "plumbing" command, although I suspect you'll be fine either way. Note that you need the same extra text with --stat when using git diff-tree. The essential difference between using the git diff "porcelain" front end, and the git diff-tree plumbing command, is that git diff looks up your configured settings for options like diff.renames to decide whether to do rename detection. Well, that, plus the front end git diff will do the equivalent of git diff-index if you're comparing a commit with the index, for instance. In other words, git diff reads your config and invokes the right plumbing automatically.)

Solution 2 - Git

For script processing, it might be better to use one of the following:

# list just the file names
git diff --name-only
path/to/modified/file
path/to/renamed/file


# list the names and change statuses:
git diff --name-status
M       path/to/modified/file
R100    path/to/existing/file   path/to/renamed/file


# list a diffstat-like output (+ed lines, -ed lines, file name):
git diff --numstat
1       0       path/to/modified/file
0       0       path/to/{existing => renamed}/file

These each become more handy for robust script processing when combined with the -z option, which uses NUL as the field terminators.

Solution 3 - Git

For Bash users, you can use the $COLUMNS variable to automatically fill the available terminal width:

git diff --stat=$COLUMNS

Very long path names might still be truncated; in this case, you can reduce the width of the +++/--- part using --stat-graph-width, for example this limits it to 1/5 of the terminal width:

git show --stat=$COLUMNS --stat-graph-width=$(($COLUMNS/5))

For a more generic solution, you could use the output of tput cols to determine the terminal width.

Solution 4 - Git

There’s an option --name-only: git diff --name-only. The option is also supported by other git commands like show and stash.

Paths don’t get shortened with the option.

Solution 5 - Git

A simple solution I found was to do this: (only works on *nix, sorry no osx)

git diff --stat=$COLUMNS --relative | head -n -1 | cut -c 2- | xargs -d '\n' -P4 printf "$(pwd)/%s\n"

This version works for both, but it doesn't look great on osx.

git diff --stat=$COLUMNS --relative | sed -e '$ d' | cut -c 2- | xargs -n4 -I{} echo "$(pwd)/{}"

Solution 6 - Git

git diff is a porcelain (user friendly) command. For scripting purposes, you probably want to use the corresponding plumbing command git diff-tree.

You can get git diff-tree to output the full paths, relative to the git repository, using a combination of the --name-only, -r and --no-commit-id options.

Examples

Paths of files changed in the "last" (the HEAD) commit of the current branch.

git diff-tree --name-only -r --no-commit-id HEAD

Paths of files in the last commit on the main branch

git diff-tree --name-only -r --no-commit-id main

Paths of files of the last three commits on the main branch

git diff-tree --name-only -r main main~3

Paths of the files of the last commit under path src/

git diff-tree --name-only -r --no-commit-id main src/

Absolute paths of the files changed in the last commit on the current branch

git diff-tree --name-only -r --no-commit-id --line-prefix=`git rev-parse --show-toplevel`/ HEAD

Explanation

git diff-tree compares the blobs of two treeish objects.

A commit is a treeish object, which points to the objects in the repository root. Directories are also treeish objects whereas files are blobs.

Running git diff-tree HEAD will compare the blobs of HEAD and HEAD~1 and contain the difference in blobs of the repository root. To see all the changed files that are not in the root, we need to descend into the directory treeish objects. This is achieved using the -r (as in recurse) option.

Note that this allows one two compare arbitrary directories in arbitrary commits.

By default, if only one commit object is specified, it's compared to its parent. Ie, running git diff-tree HEAD is equivalent to git diff-tree HEAD HEAD~1. If you only specified one commit as the treeish object, the parent commit id is displayed. Using --no-commit-id gets rid of this.

git-diff-tree prints a lot of information we don't want (ids, permissions, whether it's an add, delete, modification). We just want the name, so we use --name-only.

If we wanted absoluted paths, we need to prefix all lines using something like git rev-parse --show-toplevel. This gets the absolute path of the repository, without the trailing /. So we add that.

--line-prefix=`git rev-parse --show-toplevel`/

Solution 7 - Git

I created the following git alias:

diffstat = ! "gitdiffstat() {  git diff --stat=$(tput cols) ${1:-master} ; }; gitdiffstat"

It reads the column count from the tput cols command. It defaults to diffing against master, but you can optionally specify another branch.

$ git diffstat
 .gitalias | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Solution 8 - Git

I found that the behaviour of diff --stat changed somewhere around git 1.7.10 where previously it would shorten file paths to a fixed width by default - it now displays as much as your terminal window will allow. If you are experiencing this problem, make sure you upgrade to 1.8.0 or newer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBadriView Question on Stackoverflow
Solution 1 - GittorekView Answer on Stackoverflow
Solution 2 - GitcmbuckleyView Answer on Stackoverflow
Solution 3 - GitJohn MellorView Answer on Stackoverflow
Solution 4 - GitYevhen PavliukView Answer on Stackoverflow
Solution 5 - GitJavier BuzziView Answer on Stackoverflow
Solution 6 - GitCervEdView Answer on Stackoverflow
Solution 7 - Gituser151841View Answer on Stackoverflow
Solution 8 - GitAlex SpurlingView Answer on Stackoverflow