ChatGPT解决这个技术问题 Extra ChatGPT

How to have 'git log' show filenames like 'svn log -v'

SVN's log has a "-v" mode that outputs filenames of files changed in each commit, like so:

jes5199$ svn log -v
------------------------------------------------------------------------
r1 |   jes5199 | 2007-01-03 14:39:41 -0800 (Wed, 03 Jan 2007) | 1 line
Changed paths:
   A /AUTHORS
   A /COPYING
   A /ChangeLog
   A /EVOLUTION
   A /INSTALL
   A /MacOSX

Is there a quick way to get a list of changed files in each commit in Git?

Wonder why git log doesn't just support a -v switch like so many expect/want? </gripe>

P
Peter Mortensen

For full path names of changed files:

git log --name-only

For full path names and status of changed files:

git log --name-status

For abbreviated pathnames and a diffstat of changed files:

git log --stat

There are a lot more options. Check out the documentation.


I use git log --numstat. See git help log for more options.
git log --name-only --oneline is pretty spiffy too - one colored line for the commit, and one file per line. stackoverflow.com/a/14227496/1995714
With git 2.7.3, I had to use git log --name-status --find-renames for it to show renamed files instead of addition + deletion.
Note that --stat abbreviates long paths; width is configurable but wrapped histograms are harder to read. Other formats like --numstat always print full paths.
@ma11hew28 Thanks. --numstat is at line 946 of that man page as of git 2.22.00. That's a lot more options than most people need.
s
slm

NOTE: git whatchanged is deprecated, use git log instead

New users are encouraged to use git-log[1] instead. The whatchanged command is essentially the same as git-log[1] but defaults to show the raw format diff output and to skip merges. The command is kept primarily for historical reasons; fingers of many people who learned Git long before git log was invented by reading Linux kernel mailing list are trained to type it.

You can use the command git whatchanged --stat to get a list of files that changed in each commit (along with the commit message).

References

https://git-scm.com/docs/git-whatchanged


p
ptc

git show is also a great command.

It's kind of like svn diff, but you can pass it a git commit hash and see that diff.


It's not the GUID of the commit but its SHA1 hash.
Perhaps update your answer, addressing brainplot's comment? But without "Edit:", "Update:", or similar - the answer should appear as if it was written today.
Updated, sorry for the 10+ years of confusion :)
H
Hazok

If you want to get the file names only without the rest of the commit message you can use:

git log --name-only --pretty=format: <branch name>

This can then be extended to use the various options that contain the file name:

git log --name-status --pretty=format: <branch name>

git log --stat --pretty=format: <branch name>

One thing to note when using this method is that there are some blank lines in the output that will have to be ignored. Using this can be useful if you'd like to see the files that have been changed on a local branch, but is not yet pushed to a remote branch and there is no guarantee the latest from the remote has already been pulled in. For example:

git log --name-only --pretty=format: my_local_branch --not origin/master

Would show all the files that have been changed on the local branch, but not yet merged to the master branch on the remote.


Note on whitespace in the above examples - it's like, git log --stat --pretty="format:" $branchName. So for example, git log --stat --pretty="format:" $(git rev-parse --abbrev-ref HEAD). While I'm at it, here's the exact incantation that wound up being relevant to my purpose: git log --name-only --pretty="format: " master..$(git rev-parse --abbrev-ref HEAD)
c
cxw

I use this on a daily basis to show history with files that changed:

git log --stat --pretty=short --graph

To keep it short, add an alias in your .gitconfig by doing:

git config --global alias.ls 'log --stat --pretty=short --graph'

Mine is very close to that, git log --pretty=oneline --graph --name-status. I find it more concise, just showing the list of the files that changed.
@Thanks, the --stat flag part causes showing the files and total stats number of changed files, whereas yours --name-status part similarly, but even better, showing only files
s
scc

I use this:

git log --name-status <branch>..<branch> | grep -E '^[A-Z]\b' | sort | uniq

which outputs a list of files only and their state (added, modified, deleted):

A   sites/api/branding/__init__.py
M   sites/api/branding/wtv/mod.py
...

A
Amitesh Bharti

This short command is very helpful to list all the files changed per commit.

git log --name-only --oneline

--name-only

