如何查看单个文件的历史记录以及更改内容的完整详细信息?
git log -- [filename]
向我显示文件的提交历史记录,但如何查看更改的文件内容?
这让 Git 可以为每个日志条目生成补丁:
git log -p -- filename
有关更多选项,请参阅 git help log
— 它实际上可以做很多好事。 :)
要获取特定提交的差异,请使用
git show HEAD
或通过标识符指定任何其他修订。
要直观地浏览更改:
gitk
对于图形视图,请使用 gitk
:
gitk [filename]
要跨文件重命名跟踪文件:
gitk --follow [filename]
git log --follow -p -- path-to-file
这将显示文件的整个历史记录(包括重命名之外的历史记录以及每次更改的差异)。
换句话说,如果名为 bar
的文件曾经被命名为 foo
,那么 git log -p bar
(没有 --follow
选项)将只显示文件的历史记录,直到它被重命名 - 它不会显示文件被称为 foo
时的历史记录。使用 git log --follow -p bar
将显示文件的整个历史记录,包括在文件被称为 foo
时对文件所做的任何更改。 -p
选项确保每次更改都包含差异。
--follow
确保您看到文件重命名 (2.) -p
确保您看到文件如何更改 (3.) 它只是命令行。
--
,但我不知道为什么这样做最好?它是做什么的?
--
选项告诉 Git 它已到达选项的末尾,并且 --
后面的任何内容都应视为参数。对于 git log
,只有当您的路径名以 破折号 开头时,这才有意义。假设您想知道名称为“--follow”的文件的历史记录:git log --follow -p -- --follow
--
很有用,因为它还可以防止任何与您输入的文件名匹配的 revision
名称,这实际上可能很可怕。例如:如果您有一个名为 foo
的分支和一个文件,则 git log -p foo
将显示 git log 历史记录到 foo
,而不是 file foo
的历史记录。但是@DanMoulding 是正确的,因为 --follow
命令仅将单个文件名作为其参数,因此这不是必需的,因为它不能是 revision
。我刚刚学到了。也许您当时将其排除在答案之外是对的;我不确定。
tig
是基于终端的查看器,其颜色支持类似于基于 GUI 的 gitk
。
快速安装:
APT:apt-get 安装 tig
Homebrew (OS X): $ brew install tig
使用它来查看单个文件的历史记录:tig [filename]
或通过以下方式浏览详细的存储库历史记录:tig
tig -- path/to/specific/file
tig --follow filename
。非常感谢@falken 帮助我们发现了如此出色的 TUI 工具。
在这种情况下,git whatchanged -p filename
也等同于 git log -p filename
。
您还可以使用 git blame filename
查看文件中的特定代码行何时更改。这将为文件中的每一行打印出一个简短的提交 ID、作者、时间戳和完整的代码行。在您发现错误并且想知道它是什么时候引入的(或者是谁的错)之后,这非常有用。
源树用户
如果您使用 Sourcetree 来可视化您的存储库(它是免费的并且非常好),您可以右键单击一个文件并选择 Log Selected
https://i.stack.imgur.com/CHvfE.png
显示(下图)比 gitk 和列出的大多数其他选项更友好。不幸的是(此时)没有简单的方法可以从命令行启动这个视图——Sourcetree 的 CLI 目前只是打开存储库。
https://i.stack.imgur.com/Y9ALz.png
gitk
找到 SHA1
哈希,然后根据找到的 SHA1
打开 SourceTree
输入 Log Selected..
。
要显示上次修改文件每一行的版本和作者:
git blame filename
或者如果你想使用强大的责备 GUI:
git gui blame filename
阅读并玩了一下其他答案的摘要:
通常的命令行命令是
git log --follow --all -p dir/file.c
但您也可以使用 gitk (GUI) 或 tig (文本 UI) 来提供更易于阅读的方式来查看它。
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
中所有内容的集中历史记录。
--all
适用于所有分支,其余部分在@Dan 的答案中进行了解释
您可以将 Visual Studio Code 与 GitLens 一起使用。这是一个非常强大的工具。
安装好 GitLens 后,进入 GitLens 标签页,选择 FILE HISTORY
即可浏览。
https://i.stack.imgur.com/H0j9A.png
将此别名添加到您的 .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 输出几乎完全相同。享受。
git lg -p filename
- 它返回搜索文件的漂亮差异。
最近我发现了 tig
,发现它非常有用。在某些情况下,我希望它是 A 或 B,但大多数时候它相当整洁。
对于您的情况,tig <filename>
可能就是您要查找的内容。
你也可以试试这个,它列出了更改文件特定部分的提交(在 Git 1.8.4 中实现)。
返回的结果将是修改此特定部分的提交列表。命令:
git log --pretty=short -u -L <upperLimit>,<lowerLimit>:<path_to_filename>
其中,upperLimit 是起始行号,lowerLimit 是文件的结束行号。
http://techpurohit.in/list-some-useful-git-commands 上有更多详细信息。
techpurohit.com
不再存在。
我为此写了 git-playback
pip install git-playback
git playback [filename]
这样做的好处是既可以在命令行中显示结果(例如 git log -p
),又可以让您使用箭头键逐步完成每个提交(例如 gitk
)。
在 Sourcetree UI 中,您可以通过在右键单击上下文菜单中选择“Log Selected”选项来查找文件的历史记录:
https://i.stack.imgur.com/uxBTn.png
它将显示所有提交的历史记录。
如果您想查看文件的整个历史记录,包括所有其他分支,请使用:
gitk --all <filename>
如果您使用的是 Git GUI(在 Windows 上):
在 Repository 菜单下,您可以使用“Visualize master's History”。突出显示顶部窗格中的提交和右下角的文件,您将在左下角看到该提交的差异。
使用出色的 Git Extensions,您可以转到文件仍然存在的历史记录中的某个点(如果它已被删除,否则只需转到 HEAD),切换到 File tree
选项卡,右键单击文件并选择File history
。
默认情况下,它通过重命名跟随文件,并且 Blame
选项卡允许查看给定修订的名称。
它有一些小问题,例如单击删除修订时在 View
选项卡中显示 fatal: Not a valid object name
,但我可以接受。 :-)
如果您使用 TortoiseGit,您应该能够右键单击该文件并执行 TortoiseGit --> Show Log
。在弹出的窗口中,确保:
未选中“显示整个项目”选项。
选中“所有分支”选项。
我要找的答案不在这里。这是为了查看我为提交暂存的文件中的更改。 IE,
git diff --cached
git diff origin/master
以显示您的本地分支和主分支之间的完全差异(可以通过 git fetch
从远程更新)
git diff -U <filename>
为您提供统一的差异。
它应该用红色和绿色着色。如果不是,请先运行:git config color.ui auto
。
如果您将 Eclipse 与 Git 插件一起使用,它具有与历史记录的出色比较视图。右键单击文件并选择“比较”→“历史记录”。
我可能是关于 OP 开始时的位置,寻找一些简单的东西,让我可以使用 git difftool 和 vimdiff 来查看从特定提交开始对我的 repo 中文件的更改。我对找到的答案不太满意,所以我把这个 git 增量报告器 (gitincrep) 脚本放在一起,它对我很有用:
#!/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
不带参数调用,这将从回购历史的开头开始,否则它将以您提供的任何缩写提交哈希开始并继续到现在 - 您可以随时 ctrl-C 退出。第一个之后的任何参数都将限制差异报告以仅包含这些参数中列出的文件(我认为这是 OP 想要的,我建议除了小型项目之外的所有项目)。如果您要检查对特定文件的更改并希望从头开始,则需要为 arg1 提供一个空字符串。如果你不是 vim 用户,你可以用你最喜欢的 diff 工具替换 vimdiff。
行为是在找到相关更改时输出提交注释并开始为每个更改的文件提供 vimdiff 运行(这是 git difftool 行为,但它在这里有效)。
这种方法可能非常幼稚,但是在这里和相关帖子中查看了很多解决方案,其中许多涉及在我没有管理员访问权限的系统上安装新工具,并且界面有自己的学习曲线。上面的脚本做了我想要的,没有处理任何这些。当我需要更复杂的东西时,我会在这里研究许多优秀的建议——但我认为这直接响应了 OP。