使用 Git 版本控制查看文件的更改历史记录

Posted

技术标签:

【中文标题】使用 Git 版本控制查看文件的更改历史记录【英文标题】:View the change history of a file using Git versioning 【发布时间】:2010-09-21 15:33:07 【问题描述】:

如何在 Git 中查看单个文件的更改历史,以及更改内容的完整详细信息?

我已经做到了:

git log -- [filename]

这向我显示了文件的提交历史,但我如何获得每个文件更改的内容?

我正在尝试从 Microsoft Visual SourceSafe 进行转换,这曾经是一个简单的右键单击 → 显示历史记录

【问题讨论】:

上面的链接(由 Chris 发布)不再有效。此链接今天有效:git-scm.com/book/en/v2 @chris:你说的链接是什么?在一些现已删除的评论中? 【参考方案1】:

如果您使用的是Git GUI(在 Windows 上):

在 Repository 菜单下,您可以使用“Visualize master's History”。突出显示顶部窗格中的提交和右下角的文件,您将在左下角看到该提交的差异。

【讨论】:

这如何回答这个问题? 好吧,OP 没有指定命令行,并且从 SourceSafe(它是一个 GUI)移动它似乎很重要,指出您可以做与在 VSS 中可以做的几乎相同的事情Windows 上的 Git GUI。【参考方案2】:

你可以使用

git log -p filename

让 Git 为每个日志条目生成补丁。

git help log

更多选项 - 它实际上可以做很多好事 :) 要获得特定提交的差异,您可以

git show HEAD

或任何其他通过标识符进行的修订。或者使用

gitk

直观地浏览更改。

【讨论】:

git show HEAD 显示所有文件,你知道如何跟踪单个文件(正如 Richard 所要求的)? 你使用: git show -- 文件名,如果存在的话,它将显示该版本的差异。 --stat 也很有帮助。你可以和-p一起使用。 这很棒。 gitk 在指定不再存在的路径时表现不佳。我使用了 git log -p --path 。 加上 gitk 看起来像是由布吉怪物建造的。这是一个很好的答案,最适合原始问题。【参考方案3】:

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

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

【讨论】:

"鼓励新用户改用 git-log。(...) 保留该命令主要是出于历史原因;"【参考方案4】:

对于图形视图,我会使用gitk

gitk [filename]

或跟随文件名过去重命名:

gitk --follow [filename]

【讨论】:

但我什至有一个工具将上述内容与“git blame”结合起来,让我可以浏览文件的源代码,因为它会随着时间的推移而变化...... 不幸的是,这不遵循文件过去重命名的历史。 我也在寻找以前重命名的文件的历史,并首先找到了这个线程。解决方案是使用“git log --follow ”,正如菲尔指出的here。 作者正在寻找一个命令行工具。虽然 gitk 是 GIT 自带的,但它既不是命令行应用程序,也不是特别好的 GUI。 他在寻找命令行工具吗? “右键单击 -> 显示历史记录”当然并不意味着它。【参考方案5】:

要显示上次修改文件每一行的版本和作者:

git blame filename

或者如果你想使用强大的责备GUI:

git gui blame filename

【讨论】:

blame 命令不显示有关已删除代码的信息。通过 gitk 或 tig 查看每个提交表明。【参考方案6】:

或者:

gitx -- <path/to/filename>

如果您使用的是gitx

【讨论】:

由于某种原因,我的 gitx 打开空白。 @IgorGanapolsky 你必须确保你在你的 git 存储库的根目录【参考方案7】:

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

这将显示文件的整个历史记录(包括重命名后的历史记录以及每次更改的差异)。

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

【讨论】:

--stat 也很有帮助。你可以和-p一起使用。 我同意这是真正的答案。 (1.) --follow 确保您看到文件重命名 (2.) -p 确保您看到文件如何更改 (3.) 它只是命令行。 @NHDaly 我注意到 -- 已添加,但我不知道为什么这样做最好?它的作用是什么? @Benjohn -- 选项告诉 Git 它已经到达选项的末尾,-- 后面的任何内容都应该被视为一个参数。对于git log,只有当您的路径名以破折号 开头时,这才有意义。假设您想知道名称为“--follow”的文件的历史记录:git log --follow -p -- --follow @Benjohn:通常,-- 很有用,因为它还可以防止任何与您输入的文件名匹配的revision 名称,这实际上可能很可怕。例如:如果你有一个分支和一个名为 foo 的文件,git log -p foo 将显示 git 日志历史记录到 foo,而不是 file foo 的历史记录。但是@DanMoulding 是对的,因为--follow 命令只接受一个文件名作为它的参数,所以这是没有必要的,因为它不能是revision。我刚刚学到了。也许您当时将其排除在答案之外是对的;我不确定。【参考方案8】:

