使用 Git 版本控制查看文件的修改历史

3828

如何查看文件的完整变更历史记录以及具体修改内容?

git log -- [filename] 命令可以显示文件的提交历史,但如何查看文件的修改内容呢?


6
上面的链接(由Chris发布)已经失效。今天这个链接有效:https://git-scm.com/book/en/v2 - Cog
2
@chris:你所说的链接是什么?是在现已删除的评论中吗? - Peter Mortensen
27个回答

2926
这样可以让Git为每个日志条目生成补丁:
git log -p -- filename

查看更多选项,请参阅git help log — 它实际上可以做很多好玩的事情。 :)
要仅获取特定提交的差异,请使用以下命令:
git show HEAD

或者通过标识符指定任何其他修订。
浏览变更的方式有两种:视觉浏览和文本浏览。视觉浏览可以让您直观地查看变更的内容和布局。
gitk

10
你知道如何追踪一个单独的文件吗(就像Richard所问的那样)?git show HEAD会显示所有文件。 - Jonas Byström
6
你可以使用命令:git show <revision> -- filename,来查看该版本的差异,如果存在的话。 - Marcos Oliveira
4
-stat 也很有用。你可以和 -p 一起使用。 - khatchad
5
太好了。当指定的路径不存在时,gitk 的行为表现不佳。我使用了 git log -p -- path 命令。 - Paulo Casaretto
7
加上gitk看起来像是由boogie怪物建造的。这是一个很好的答案,并且最适合原始问题。 - hayesgm
显示剩余6条评论

2697

要查看图形化视图,请使用gitk

gitk [filename]
跟随文件重命名后的文件:
gitk --follow [filename]

36
我更愿意拥有一个结合了上述功能和“git blame”的工具,使我能够随着时间的推移浏览文件源代码的变化。 - Egon Willighagen
29
很遗憾,这并没有遵循文件在重命名之前的历史记录。 - Dan Moulding
156
我也在寻找之前重命名的文件的历史记录,并首先找到了这个主题。解决方法是使用“git log --follow <filename>”,正如Phil在这里所指出的那样。 - Florian Gutmann
131
作者正在寻找一种命令行工具。虽然 Git 自带 gitk,但它既不是命令行程序,也不是特别好的 GUI。 - mikemaccana
79
他是否在寻找一个命令行工具?“右键单击->显示历史记录”显然并没有暗示这一点。 - hdgarrood
显示剩余21条评论

1770
git log --follow -p -- path-to-file

这将展示文件的完整历史记录(包括重命名之后的历史和每个更改的差异)。

换句话说,如果名为bar的文件曾经被命名为foo,那么git log -p bar(不带--follow选项)只会显示文件的历史记录到它被重命名的那个时间点为止 -- 它不会显示文件作为foo时的历史记录。使用git log --follow -p bar将显示文件的完整历史记录,包括文件作为foo时的任何更改。 -p选项确保每个更改的差异都被包含在内。


23
-stat也很有用,你可以和-p一起使用。 - khatchad
34
我同意这是真正的答案。(1.) --follow 确保你能看到文件重命名 (2.) -p 确保你能看到文件如何被更改 (3.) 这只能在命令行中运行。 - Trevor Boyd Smith
5
我注意到--被添加了,但我不知道这为什么会使它更好?它有什么作用? - Benjohn
54
“--”选项告诉Git它已经到达了选项的结尾,接下来的任何内容都应该被视为参数。对于git log命令而言,只有当您有一个以破折号开头的路径名称时,这才有所区别。假设您想要查看文件“--follow”的历史记录:git log --follow -p -- --follow - Dan Moulding
11
通常情况下,-- 是有用的,因为它还可以防止与您输入的文件名相匹配的任何 revision 名称,这可能会令人感到恐慌。例如:如果您同时拥有一个名为 foo 的分支和文件,则 git log -p foo 将显示直到 foo 的 git 日志历史记录,而不是文件 foo 的历史记录。但是 @DanMoulding 是正确的,因为 --follow 命令只需要单个文件名作为其参数,所以这种情况就不那么必要了,因为它不能是一个 revision。我刚学到这一点。也许您在回答中将其省略是正确的,我不确定。 - NHDaly
显示剩余9条评论

208

tig是一个基于终端的查看器,支持颜色显示,类似于基于图形用户界面的gitk

快速安装方法:

  • APTapt-get install tig
  • Homebrew (OS X)$ brew install tig

使用它来查看单个文件的历史:tig [filename]

或者通过tig浏览详细的仓库历史记录。


