How can I show the complete history of a single file in Git? When I use git log <filename>
or gitk <filename>
, I only get merges. I want to see the commits from the merged branches that affect the file. I've tried --follow
and other flags and can't find a way.

- 13,807
- 9
- 40
- 57

- 864
- 9
- 21
-
1Does `git log --all --full-history -- path/to/file` do it for you? – jthill Jul 22 '14 at 01:15
-
No, it just shows even more merges... – Juliana Peña Jul 22 '14 at 01:34
-
1mmm. add `--no-merges` to see if there's anything valuable hiding in the chaff. – jthill Jul 22 '14 at 01:51
-
I found out the problem! The merge was actually a subtree merge, so the history was showing the add only. Detailed answer here: http://stackoverflow.com/questions/10918244/git-subtree-without-squash-view-log – Juliana Peña Jul 22 '14 at 05:57
2 Answers
TL;DR summary: --all
First, let me tackle one general item that applies to many git commands.
git log
looks at the revision(s) you specify, using git rev-list
to handle them. The reason you normally see many commits is that git rev-list
"walks history", unless told not to:
$ git rev-list --no-walk HEAD
d1574b852963482d4b482992ad6343691082412f
$ git rev-list HEAD
d1574b852963482d4b482992ad6343691082412f
b9491ea160d12ddfd69a9ddc79ebd264cda20679
676699a0e0cdfd97521f3524c763222f1c30a094
[snip]
However, the revisions visited by git rev-list
start from the point(s) you specify (with default = HEAD
). So any revisions that are not already part of the point(s) you specified, or its history, are omitted:
C - D <-- branchA
/
A - B - E - F - G <-- branchB
\
H - I - J - M <-- HEAD=branchC
\ /
K - L
In this diagram I've put in three branch names, and shown that HEAD
is branchC
. Each single letter represents a commit (an SHA-1). Any commit's parents are those to the left of it, either directly left or moving up or down along the parent-commit links that go between commits.
At this point, git log
will show you commits M
, L
, K
, J
, I
, H
, B
, and A
, because git log
(and git rev-list
) will start at HEAD
and walk backwards. (The precise order of these commits depends on additional arguments.)
On the other hand, git log branchB
will show you commits G
, F
, E
, B
, and A
, because starting at commit G
and walking backwards selects those commits (and no others). Similarly, git log branchA
starts with D
and walks back to A
.
If you ask git rev-list
to look at --all
, it will start at all references (all branches, all tags, all remote-branches, and all other refs in the refs/
namespace) and walk backwards. In this case, all branches alone suffices to select every commit. In repositories with tags, --branches
might get you less than --all
, since there might be some line(s) that are tagged but not marked with a branch. See the (rather overwhelming) git rev-list
documentation to see all available options here.
Adding a file name to git log
makes it skip the printing of some (many or most) of the commits it visits, through what is described in the documentation as "History Simplification". That is, git log
first selects all the commits selected by your git rev-list
arguments, but then it only shows a smaller number.
Adding --follow
makes git log
attempt to notice cases where a file is renamed across a particular commit, and in those cases, switch selected revisions to those with the previous name once it transitions across such commits in its history-walk. In other words, it tries to adjust the history simplification to correct for name changes. This rename discovery is performed dynamically (re-tested for every pair of commits). It works only when stepping backwards—the code is just not there for handling other commit-orders.
When using git diff
, you have more control over what is recognized as a rename; with git log
's --follow
, you're stuck with the compiled-in default of a 50% match.

- 448,244
- 59
- 642
- 775
-
-
It's possible that the file is only modified in those merges. That would be *rare*, to be sure, but it is possible. (It's not entirely clear what "modified" should mean for a merge, since a merge has multiple parents; `git show` shows combined diffs for merges by default, which show only files modified in both parents. I'm not sure off-hand whether `git log` does the same.) – torek Jul 22 '14 at 01:47
This will show all versions of the file (merges or not):
gitk --all <filename>

- 17,357
- 9
- 82
- 98