我正在寻找的答案不在这里。这是为了查看我为提交暂存的文件中的更改。即,

git diff --cached

【讨论】:

如果你想包含本地(未暂存的)更改,我经常运行git diff origin/master 来显示本地分支和主分支之间的完全差异(可以通过git fetch 从远程更新) 【参考方案9】:

如果您更喜欢基于文本,您可能需要使用 tig

快速安装:

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

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

或浏览详细的仓库历史记录:tig

它类似于gitk,但基于文本。它支持终端中的颜色!

【讨论】:

优秀的基于文本的工具,很好的答案。当我看到在我的无头服务器上安装 gitk 的依赖项时,我吓坏了。会再次投票 A+++ 您也可以使用 tig 查看特定文件,即tig -- path/to/specific/file【参考方案10】:

如果您想查看文件的全部历史记录,包括 所有其他 分支使用:

gitk --all <filename>

【讨论】:

【参考方案11】:

我为此写了git-playback

pip install git-playback
git playback [filename]

这样做的好处是既可以在命令行中显示结果(例如 git log -p),又可以让您使用箭头键逐步完成每个提交(例如 gitk)。

【讨论】:

【参考方案12】:

使用出色的Git Extensions,您可以转到历史记录中仍然存在的文件(如果已删除,否则只需转到HEAD),切换到File tree选项卡,右键单击文件并选择File history

默认情况下,它通过重命名跟随文件,Blame 选项卡允许查看给定版本的名称。

它有一些小问题,例如在单击删除修订时在View 选项卡中显示fatal: Not a valid object name,但我可以接受。 :-)

【讨论】:

值得注意的是,这仅适用于 Windows。 @EvanHahn 不准确,通过单声道也可以在 Linux 上使用 GitExtension,我们在 ubuntu 上使用它并且非常满意。见git-extensions-documentation.readthedocs.org/en/latest/…【参考方案13】:

通读并玩了一下其他答案的总结:

通常的命令行命令是

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 中所有内容的集中历史记录。

【讨论】:

我认为这是一个很好的答案。也许您也没有获得投票,因为您回答了其他方式(恕我直言,更好)来查看更改,即除了 git 之外,还通过 gitk 和 tig。 只是为了添加答案。找到路径(在 git 空间中,直到它仍然存在于存储库中)。然后使用上述命令“git log --follow --all -p ”。可能存在这种情况,该文件/文件夹将在历史记录中被删除,因此找到仍然存在的最大路径,并尝试获取其历史记录。有效! --all 适用于所有分支,其余部分在@Dan 的回答中解释 哦,伙计,经过这么长时间寻找超越重命名跟踪文件的好解决方案,终于,我在这里找到了它。像魅力一样工作!谢谢!【参考方案14】:

如果您将 Eclipse 与 Git 插件一起使用,它具有与历史记录的出色比较视图。右键单击文件并选择“比较”→“历史记录”。

【讨论】:

然而,这不会让您找到已删除的文件。 比较一个文件的两个版本不同于查看一个文件的更改历史【参考方案15】:

git diff -U &lt;filename&gt; 给你一个统一的差异。

它应该用红色和绿色着色。如果不是,请先运行:git config color.ui auto

【讨论】:

【参考方案16】:

将此别名添加到您的 .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”是错误的。 也可以使用git lg -p filename - 它返回搜索文件的漂亮差异。【参考方案17】:

Sourcetree 用户

如果您使用 Sourcetree 来可视化您的存储库(它是免费的并且非常好),您可以右键单击一个文件并选择 Log Selected

显示(下图)比gitk 和列出的大多数其他选项更友好。不幸的是(目前)没有简单的方法从命令行启动这个视图——Sourcetree 的 CLI 目前只是打开存储库。

【讨论】:

我特别喜欢“关注重命名的文件”选项,它可以让您查看文件是否被重命名或移动。 但除非我弄错了(请告诉我!),在 gui 中一次只能比较两个版本?是否有任何客户端具有优雅的界面,可以同时区分多个不同的版本?可能有像 Sublime Text 那样的缩小视图?我认为这将非常有用。 @SamLewallen 如果我理解正确,您想比较三个不同的提交?这听起来类似于三向合并(我的、你的、基础的)——通常这种策略用于解决合并冲突,不一定要比较三个任意提交。有许多工具支持三向合并***.com/questions/10998728/…,但诀窍是为这些工具提供特定修订版gitready.com/intermediate/2009/02/27/… 谢谢马克福克斯,这就是我的意思。你碰巧知道有什么应用可以做到这一点吗? @MarnenLaibow-Koser 我不记得当时为什么需要 SHA。啊哈哈。【参考方案18】:

如果您使用 TortoiseGit,您应该能够右键单击该文件并执行 TortoiseGit --&gt; Show Log。在弹出的窗口中,确保:

'Show Whole Project'选项未选中。

'All Branches'选项被选中。

【讨论】:

TortoiseGit(以及 Eclipse Git)不知何故错过了所选文件的修订版,不要指望它! @NoamManos,我没有遇到过这个问题,所以我无法验证您的说法是否正确。 我的错误,它只发生在 Eclipse 中,但在 TortoiseGit 中,如果取消选中“显示所有项目”+选中“所有分支”(如果文件提交到另一个分支,在它合并到主分支之前)。我会更新你的答案。【参考方案19】:

您也可以试试这个,它列出了更改文件特定部分的提交(在 Git 1.8.4 中实现)。

返回的结果将是修改此特定部分的提交列表。命令:

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

其中upperLimit 是文件的起始行号,lowerLimit 是文件的结束行号。

更多详情请访问https://web.archive.org/web/20210120153550/http://techpurohit.com/list-some-useful-git-commands

【讨论】:

链接已损坏 - 域techpurohit.com不再存在。 @PeterMortensen 您好,该链接已替换为存档链接。【参考方案20】:

最近我发现了tig,发现它非常有用。在某些情况下,我希望它是 A 或 B,但大多数时候它相当整洁。

对于您的情况,tig &lt;filename&gt; 可能就是您要查找的内容。

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

【讨论】:

【参考方案21】:

SmartGit:

    在菜单中启用以显示未更改的文件:查看/显示未更改的文件 右键单击文件并选择“日志”或按“Ctrl-L”

【讨论】:

【参考方案22】:

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

安装好GitLens后,进入GitLens标签,选择FILE HISTORY即可浏览。

【讨论】:

【参考方案23】:

我可能是关于 OP 开始时的位置,正在寻找一些简单的东西,让我可以使用 git difftoolvimdiff 来查看对我的文件的更改从特定提交开始的回购。我对找到的答案不太满意,所以我把这个 git incremental reporter (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 用户,您可以将 vimdiff 替换为您最喜欢的 diff 工具。

行为是在找到相关更改时输出提交 cmets 并开始为每个更改的文件提供 vimdiff 运行(这是 git difftool 行为,但它在这里有效)。

这种方法可能非常幼稚,但是在这里和相关帖子中查看了很多解决方案,其中许多涉及在我没有管理员访问权限的系统上安装新工具,并且界面有自己的学习曲线.上面的脚本做了我想要的,没有处理任何这些。当我需要更复杂的东西时,我会在这里查看许多优秀的建议 - 但我认为这是直接响应 OP。

【讨论】:

【参考方案24】:

在Sourcetree UI 中,您可以通过在右键单击上下文菜单中选择“Log Selected”选项来查找文件的历史记录:

它将显示所有提交的历史记录。

【讨论】:

这个 GUI 是从哪里来的? Sourcetree UI。谢谢 什么是窗口? @Emobe:你什么意思?你能详细说明吗? (截图似乎来自微软Windows。)

以上是关于使用 Git 版本控制查看文件的更改历史记录的主要内容,如果未能解决你的问题,请参考以下文章

Git简单使用

Git详解

git操作

Git——版本控制器概述

版本控制的介绍以及Git和SVN的区别

Git - 如何查看方法/函数的更改历史记录?