3789

How do I view the history of an individual file with complete details of what has changed?

git log -- [filename] shows me the commit history of a file, but how do I see the file content that changed?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Richard
  • 39,052
  • 6
  • 25
  • 29

27 Answers27

2890

This lets Git generate the patches for each log entry:

git log -p -- filename

See git help log for more options — it can actually do a lot of nice things. :)


To get just the diff for a specific commit, use

git show HEAD

or specify any other revision by identifier.


To browse the changes visually:

gitk
Muhammad Asadullah
  • 3,735
  • 1
  • 22
  • 38
VolkA
  • 34,983
  • 7
  • 37
  • 37
2687

For a graphical view, use gitk:

gitk [filename]

To follow the file across file renames:

gitk --follow [filename]
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Claudio Acciaresi
  • 31,951
  • 5
  • 33
  • 43
  • 36
    But I rather even have a tool that combined the above with 'git blame' allowing me to browse the source of a file as it changes in time... – Egon Willighagen Apr 06 '10 at 15:50
  • 2
    GitWeb is the answer to that. – Jonas Byström Feb 17 '11 at 17:16
  • 29
    Unfortunately, this doesn't follow the history of the file past renames. – Dan Moulding Mar 30 '11 at 23:17
  • 154
    I was also looking for the history of files that were previously renamed and found this thread first. The solution is to use "git log --follow " as Phil pointed out [here](http://stackoverflow.com/questions/1430749/getting-git-to-acknowledge-previously-moved-files). – Florian Gutmann Apr 26 '11 at 09:05
  • 130
    The author was looking for a command line tool. While gitk comes with GIT, it's neither a command line app nor a particularly good GUI. – mikemaccana Jul 18 '11 at 15:17
  • 3
    Nice tip. In my machine (git v1.7.10) I had to use `gitk -- [filename]`. – n0nick Jul 31 '12 at 14:07
  • 79
    Was he looking for a command line tool? "right click -> show history" certainly doesn't imply it. – hdgarrood May 13 '13 at 14:57
  • 5
    Caution Windows users... The filename path is case sensitive – MattSlay Sep 23 '13 at 16:17
  • 5
    @DanMoulding: `gitk --follow [filename]` shows the history of the file past renames. It doesn't show the file content's changes before the renaming, though. See [this](https://stackoverflow.com/questions/278192/view-the-change-history-of-a-file-using-git-versioning#answer-13730108) answer. – Matthias Braun Feb 20 '14 at 15:07
  • 1
    if this file is deleted, and you want to find who delete it, shoud use `git log -- [filename]` – hiway Apr 16 '14 at 02:50
  • 6
    not looking for anything else other than git, this should not be the accepted answer – Cosmin Apr 28 '15 at 14:30
  • 28
    `gitk` is not part of the basic git package. You need to download the tk package to use gitk. @VolkA's answer is better, `git log -p filename` works without any dependencies. – aaron-coding Jan 22 '16 at 21:12
  • 4
    The question was "View the change history of a file using Git versioning". This is exactly what gitk does. It looks up the git commit history for changes. I don't care if it is part of the basic git package as long as it does the job in a fast and simple way. – Mike76 Aug 09 '16 at 18:13
  • 2
    @HenriquedeSousa: Because the asker felt that this answer was the most helpful *to him*. – Martin Bonner supports Monica Aug 24 '16 at 09:28
  • gitk works like a charm. it helped me checking the history of a single file, exactly what I needed. – sunlover3 Sep 28 '16 at 09:36
  • 1
    Is there any way to do this using gitGUI? – Preshan Pradeepa Jul 16 '17 at 07:01
  • 2
    downvote due to the use of another tool, better use the standard cli from the answer https://stackoverflow.com/a/278242/1700569 – coolxeo Nov 23 '17 at 16:11
  • 2
    The accepted answer should take into account not everyone has gitk installed on their system. If I was in a CLI-only environment there would be no GUI available. OP asked to use the "git" command. Using gitweb, gitk, or whatever is the same as saying "just go to GitHub and check history there". – Martin Jan 24 '18 at 09:15
  • 1
    This answer shouldn't be the accepted one imo. I personally use Gitx, not Gitk, but I wouldn't want a Gitx-specific answer either. The `git log -p` answer below is much more applicable to a majority of users. – D G May 22 '18 at 13:57
  • independent of what the accepted answer should be, +1 for facilitating gitk mind blown action – frostini Sep 11 '18 at 11:48
  • 2
    What's `gitk` ? – Jim Aho Nov 15 '18 at 19:58
  • 1
    @JimAho git visualization tool – ncopiy Apr 02 '19 at 13:16
  • 2
    why that answer marks as right if it suggests using a third-party utility? the right answer stays below ( @DanMoulding is author) – ncopiy Apr 02 '19 at 13:18
  • If you come, as I do, from a Windows background and are unsure what `gitk` is, you'll find it as part of `Git for Windows`. Launch from the `git-bash.exe` application (a Linux command-line emulator). `Git for Windows`, `git bash` and `gitk` are awesome... – AlainD Mar 05 '21 at 01:12
  • This is the best answer – Dimitris Thomas Jun 02 '21 at 21:23
  • I get "bad arguments to gitk invalid object name 'c'" – David Klempfner Oct 25 '22 at 02:43
1760
git log --follow -p -- path-to-file

This will show the entire history of the file (including history beyond renames and with diffs for each change).

In other words, if the file named bar was once named foo, then git log -p bar (without the --follow option) will only show the file's history up to the point where it was renamed -- it won't show the file's history when it was known as foo. Using git log --follow -p bar will show the file's entire history, including any changes to the file when it was known as foo. The -p option ensures that diffs are included for each change.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Dan Moulding
  • 211,373
  • 23
  • 97
  • 98
  • I find it a bit weird but you cannot use `-CC` flag with `log --follow file` or it will find nothing (git 1.7.0.4). – Mikko Rantalainen Feb 09 '12 at 12:45
  • 23
    --stat is also helpful. You can use it together with -p. – Raffi Khatchadourian May 09 '12 at 22:29
  • 34
    I agree this is the REAL answer. (1.) `--follow` ensures that you see file renames (2.) `-p` ensures that you see how the file gets changed (3.) it is command line only. – Trevor Boyd Smith Sep 11 '12 at 18:54
  • 2
    Add a `--` before your `file`, and this would be absolutely the best answer! – NHDaly Mar 03 '14 at 21:25
  • 1
    Wow. It works for me. http://stackoverflow.com/a/1321962/3034747 and http://stackoverflow.com/a/5493663/3034747 is not. I dont know why.. I'm using ubuntu and GIT version 2.0.2 – Yana Agun Siswanto Dec 08 '14 at 06:41
  • "fatal: ambiguous argument 'my_file_name': unknown revision or path not in the working tree." – Sarah Vessels Mar 09 '15 at 15:27
  • 5
    @NHDaly I notice that the `--` was added, but I don't know why this makes it best? What is it that it does? – Benjohn May 27 '15 at 15:10
  • 54
    @Benjohn The `--` option tells Git that it has reached the end of the options and that anything that follows `--` should be treated as an argument. For `git log` this only makes any difference if you have a path name that begins with a *dash*. Say you wanted to know the history of a file that has the unfortunate name "--follow": `git log --follow -p -- --follow` – Dan Moulding May 28 '15 at 16:10
  • 11
    @Benjohn: Normally, the `--` is useful because it can also guard against any `revision` names that match the filename you've entered, which can actually be scary. For example: If you had both a branch and a file named `foo`, `git log -p foo` would show the git log history up to `foo`, not the history for the *file* `foo`. But @DanMoulding is right that since the `--follow` command only takes a single filename as its argument, this is less necessary since it can't be a `revision`. I just learned that. Maybe you were right to leave it out of your answer then; I'm not sure. – NHDaly May 30 '15 at 06:03
  • 2
    It's crazy how far down the long page of documentation for [git log](https://git-scm.com/docs/git-log) one has to read before the section "Generating patches with -p". This answer does a great job explaining `--follow` it would be useful to explain `-p` too. – dumbledad Feb 20 '16 at 09:59
  • 1
    actually @JohnLawrenceAspden brought up a good point (in his answer) to also include `--all` to see the file history in all branches. might be useful in some cases. – cregox Mar 18 '17 at 09:46
  • 1
    Be careful not to type the filename wrongly (I forgot an "s" at the end of my filename) You will see a message in the git log, `skipping...` followed by series of tildes `~` (presumably one for each commit/ I dunno). – Nate Anderson Dec 21 '17 at 14:11
  • Throwing error. `fatal: unrecognized argument: --folow`. But the command `git log -p ` worked. – Asim K T Jul 29 '18 at 02:37
  • I get: `fatal: --follow requires exactly one pathspec` – David Klempfner Oct 25 '22 at 02:45
206

tig is a terminal-based viewer with color support similar to the GUI-based gitk.

Quick Install:

  • APT: apt-get install tig
  • Homebrew (OS X): $ brew install tig

Use it to view history on a single file: tig [filename]

Or browse the detailed repository history via: tig

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Falken
  • 2,528
  • 2
  • 17
  • 10
  • 29
    Excellent text-based tool, great answer. I freaked out when I saw the dependencies for gitk installing on my headless server. Would upvote again A+++ – Tom McKenzie Oct 24 '12 at 05:28
  • 1
    You can look at specific files with tig too, i.e. `tig -- path/to/specific/file` – gloriphobia Oct 27 '17 at 12:05
  • To show all changes for a file, including renames, use `tig --follow filename`. Thank you so much @falken for helping us discover such a wonderful TUI tool. – GMaster Jul 10 '22 at 05:50
129

git whatchanged -p filename is also equivalent to git log -p filename in this case.

You can also see when a specific line of code inside a file was changed with git blame filename. This will print out a short commit id, the author, timestamp, and complete line of code for every line in the file. This is very useful after you've found a bug and you want to know when it was introduced (or whose fault it was).

danronmoon
  • 3,814
  • 5
  • 34
  • 56
farktronix
  • 3,880
  • 1
  • 21
  • 27
  • 15
    "New users are encouraged to use git-log instead. (...) The command is kept primarily for historical reasons;" – ciastek Mar 18 '14 at 08:03
123

Sourcetree users

If you use Sourcetree to visualize your repository (it's free and quite good) you can right click a file and select Log Selected

Enter image description here

The display (below) is much friendlier than gitk and most the other options listed. Unfortunately (at this time) there is no easy way to launch this view from the command line — Sourcetree's CLI currently just opens repositories.

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mark Fox
  • 8,694
  • 9
  • 53
  • 75
  • 1
    I particularly like the option "Follow renamed files", which allows you to see if a file was renamed or moved. – Chris Mar 13 '15 at 13:07
  • but unless i'm mistaken (please let me know!), one can only compare two versions at a time in the gui? Are there any clients which have an elegant interface for diffing several different versions at once? Possibly with a zoom-out view like in Sublime Text? That would be really useful I think. – Sam Lewallen Jun 30 '15 at 06:16
  • @SamLewallen If I understand correctly you want to compare three different commits? This sounds similar to a three-way merge (mine, yours, base) — usually this strategy is used for resolving merge conflicts not necessarily comparing three arbitrary commits. There are many tools that support three way merges http://stackoverflow.com/questions/10998728/view-already-committed-git-merge-in-external-3-way-diff-tool but the trick is feeding these tools the specific revisions http://gitready.com/intermediate/2009/02/27/get-a-file-from-a-specific-revision.html – Mark Fox Jun 30 '15 at 18:47
  • You save my life. You can use `gitk` to find the `SHA1` hash, and then open `SourceTree` to enter `Log Selected..` based on the found `SHA1`. – AechoLiu Jan 25 '18 at 06:58
  • It's perfect. I searched the same solution on ATLASSIAN Community https://community.atlassian.com/t5/Sourcetree-questions/File-history-revision/qaq-p/433654 – 夜一林风 Mar 22 '18 at 06:36
  • @AechoLiu What do you need the SHA for if you already have the file name? (Anyway, if you do need the SHA, you can find it with SourceTree too.) – Marnen Laibow-Koser Mar 13 '19 at 23:14
  • 1
    @MarnenLaibow-Koser I cannot remember why I need the SHA at that time. Ahaha. – AechoLiu Mar 14 '19 at 00:30
  • This is the best answer. – David Klempfner Oct 25 '22 at 02:47
75

To show what revision and author last modified each line of a file:

git blame filename

or if you want to use the powerful blame GUI:

git gui blame filename
Colin D Bennett
  • 11,294
  • 5
  • 49
  • 66
yllohy
  • 777
  • 5
  • 2
  • 1
    The blame commands do not show information about deleted code. Looking at each commit through gitk or tig shows that. – vezun Jun 02 '21 at 15:58
67

Summary of other answers after reading through them and playing a bit:

The usual command line command would be

git log --follow --all -p dir/file.c

But you can also use either gitk (GUI) or tig (text UI) to give much more human-readable ways of looking at it.

gitk --follow --all -p dir/file.c

tig --follow --all -p dir/file.c

Under Debian/Ubuntu, the install command for these lovely tools is as expected:

sudo apt-get install gitk tig

And I'm currently using:

alias gdf='gitk --follow --all -p'

so that I can just type gdf dir to get a focussed history of everything in subdirectory dir.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Lawrence Aspden
  • 17,124
  • 11
  • 67
  • 110
  • 2
    I think this is a great answer. Maybe you arent getting voted as well because you answer other ways (IMHO better) to see the changes i.e. via gitk and tig in addition to git. – PopcornKing Feb 25 '13 at 17:11
  • Just to add to answer. Locate the path (in git space, up to which exists in repository still). Then use the command stated above "git log --follow --all -p ". There may be the case, that the filde/folder would have been removed over the history, hence locate the maximum path that exists still, and try to fetch its history. works ! – parasrish Aug 16 '16 at 10:04
  • 3
    `--all` is for all branches, the rest is explained in @Dan's answer – cregox Mar 18 '17 at 09:44
  • 1
    Oh man, after so long time looking for good solution to track file beyond renames, finally, I found it here. Works like charm! Thanks! – xZero Mar 08 '19 at 14:34
31

You can use Visual Studio Code with GitLens. It's a very powerful tool.

After having installed GitLens, go to GitLens tab, select FILE HISTORY and you can browse it.

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
foxiris
  • 3,125
  • 32
  • 32
29

Add this alias to your .gitconfig:

[alias]
    lg = log --all --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'\n--abbrev-commit --date=relative

And use the command like this:

> git lg
> git lg -- filename

The output will look almost exactly the same as the gitk output. Enjoy.

Palesz
  • 2,104
  • 18
  • 20
  • After I ran that lg shortcut, I said (and I quote) "Beautiful!". However, note that the "\n" after "--graph" is an error. – jmbeck Jul 22 '13 at 14:40
  • 3
    Also can be used `git lg -p filename` - it returns a beautiful diff of searched file. – Egel Mar 27 '15 at 12:11
25

Lately I discovered tig and found it very useful. There are some cases I'd wish it does A or B but most of the time it's rather neat.

For your case, tig <filename> might be what you're looking for.

https://jonas.github.io/tig/

li ki
  • 342
  • 3
  • 11
lang2
  • 11,433
  • 18
  • 83
  • 133
17

You can also try this which lists the commits that has changed a specific part of a file (implemented in Git 1.8.4).

The result returned would be the list of commits that modified this particular part. Command:

git log --pretty=short -u -L <upperLimit>,<lowerLimit>:<path_to_filename>

where upperLimit is the start line number and lowerLimit is the ending line number of the file.

More details are at http://techpurohit.in/list-some-useful-git-commands.

jitendrapurohit
  • 9,435
  • 2
  • 28
  • 39
16

In the Sourcetree UI, you can find the history of a file by selecting the 'Log Selected' option in the right click context menu:

Enter image description here

It would show the history of all the commits.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
savvyBrar
  • 207
  • 2
  • 4
15

I wrote git-playback for this exact purpose

pip install git-playback
git playback [filename]

This has the benefit of both displaying the results in the command line (like git log -p) while also letting you step through each commit using the arrow keys (like gitk).

Jian
  • 10,320
  • 7
  • 38
  • 43
14

Or:

gitx -- <path/to/filename>

if you're using gitx

George Anderson
  • 972
  • 8
  • 14
9

If you want to see the whole history of a file, including on all other branches use:

gitk --all <filename>
Adi Shavit
  • 16,743
  • 5
  • 67
  • 137
8

If you're using the Git GUI (on Windows):

Under the Repository menu, you can use Visualize master's History.

Highlight a commit in the top pane and a file in the lower right and you'll see the diff for that commit in the lower left.

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
cori
  • 8,666
  • 7
  • 45
  • 81
  • 3
    How does this answer the question? – jmbeck Jul 22 '13 at 14:42
  • 3
    Well, OP didn't specify command line, and moving from SourceSafe (which is a GUI) it seemed relevant to point out that you could do pretty much the same thing that you can do in VSS in the Git GUI on Windows. – cori Jul 22 '13 at 15:34
7

With the excellent Git Extensions, you go to a point in the history where the file still existed (if it have been deleted, otherwise just go to HEAD), switch to the File tree tab, right-click on the file and choose File history.

By default, it follows the file through the renames, and the Blame tab allows to see the name at a given revision.

It has some minor gotchas, like showing fatal: Not a valid object name in the View tab when clicking on the deletion revision, but I can live with that. :-)

li ki
  • 342
  • 3
  • 11
PhiLho
  • 40,535
  • 6
  • 96
  • 134
  • Worth noting that this is Windows-only. – Evan Hahn May 09 '13 at 20:39
  • 3
    @EvanHahn not accurate, via mono one can use GitExtension also on Linux, we use it on ubuntu and quite happy w/ it. see http://git-extensions-documentation.readthedocs.org/en/latest/getting_started.html – Shmil The Cat Aug 09 '15 at 17:42
6

SmartGit:

  1. In the menu enable to display unchanged files: View / Show unchanged files
  2. Right click the file and select 'Log' or press 'Ctrl-L'
Antonín Slejška
  • 1,980
  • 4
  • 29
  • 39
6

To get all commits for a specific file use this command:

git rev-list HEAD --oneline FileName


For example

git rev-list HEAD --oneline index.html

Output

7a2bb2f update_index_with_alias
6c03e56 update_changes
e867142 Revert "add_paragraph"

If you want to view the changes that make on the file

git log -p fileName

See gif imagegit commits for specific files

Eng_Farghly
  • 1,987
  • 1
  • 23
  • 34
6

The answer I was looking for wasn't here. It was to see changes in files that I'd staged for commit. I.e.,

git diff --cached
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Malks
  • 952
  • 1
  • 11
  • 11
  • 1
    If you want to include local (unstaged) changes, I often run `git diff origin/master` to show the complete differences between your local branch and the master branch (which can be updated from remote via `git fetch`) – hayesgm Jul 21 '13 at 19:47
  • And to limit this to a particular file, you can use `git diff --cached path/to/file.xml` – Woodchuck Nov 11 '22 at 22:47
5

If you use TortoiseGit you should be able to right click on the file and do TortoiseGit --> Show Log. In the window that pops up, make sure:

  • 'Show Whole Project' option is not checked.

  • 'All Branches' option is checked.

Noam Manos
  • 15,216
  • 3
  • 86
  • 85
user3885927
  • 3,363
  • 2
  • 22
  • 42
  • TortoiseGit (and Eclipse Git as well) somehow misses revisions of the selected file, don't count on it! – Noam Manos Nov 30 '15 at 10:54
  • @NoamManos, I haven't encountered that issue, so I cannot verify if your statement is correct. – user3885927 Nov 30 '15 at 23:20
  • My mistake, it only happens in Eclipse, but in TortoiseGit you can see all revisions of a file if unchecking "show all project" + checking "all branches" (in case the file was committed on another branch, before it was merged to main branch). I'll update your answer. – Noam Manos Dec 01 '15 at 12:06
4

git diff -U <filename> give you a unified diff.

It should be colored on red and green. If it's not, run: git config color.ui auto first.

Lukasz Czerwinski
  • 13,499
  • 10
  • 55
  • 65
4

How to manually view the change history of a file graphically in meld

If you want to just see which commits changed a file, so you can do git difftool on them to graphically see the changes with meld (as I explain here), do this instead:

git log --follow --oneline -- path/to/file.c

Sample run and output:

eRCaGuy_hello_world$ git log --follow --oneline -- c/alsa_aplay__play_tone_sound_WIP.c
04b67fb (HEAD -> master) Update c/alsa_aplay__play_tone_sound_WIP.c
301122a wip: alsa_aplay__play_tone_sound.c: finish initial version of program
d4e8092 wip: add c/alsa_aplay__play_tone_sound.c

Now I can just look at the last changes graphically in meld like this (pulling the commit hashes from the output above).

Note that I intentionally leave off the filename so that it can properly track the file automatically for me since the file was renamed, and I know these commits likely only edited this file anyway:

# just the last change
git difftool 04b67fb~..04b67fb

# and the one before that
git difftool 301122a~..301122a

# ...and before that
git difftool d4e8092~..d4e8092

If you need to specify the filename, just do so with:

git difftool 04b67fb~..04b67fb -- path/to/file.c
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
2

If you are using Eclipse with the Git plugin, it has an excellent comparison view with history. Right click the file and select "Compare With" → "History".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
AhHatem
  • 1,415
  • 3
  • 14
  • 23
2

You can use git log command as the following:

git log -L 992,+4:path-to-file

Explanation: Here the 992 shows the line number you want to see the revision information, +4 indicates how many lines you want to see after the specified line 992. And lastly path-to-file , it generally starts with ./src/..

user12256545
  • 2,755
  • 4
  • 14
  • 28
oktemerbay
  • 61
  • 5
1

I'm probably about where the OP was when this started, looking for something simple that would let me use git difftool with vimdiff to review changes to files in my repo starting from a specific commit. I wasn't too happy with answers I was finding, so I threw this git incremental reporter (gitincrep) script together and it's been useful to me:

#!/usr/bin/env bash

STARTWITH="${1:-}"
shift 1

DFILES=( "$@" )

RunDiff()
{
        GIT1=$1
        GIT2=$2
        shift 2

        if [ "$(git diff $GIT1 $GIT2 "$@")" ]
        then
                git log ${GIT1}..${GIT2}
                git difftool --tool=vimdiff $GIT1 $GIT2 "$@"
        fi
}

OLDVERS=""
RUNDIFF=""

for NEWVERS in $(git log --format=format:%h  --reverse)
do
        if [ "$RUNDIFF" ]
        then
                RunDiff $OLDVERS $NEWVERS "${DFILES[@]}"
        elif [ "$OLDVERS" ]
        then
                if [ "$NEWVERS" = "${STARTWITH:=${NEWVERS}}" ]
                then
                        RUNDIFF=true
                        RunDiff $OLDVERS $NEWVERS "${DFILES[@]}"
                fi
        fi
        OLDVERS=$NEWVERS
done

Called with no args, this will start from the beginning of the repo history, otherwise it will start with whatever abbreviated commit hash you provide and proceed to the present - you can ctrl-C at any time to exit. Any args after the first will limit the difference reports to include only the files listed among those args (which I think is what the OP wanted, and I'd recommend for all but tiny projects). If you're checking changes to specific files and want to start from the beginning, you'll need to provide an empty string for arg1. If you're not a vim user, you can replace vimdiff with your favorite diff tool.

Behavior is to output the commit comments when relevant changes are found and start offering vimdiff runs for each changed file (that's git difftool behavior, but it works here).

This approach is probably pretty naive, but looking through a lot of the solutions here and at a related post, many involved installing new tools on a system where I don't have admin access, with interfaces that had their own learning curve. The above script did what I wanted without dealing with any of that. I'll look into the many excellent suggestions here when I need something more sophisticated - but I think this is directly responsive to the OP.

oracleif
  • 21
  • 5