Show only names of changed files. The file names are often encoded in UTF-8. For more information see the discussion about encoding in the git-log1 manual page.

--oneline

This is a shorthand for "--pretty=oneline --abbrev-commit" used together.

https://i.stack.imgur.com/znJus.png


P
Peter Mortensen

git diff --stat HEAD^! shows changed files and added/removed line counts for the last commit (HEAD).

It seems to me that there isn't any single command to get concise output consisting only of filenames and added and removed line counts for several commits at once, so I created my own Bash script for that:

#!/bin/bash
for ((i=0; i<=$1; i++))
do
    sha1=`git log -1 --skip=$i --pretty=format:%H`
    echo "HEAD~$i $sha1"
    git diff --stat HEAD~$(($i+1)) HEAD~$i
done

It is to be called, for example, ./changed_files 99 to get the changes in a concise form from HEAD to HEAD~99. It can be piped, for example, to less.


Can't you do git diff --stat HEAD..master to show the difference between HEAD and master, or didn't this exist when you posted your answer back in 2012?
@Ferrybig OP's question is about how "to get a list of changed files in each commit", not about the diff between HEAD and master. Those are two different things.
J
JamesThomasMoon

A summary of answers with example output

This is using a local repository with five simple commits.

‣ git log --name-only
commit ed080bc88b7bf0c5125e093a26549f3755f7ae74 (HEAD -> master)
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:46:04 2019 -0700

    mv file4 to file5

file5

commit 5c4e8cfbe3554fe3d7d99b5ae4ba381fa1cdb328
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:36:32 2019 -0700

    foo file1

    really important to foo before the bar

file1

commit 1b6413400b5a6a96d062a7c13109e6325e081c85
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:34:37 2019 -0700

    foobar file2, rm file3

file2
file3

commit e0dd02ce23977c782987a206236da5ab784543cc
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:33:05 2019 -0700

    Add file4

file4

commit b58e85692f711d402bae4ca606d3d2262bb76cf1
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:32:41 2019 -0700

    Added files

file1
file2
file3

‣ git log --name-status
commit ed080bc88b7bf0c5125e093a26549f3755f7ae74 (HEAD -> master)
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:46:04 2019 -0700

    mv file4 to file5

R100    file4   file5

commit 5c4e8cfbe3554fe3d7d99b5ae4ba381fa1cdb328
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:36:32 2019 -0700

    foo file1

    really important to foo before the bar

M       file1

commit 1b6413400b5a6a96d062a7c13109e6325e081c85
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:34:37 2019 -0700

    foobar file2, rm file3

M       file2
D       file3

commit e0dd02ce23977c782987a206236da5ab784543cc
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:33:05 2019 -0700

    Add file4

A       file4

commit b58e85692f711d402bae4ca606d3d2262bb76cf1
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:32:41 2019 -0700

    Added files

A       file1
A       file2
A       file3

‣ git log --stat
commit ed080bc88b7bf0c5125e093a26549f3755f7ae74 (HEAD -> master)
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:46:04 2019 -0700

    mv file4 to file5

 file4 => file5 | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

commit 5c4e8cfbe3554fe3d7d99b5ae4ba381fa1cdb328
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:36:32 2019 -0700

    foo file1

    really important to foo before the bar

 file1 | 3 +++
 1 file changed, 3 insertions(+)

commit 1b6413400b5a6a96d062a7c13109e6325e081c85
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:34:37 2019 -0700

    foobar file2, rm file3

 file2 | 1 +
 file3 | 0
 2 files changed, 1 insertion(+)

commit e0dd02ce23977c782987a206236da5ab784543cc
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:33:05 2019 -0700

    Add file4

 file4 | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

commit b58e85692f711d402bae4ca606d3d2262bb76cf1
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:32:41 2019 -0700

    Added files

 file1 | 0
 file2 | 0
 file3 | 0
 3 files changed, 0 insertions(+), 0 deletions(-)

‣ git log --name-only --oneline
ed080bc (HEAD -> master) mv file4 to file5
file5
5c4e8cf foo file1
file1
1b64134 foobar file2, rm file3
file2
file3
e0dd02c Add file4
file4
b58e856 Added files
file1
file2
file3

