View the change history of a file using Git versioning

GitGit Log

Git Problem Overview


How can I view the change history of an individual file in Git, complete details with what has changed?

I have got as far as:

git log -- [filename]

which shows me the commit history of the file, but how do I get at the content of each of the file changes?

I'm trying to make the transition from Microsoft Visual SourceSafe and that used to be a simple right-click → Show history.

Git Solutions


Solution 1 - Git

For a graphical view I'd use gitk:

gitk [filename]

Or to follow filename past renames:

gitk --follow [filename]

Solution 2 - Git

You can use

git log -p -- filename

to let Git generate the patches for each log entry.

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 you can

git show HEAD

or any other revision by identifier. Or use

gitk

to browse the changes visually.

Solution 3 - Git

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.

Solution 4 - Git

If you prefer to stay text-based, you may want to use tig.

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: tig

It is similar to gitk, but text-based. It supports colors in the terminal!

Solution 5 - Git

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 who's fault it was).

Solution 6 - Git

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

Solution 7 - Git

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

Solution 8 - Git

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.

Solution 9 - Git

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

Solution 10 - Git

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.

Solution 11 - Git

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/

Solution 12 - Git

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.

Solution 13 - Git

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).

Solution 14 - Git

Or:

gitx -- <path/to/filename>

if you're using gitx

Solution 15 - Git

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.

Solution 16 - Git

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

gitk --all <filename>

Solution 17 - Git

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.

Solution 18 - Git

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. :-)

Solution 19 - Git

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'

Solution 20 - Git

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

Solution 21 - Git

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.

Solution 22 - Git

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.

Solution 23 - Git

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".

Solution 24 - Git

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.

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
QuestionRichardView Question on Stackoverflow
Solution 1 - GitClaudio AcciaresiView Answer on Stackoverflow
Solution 2 - GitVolkAView Answer on Stackoverflow
Solution 3 - GitDan MouldingView Answer on Stackoverflow
Solution 4 - GitFalkenView Answer on Stackoverflow
Solution 5 - GitfarktronixView Answer on Stackoverflow
Solution 6 - GitMark FoxView Answer on Stackoverflow
Solution 7 - GityllohyView Answer on Stackoverflow
Solution 8 - GitJohn Lawrence AspdenView Answer on Stackoverflow
Solution 9 - GitfoxirisView Answer on Stackoverflow
Solution 10 - GitPaleszView Answer on Stackoverflow
Solution 11 - Gitlang2View Answer on Stackoverflow
Solution 12 - GitjitendrapurohitView Answer on Stackoverflow
Solution 13 - GitJianView Answer on Stackoverflow
Solution 14 - GitGeorge AndersonView Answer on Stackoverflow
Solution 15 - GitsavvyBrarView Answer on Stackoverflow
Solution 16 - GitAdi ShavitView Answer on Stackoverflow
Solution 17 - GitcoriView Answer on Stackoverflow
Solution 18 - GitPhiLhoView Answer on Stackoverflow
Solution 19 - GitAntonín SlejškaView Answer on Stackoverflow
Solution 20 - GitMalksView Answer on Stackoverflow
Solution 21 - Gituser3885927View Answer on Stackoverflow
Solution 22 - GitLukasz CzerwinskiView Answer on Stackoverflow
Solution 23 - GitAhHatemView Answer on Stackoverflow
Solution 24 - GitoracleifView Answer on Stackoverflow