29
优秀的基于文本的工具,答案精彩。当我看到在我的无头服务器上安装gitk的依赖时,我感到非常慌张。会再次点赞A+++。 - Tom McKenzie
1
您可以使用tig查看特定文件,例如:tig -- path/to/specific/file - gloriphobia
要显示文件的所有更改,包括重命名,请使用“tig --follow 文件名”。非常感谢@falken帮助我们发现这样一个精彩的TUI工具。 - GMaster

131

git whatchanged -p filename 在这种情况下也等同于 git log -p filename

你还可以使用 git blame filename 查看文件中特定代码行的更改时间。对于文件中的每一行,它会打印出一个短的提交 ID、作者、时间戳和完整的代码行。当你发现一个 bug 并想知道是什么时候引入的(或者是谁的错)时,这非常有用。


16
鼓励新用户使用git-log命令,此命令被保留主要是出于历史原因。 - ciastek

124

Sourcetree用户

如果您使用Sourcetree来可视化您的代码库(它是免费且相当不错的),您可以右键单击文件并选择Log Selected

在此输入图片描述

显示结果(如下所示)比gitk和其他大多数选项更加友好。不幸的是,目前没有简单的方法从命令行启动此视图。Sourcetree的CLI目前只打开代码库。

在此输入图片描述


1
我特别喜欢“跟踪重命名的文件”选项,它可以让你看到文件是否被重命名或移动了。 - Chris
除非我理解错了(请告诉我!),否则在GUI中一次只能比较两个版本?有没有任何客户端可以同时为多个不同版本提供优雅的界面进行差异比较? 可以像Sublime Text中的缩小视图一样吗?我认为那会非常有用。 - Sam Lewallen
@SamLewallen 如果我理解正确,您想比较三个不同的提交?这听起来类似于三方合并(我的,你的,基础)-通常此策略用于解决合并冲突,而不一定是比较三个任意提交。有许多工具支持三方合并https://dev59.com/yWgu5IYBdhLWcg3w5K9a,但诀窍是向这些工具提供特定的修订版本http://gitready.com/intermediate/2009/02/27/get-a-file-from-a-specific-revision.html - Mark Fox
你救了我的命。你可以使用 gitk 查找 SHA1 哈希值,然后打开 SourceTree 根据找到的 SHA1 输入 Log Selected.. - AechoLiu
1
@MarnenLaibow-Koser 我不记得当时为什么需要SHA了。哈哈。 - AechoLiu
显示剩余3条评论

75

显示文件每行的修订版本和最后修改者:

git blame filename

或者如果您想使用强大的责备图形界面:

git gui blame filename

1
责备命令不会显示有关已删除代码的信息。通过gitk或tig查看每个提交可以看到这一点。 - vezun

67

在阅读其他答案和尝试了一些操作后,以下是它们的总结:

通常的命令行命令应该是:

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

但你也可以使用 gitk(图形用户界面)或 tig(文本用户界面)以更加易读的方式查看它。

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

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

Debian/Ubuntu 系统下,这些优秀工具的安装命令如预期的一样:

sudo apt-get install gitk tig

我目前正在使用:

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

这样我只需键入gdf dir,就可以获得子目录dir中所有内容的重点历史记录。


2
我认为这是一个很好的答案。也许你没有得到更多的投票,是因为你回答了其他方式(在我看来更好),比如通过gitk和tig来查看变化,而不仅仅是使用git。 - PopcornKing
只是为了补充答案。找到路径(在git空间中,直到仓库中仍存在的路径)。然后使用上面提到的命令“git log --follow --all -p <folder_path/file_path>”。可能会出现这种情况,文件/文件夹在历史记录中已被删除,因此请找到仍然存在的最大路径,并尝试获取其历史记录。有效! - parasrish
3
--all 表示所有分支,其余内容详见 @Dan 的回答。 - cregox
1
哦,老兄,经过漫长的时间寻找跟踪文件重命名以外的好方法,终于,在这里找到了。运行得非常好!谢谢! - xZero

31

你可以使用 Visual Studio Code 与 GitLens。这是一个非常强大的工具。

安装完 GitLens 后,进入 GitLens 标签,选择 FILE HISTORY,就可以浏览它了。

输入图片描述


或者 donjayamanne.githistory - Felix F Xu

29

将此别名添加到您的.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

然后像这样使用命令:

> git lg
> git lg -- filename

输出结果几乎与 gitk 输出相同。享受吧。


在我运行了那个 lg 快捷方式之后,我说(引用):“太棒了!”但是请注意,“--graph”后面的“\n”是一个错误。 - jmbeck
3
还可以使用 git lg -p filename 命令,它会返回所搜索的文件的漂亮差异。 - Egel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接