‣ git log --pretty=oneline --graph --name-status
* ed080bc88b7bf0c5125e093a26549f3755f7ae74 (HEAD -> master) mv file4 to file5
| R100  file4   file5
* 5c4e8cfbe3554fe3d7d99b5ae4ba381fa1cdb328 foo file1
| M     file1
* 1b6413400b5a6a96d062a7c13109e6325e081c85 foobar file2, rm file3
| M     file2
| D     file3
* e0dd02ce23977c782987a206236da5ab784543cc Add file4
| A     file4
* b58e85692f711d402bae4ca606d3d2262bb76cf1 Added files
  A     file1
  A     file2
  A     file3

‣ git diff-tree HEAD
ed080bc88b7bf0c5125e093a26549f3755f7ae74
:100644 000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 D  file4
:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A  file5

‣ git log --stat --pretty=short --graph
* commit ed080bc88b7bf0c5125e093a26549f3755f7ae74 (HEAD -> master)
| Author: My Name <user@email.com>
| 
|     mv file4 to file5
| 
|  file4 => file5 | 0
|  1 file changed, 0 insertions(+), 0 deletions(-)
| 
* commit 5c4e8cfbe3554fe3d7d99b5ae4ba381fa1cdb328
| Author: My Name <user@email.com>
| 
|     foo file1
| 
|  file1 | 3 +++
|  1 file changed, 3 insertions(+)
| 
* commit 1b6413400b5a6a96d062a7c13109e6325e081c85
| Author: My Name <user@email.com>
| 
|     foobar file2, rm file3
| 
|  file2 | 1 +
|  file3 | 0
|  2 files changed, 1 insertion(+)
| 
* commit e0dd02ce23977c782987a206236da5ab784543cc
| Author: My Name <user@email.com>
| 
|     Add file4
| 
|  file4 | 0
|  1 file changed, 0 insertions(+), 0 deletions(-)
| 
* commit b58e85692f711d402bae4ca606d3d2262bb76cf1
  Author: My Name <user@email.com>

      Added files

   file1 | 0
   file2 | 0
   file3 | 0
   3 files changed, 0 insertions(+), 0 deletions(-)

‣ git log --name-only --pretty=format:
file5

file1

file2
file3

file4

file1
file2
file3

‣ git log --name-status --pretty=format:
R100    file4   file5

M       file1

M       file2
D       file3

A       file4

A       file1
A       file2
A       file3

‣ git diff --stat 'HEAD^!'
 file4 => file5 | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

‣ git show
commit ed080bc88b7bf0c5125e093a26549f3755f7ae74 (HEAD -> master)
Author: My Name <user@email.com>
Date:   Mon Oct 21 15:46:04 2019 -0700

    mv file4 to file5

diff --git a/file4 b/file5
similarity index 100%
rename from file4
rename to file5

Credits to @CB-Bailey @Peter-Suwara @Gaurav @Omer-Dagan @xsor @Hazok @nrz @ptc


P
Peter Mortensen

I find the following is the ideal display for listing what files changed per commit in a concise format:

git log --pretty=oneline --graph --name-status

Thanks, exactly what i was looking for. I would alsoe suggest using pretty format like 'git log --pretty="format:%n %cn %s %cr" --graph --name-status' hansrobo.github.io/cheatsheets/git-log-format
O
Omer Dagan

Another useful command would be git diff-tree <hash> where hash can be also a hash range (denoted by <old>..<new> notation). An output example:

$ git diff-tree  HEAD
:040000 040000 8e09a be406 M myfile

The fields are:

source mode, destination mode, source hash, destination hash, status, and filename

Statuses are the ones you would expect: D (deleted), A (added), M (modified), etc. See the man page for full description


I tried this, but it only gave the M status for files in the root of the repo. So for files in a dir it would only give ":xxxx yyy zzz aaa M dirname"
P
Peter Mortensen

I generally use these to get the logs:

$ git log --name-status --author='<Name of author>' --grep="<text from Commit message>"

$ git log --name-status --grep="<text from Commit message>"

I didn't know about these options, but this post would be more useful if it explained that it filters the log. For a moment there, I thought it was a way to change the way authors are listed in the output.
M
Manoj

I am using:

git diff-tree -v --name-status -r <commit-id>

And it shows very similar output like svn log -v