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

3828

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

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


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

6
我在这里找不到我要的答案。我希望看到已经暂存用于提交的文件的更改。也就是说,
git diff --cached

1
如果您想包含本地(未暂存)更改,我经常运行 git diff origin/master 来显示本地分支和主分支之间的完整差异(可以通过 git fetch 从远程更新)。 - hayesgm
而要将其限制在特定文件中,您可以使用 git diff --cached path/to/file.xml - Woodchuck

5
如果您使用TortoiseGit,您应该能够右键单击文件并执行“TortoiseGit-->显示日志”。 在弹出的窗口中,请确保:
  • 未选中“显示整个项目”选项。

  • 选中“所有分支”选项。


TortoiseGit(以及Eclipse Git)在某些情况下会错过所选文件的修订版本,不要指望它! - Noam Manos
@NoamManos,我没有遇到过这个问题,所以无法验证你的说法是否正确。 - user3885927
我的错误,这只发生在Eclipse中,但是在TortoiseGit中,如果取消“显示所有项目”并选中“所有分支”,则可以查看文件的所有修订版本(如果文件在合并到主分支之前已提交到另一个分支)。我会更新你的答案。 - Noam Manos

4

git diff -U <filename> 会给你一个统一的差异。

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


4

如何在 meld 中手动以图形方式查看文件的更改历史记录

如果您只想查看哪些提交更改了文件,以便可以对它们执行 git difftool 命令,并使用 meld(如我在这里所解释的) 以图形方式查看更改,请执行以下操作:

git log --follow --oneline -- path/to/file.c

样例运行和输出:

eRCaGuy_hello_world$ git log --follow --oneline -- c/alsa_aplay__play_tone_sound_WIP.c
04b67fb (HEAD -> master) Update c/alsa_aplay__play_tone_sound_WIP.c
301122a wip: alsa_aplay__play_tone_sound.c: finish initial version of program
d4e8092 wip: add c/alsa_aplay__play_tone_sound.c

现在我可以通过 meld 图形化地查看最新的更改情况,就像这样(从上面的输出中提取提交哈希值)。
请注意,我故意省略了文件名,以便它可以自动跟踪文件,因为文件已被重命名,并且我知道这些提交很可能只编辑了这个文件。
# just the last change
git difftool 04b67fb~..04b67fb

# and the one before that
git difftool 301122a~..301122a

# ...and before that
git difftool d4e8092~..d4e8092

如果您需要指定文件名,请使用以下方式:
git difftool 04b67fb~..04b67fb -- path/to/file.c

2
如果您正在使用带有Git插件的Eclipse,它具有出色的历史比较视图。右键单击文件,然后选择“与历史比较”。

这并不能让你找到已删除的文件。 - avgvstvs
比较两个文件版本与查看文件的更改历史是不同的。 - golimar

2
你可以使用以下的git log命令:
git log -L 992,+4:path-to-file

解释: 这里的992表示您想要查看修订信息的行号, +4表示您想要在指定行992之后看到多少行。 最后是文件路径,通常以./src/..开头。

1

我大概和这个问题的提出者一样,正在寻找一个简单的方法,让我可以使用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工具。
行为是在找到相关更改时输出提交注释并开始为每个更改的文件提供vimdiff运行(这是git difftool的行为,但它在这里起作用)。
这种方法可能相当幼稚,但是浏览了许多解决方案以及相关帖子后,许多解决方案涉及在我没有管理访问权限的系统上安装新工具,这些工具有自己的学习曲线。以上脚本可以在不处理任何内容的情况下完成我想要的工作。当我需要更复杂的东西时,我会研究这里的许多优秀建议 - 但我认为这直接响应了OP。

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